Current GLFW has the function glfwSetClipboardText() and glfwGetClipboardText(), but the underlying system clipboard APIs are significantly more powerful:
They allow you to offer multiple different formats of the data, e.g. text, image, binary blob.
They allow you to defer the encoding of this data until it is actually requested by another application (when the user tries to paste in another application).
We could add support for this by expanding the API. I am happy to work on this, but would like some feedback first. Here is my proposed API.
Clipboard Offer Objects
We could have an opaque structure GLFWcboffer, which is used to define offers to the clipboard. We would create it with a user-defined data pointer, and a "cancel" callback.
The cancel callback is invoked when the app loses ownership of the clipboard (another app inserted something into it).
Offering different types
On some platforms like Windows, there are some standard predefined types such as "text" and "bitmap", whereas on other platforms there are no predefined types and we provide the MIME type of the data instead. To make the API generic, we need special handling for those predefined types, as well the ability to add custom types. In each case, we pass a "send" callback function, which will be called to provide the data when it is needed. For strings we can have this:
GLFWstringsendfun could return a heap-allocated UTF-8 string, which GLFW will then free(). On Windows this would encode the string into UTF-16 (as glfwSetClipboardString() already does) and add it to the clipboard as CF_UNICODETEXT, whereas on Wayland it would offer it as text/plain;charset=utf-8 (again, as the existing API already does). The main difference would be that it is deferred.
We could have a similar API for offering images, but I haven't looked into it yet (there is no API for storing images in the clipboard yet, but some people have proposed them).
We could have a generic "binary blob" API as well, which could look like this:
The callback would set *outptr to point to a heap-allocated buffer with arbitrary binary data, and *outsize to its size in bytes. GLFW would free the buffer. mimetype would be used to identify the type. On Wayland it would simply pass the MIME type through, on Windows it would call RegisterClipboardFormat() to assign an ID for the mime type and then pass that through.
Acquiring the clipboard
After adding callbacks for one or more types to the offer, a function like this would be used:
This function would take ownership of the offer. When another application tries to paste a specific type, the appropriate "send" callback is invoked. If another application changes the clipboard content, the "cancel" callback will be invoked.
Getting the clipboard data
We could have separate functions for getting clipboard data in various formats. The existing glfwGetClipboardString() could be used to read strings as before. We could add a function for reading binary blobs too:
The returned pointer would be valid until the next call to any of the GetClipboard functions.
Fallback
There is a good fallback mechanism for any backend that cannot support all of the features. For example, if a backend only supports copying strings, then glfwAcquireClipboard() could simply immediately invoke the string send callback, and send over the string.
Example: glfwSetClipboardString
With this API, glfwSetClipboardString() could be reimplemented like this (ignoring error handling):
This is a more efficient way of copying large amount of data, is supported by all major operating systems, and allows other types of data to be sent (such as binary blobs) and not just text. One example of where this would be useful is this PR I've raised against Goxel:
2636 is related; it's a much lower-level solution that puts most of the work on the client, but allows client to implement this functionality for X11 within GLFW.
Current GLFW has the function
glfwSetClipboardText()
andglfwGetClipboardText()
, but the underlying system clipboard APIs are significantly more powerful:We could add support for this by expanding the API. I am happy to work on this, but would like some feedback first. Here is my proposed API.
Clipboard Offer Objects
We could have an opaque structure
GLFWcboffer
, which is used to define offers to the clipboard. We would create it with a user-defined data pointer, and a "cancel" callback.The cancel callback is invoked when the app loses ownership of the clipboard (another app inserted something into it).
Offering different types
On some platforms like Windows, there are some standard predefined types such as "text" and "bitmap", whereas on other platforms there are no predefined types and we provide the MIME type of the data instead. To make the API generic, we need special handling for those predefined types, as well the ability to add custom types. In each case, we pass a "send" callback function, which will be called to provide the data when it is needed. For strings we can have this:
GLFWstringsendfun
could return a heap-allocated UTF-8 string, which GLFW will thenfree()
. On Windows this would encode the string into UTF-16 (asglfwSetClipboardString()
already does) and add it to the clipboard asCF_UNICODETEXT
, whereas on Wayland it would offer it astext/plain;charset=utf-8
(again, as the existing API already does). The main difference would be that it is deferred.We could have a similar API for offering images, but I haven't looked into it yet (there is no API for storing images in the clipboard yet, but some people have proposed them).
We could have a generic "binary blob" API as well, which could look like this:
The callback would set
*outptr
to point to a heap-allocated buffer with arbitrary binary data, and*outsize
to its size in bytes. GLFW would free the buffer.mimetype
would be used to identify the type. On Wayland it would simply pass the MIME type through, on Windows it would callRegisterClipboardFormat()
to assign an ID for the mime type and then pass that through.Acquiring the clipboard
After adding callbacks for one or more types to the offer, a function like this would be used:
This function would take ownership of the
offer
. When another application tries to paste a specific type, the appropriate "send" callback is invoked. If another application changes the clipboard content, the "cancel" callback will be invoked.Getting the clipboard data
We could have separate functions for getting clipboard data in various formats. The existing
glfwGetClipboardString()
could be used to read strings as before. We could add a function for reading binary blobs too:The returned pointer would be valid until the next call to any of the
GetClipboard
functions.Fallback
There is a good fallback mechanism for any backend that cannot support all of the features. For example, if a backend only supports copying strings, then
glfwAcquireClipboard()
could simply immediately invoke the string send callback, and send over the string.Example: glfwSetClipboardString
With this API,
glfwSetClipboardString()
could be reimplemented like this (ignoring error handling):Use cases
This is a more efficient way of copying large amount of data, is supported by all major operating systems, and allows other types of data to be sent (such as binary blobs) and not just text. One example of where this would be useful is this PR I've raised against Goxel:
https://github.com/guillaumechereau/goxel/pull/395
Furthermore, SDL3 has added support for this as well:
https://wiki.libsdl.org/SDL3/SDL_SetClipboardData
Let me know of any comments or suggestions, and I'll be happy to begin implementing this.