aboutsummaryrefslogtreecommitdiffstats
path: root/doc/c/clipboards.rst
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2022-05-22 12:24:59 -0400
committerDavid Robillard <d@drobilla.net>2022-05-23 16:50:43 -0400
commit2501218801437ea413091007b535d7c097801713 (patch)
treecf938dd335f8aa9b547b458f97f05e7e18d8b9d3 /doc/c/clipboards.rst
parent0093196a4c624da6d7f78a909a442f2e784c37aa (diff)
downloadpugl-2501218801437ea413091007b535d7c097801713.tar.gz
pugl-2501218801437ea413091007b535d7c097801713.tar.bz2
pugl-2501218801437ea413091007b535d7c097801713.zip
Add rich clipboard support
This implements a more powerful protocol for working with clipboards, which supports datatype negotiation, and fixes various issues by mapping more directly to how things work on X11.
Diffstat (limited to 'doc/c/clipboards.rst')
-rw-r--r--doc/c/clipboards.rst118
1 files changed, 118 insertions, 0 deletions
diff --git a/doc/c/clipboards.rst b/doc/c/clipboards.rst
new file mode 100644
index 0000000..ec66bd5
--- /dev/null
+++ b/doc/c/clipboards.rst
@@ -0,0 +1,118 @@
+.. default-domain:: c
+.. highlight:: c
+
+################
+Using Clipboards
+################
+
+Clipboards provide a way to transfer data between different views,
+including views in different processes.
+A clipboard transfer is a multi-step event-driven process,
+where the sender and receiver can negotiate a mutually supported data format.
+
+*******
+Copying
+*******
+
+Data can be copied to the general clipboard with :func:`puglSetClipboard`.
+The `MIME type <https://www.iana.org/assignments/media-types/media-types.xhtml>`_ of the data must be specified.
+Commonly supported types are ``text/plain`` for plain text,
+and `text/uri-list <http://amundsen.com/hypermedia/urilist/>`_ for lists of URIs (including local files).
+
+For example, a string can be copied to the clipboard by setting the general clipboard to ``text/plain`` data:
+
+.. code-block:: c
+
+ const char* someString = "Copied string";
+
+ puglSetClipboard(view,
+ "text/plain",
+ someString,
+ strlen(someString));
+
+*******
+Pasting
+*******
+
+Data from a clipboard can be pasted to a view using :func:`puglPaste`:
+
+.. code-block:: c
+
+ puglPaste(view);
+
+This initiates a data transfer from the clipboard to the view if possible.
+If data is available,
+the view will be sent a :enumerator:`PUGL_DATA_OFFER` event to begin the transfer.
+
+**************
+Receiving Data
+**************
+
+A data transfer from a clipboard to a view begins with the view receiving a :enumerator:`PUGL_DATA_OFFER` event.
+This indicates that data (possibly in several formats) is being offered to a view,
+which can either "accept" or "reject" it:
+
+.. code-block:: c
+
+ case PUGL_DATA_OFFER:
+ onDataOffer(view, &event->offer);
+ break;
+
+When handling this event,
+:func:`puglGetNumClipboardTypes` and :func:`puglGetClipboardType` can be used to enumerate the available data types:
+
+.. code-block:: c
+
+ static void
+ onDataOffer(PuglView* view, const PuglEventDataOffer* event)
+ {
+ size_t numTypes = puglGetNumClipboardTypes(view, clipboard);
+
+ for (uint32_t t = 0; t < numTypes; ++t) {
+ const char* type = puglGetClipboardType(view, t);
+ printf("Offered type: %s\n", type);
+ }
+ }
+
+If the view supports one of the data types,
+it can accept the offer with :func:`puglAcceptOffer`:
+
+.. code-block:: c
+
+ for (uint32_t t = 0; t < numTypes; ++t) {
+ const char* type = puglGetClipboardType(view, t);
+ if (!strcmp(type, "text/uri-list")) {
+ puglAcceptOffer(view, event, t);
+ }
+ }
+
+When an offer is accepted,
+the data will be transferred and converted if necessary,
+then the view will be sent a :enumerator:`PUGL_DATA` event.
+When the data event is received,
+the data can be fetched with :func:`puglGetClipboard`:
+
+.. code-block:: c
+
+ case PUGL_DATA:
+ onData(view, &event->data);
+ break;
+
+ // ...
+
+ static void
+ onData(PuglView* view, const PuglEventData* event)
+ {
+ uint32_t typeIndex = event->typeIndex;
+
+ const char* type = puglGetClipboardType(view, typeIndex);
+
+ fprintf(stderr, "Received data type: %s\n", type);
+
+ if (!strcmp(type, "text/plain")) {
+ size_t len = 0;
+ const void* data = puglGetClipboard(view, typeIndex, &len);
+
+ printf("Dropped: %s\n", (const char*)data);
+ }
+ }