You can repro this with clipboard app from tests folder, here's a junk file of 262146 bytes, copy all of it and paste into window, you'll get:
Error: X11: Failed to convert selection to string
Clipboard does not contain a string
GLFW doesn't support incremental clipboard data transfer yet.
Note to self: UTF8_STRING
I've been looking into this myself but I haven't been able to complete the implementation of it. Hopefully some of the experience in trying to implement it might be of use to someone else trying to do the same. In a nutshell, here is what happens and what ICCCM expects us to do to handle this INCR atom:
Below, when calling _glfwPlatformGetClipboardString
is where X11 becomes very sad:
if (_glfwGetWindowPropertyX11(event.xselection.requestor,
event.xselection.property,
event.xselection.target,
(unsigned char**) &data))
_glfw.x11.clipboardString = strdup(data);
And the reason is because we are requesting event.xselection.target
of type UTF8_STRING
, which will work most of the time, except when we have passed the selection owner's maximum allowed single-batch transfer size (262146 bytes in this case). The selection owner will instead give us an actualType
of INCR
which is not the same as the requested type UTF8_STRING
. The owner wants to send data incrementally, i.e. in chunks of several XGetWindowProperty
s containing UTF8_STRING
s.
To solve this we need to follow the ICCCM recommendation "INCR Properties". But in a nutshell:
INCR
-atom with XInternAtom
e.g. with the name INCR_STRING
._glfwGetWindowPropertyX11
if we received actualType
of INCR_STRING
, if so:INCR_STRING
using XGetWindowProperty
, it contains a lower transfer bound.INCR_STRING
property so the owner can start sending us the good stuff.PropertyNotify
event, signaling arrival of a chunk of the full data.XGetWindowProperty
, append it to a buffer.If you are interested, here is a half-done implementation gist of incremental selections that I wrote.
Here are a couple of links that I found useful when looking into the issue:
Hopefully this is to some use to somebody, I wasn't able to figure it out myself unfortunately.
Thank you, that's an an excellent description! It's a little absurd what clients need to do to accomplish things that are a couple of function calls on other platforms.
I started implementing INCR two days ago. I have reading working, as well as conversion from STRING / Latin-1, but had a brief moment of despair when I realized that INCR, MULTIPLE and STRING can combine for writing. Some restructuring is in order before that can be implemented cleanly.
Pushed it just now to the selection-fixes
branch if anyone wants a peek.
I need to focus on pull request reviews for a while. I've kept a lot of fine code waiting for a shameful a amount of time. If anyone wants to continue working on this in the meantime, based on code above or not, please do.
Most helpful comment
I've been looking into this myself but I haven't been able to complete the implementation of it. Hopefully some of the experience in trying to implement it might be of use to someone else trying to do the same. In a nutshell, here is what happens and what ICCCM expects us to do to handle this INCR atom:
Below, when calling
_glfwPlatformGetClipboardString
is where X11 becomes very sad:And the reason is because we are requesting
event.xselection.target
of typeUTF8_STRING
, which will work most of the time, except when we have passed the selection owner's maximum allowed single-batch transfer size (262146 bytes in this case). The selection owner will instead give us anactualType
ofINCR
which is not the same as the requested typeUTF8_STRING
. The owner wants to send data incrementally, i.e. in chunks of severalXGetWindowProperty
s containingUTF8_STRING
s.To solve this we need to follow the ICCCM recommendation "INCR Properties". But in a nutshell:
INCR
-atom withXInternAtom
e.g. with the nameINCR_STRING
._glfwGetWindowPropertyX11
if we receivedactualType
ofINCR_STRING
, if so:a) Fetch
INCR_STRING
usingXGetWindowProperty
, it contains a lower transfer bound.b) Delete this
INCR_STRING
property so the owner can start sending us the good stuff.c) Wait for a
PropertyNotify
event, signaling arrival of a chunk of the full data.d) Retrieve chunk data using
XGetWindowProperty
, append it to a buffer.e) Delete the property, signaling owner to send additional chunks.
f) Check if the size of the data is zero, if not loop back to c.
g) Transfer complete, you now have the entire data!
If you are interested, here is a half-done implementation gist of incremental selections that I wrote.
Here are a couple of links that I found useful when looking into the issue:
Hopefully this is to some use to somebody, I wasn't able to figure it out myself unfortunately.