aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2022-05-22 17:48:16 -0400
committerDavid Robillard <d@drobilla.net>2023-11-11 09:49:51 -0500
commitc59e88aa6fa60c6f7424da737fcaf0496a0bf3d6 (patch)
treeca5e6f85207f3f51bd3015a67c23d9dd0c917846 /src
parent32733abab8546b708cab59a4df09f92eb3214f73 (diff)
downloadpugl-c59e88aa6fa60c6f7424da737fcaf0496a0bf3d6.tar.gz
pugl-c59e88aa6fa60c6f7424da737fcaf0496a0bf3d6.tar.bz2
pugl-c59e88aa6fa60c6f7424da737fcaf0496a0bf3d6.zip
Add API support for multiple clipboards
Adds a PuglClipboard enum, and uses it everywhere necessary to "structurally" support multiple clipboards. Towards re-using this API to support DnD.
Diffstat (limited to 'src')
-rw-r--r--src/mac.m61
-rw-r--r--src/win.c38
-rw-r--r--src/x11.c80
-rw-r--r--src/x11.h1
4 files changed, 121 insertions, 59 deletions
diff --git a/src/mac.m b/src/mac.m
index 2d492a9..6da3cf7 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -1867,6 +1867,19 @@ puglSetTransientParent(PuglView* view, PuglNativeView parent)
return PUGL_FAILURE;
}
+static NSPasteboard*
+getPasteboard(const PuglView* const view, const PuglClipboard clipboard)
+{
+ (void)view;
+
+ switch (clipboard) {
+ case PUGL_CLIPBOARD_GENERAL:
+ return [NSPasteboard generalPasteboard];
+ }
+
+ return NULL;
+}
+
PuglStatus
puglPaste(PuglView* const view)
{
@@ -1883,18 +1896,20 @@ puglPaste(PuglView* const view)
}
uint32_t
-puglGetNumClipboardTypes(const PuglView* PUGL_UNUSED(view))
+puglGetNumClipboardTypes(const PuglView* const view,
+ const PuglClipboard clipboard)
{
- NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard];
+ NSPasteboard* const pasteboard = getPasteboard(view, clipboard);
return pasteboard ? (uint32_t)[[pasteboard types] count] : 0;
}
const char*
-puglGetClipboardType(const PuglView* PUGL_UNUSED(view),
- const uint32_t typeIndex)
+puglGetClipboardType(const PuglView* const view,
+ const PuglClipboard clipboard,
+ const uint32_t typeIndex)
{
- NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard];
+ NSPasteboard* const pasteboard = getPasteboard(view, clipboard);
if (!pasteboard) {
return NULL;
}
@@ -1918,7 +1933,7 @@ puglAcceptOffer(PuglView* const view,
const PuglRect region)
{
PuglWrapperView* const wrapper = view->impl->wrapperView;
- NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard];
+ NSPasteboard* const pasteboard = getPasteboard(view, offer->clipboard);
if (!pasteboard) {
return PUGL_BAD_PARAMETER;
}
@@ -1945,13 +1960,14 @@ puglAcceptOffer(PuglView* const view,
}
const void*
-puglGetClipboard(PuglView* const view,
- const uint32_t typeIndex,
- size_t* const len)
+puglGetClipboard(PuglView* const view,
+ const PuglClipboard clipboard,
+ const uint32_t typeIndex,
+ size_t* const len)
{
*len = 0;
- NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard];
+ NSPasteboard* const pasteboard = getPasteboard(view, clipboard);
if (!pasteboard) {
return NULL;
}
@@ -2035,20 +2051,23 @@ puglSetCursor(PuglView* view, PuglCursor cursor)
}
PuglStatus
-puglSetClipboard(PuglView* PUGL_UNUSED(view),
- const char* const type,
- const void* const data,
- const size_t len)
+puglSetClipboard(PuglView* PUGL_UNUSED(view),
+ const PuglClipboard clipboard,
+ const char* const type,
+ const void* const data,
+ const size_t len)
{
- NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard];
- NSString* const mimeType = [NSString stringWithUTF8String:type];
- NSString* const uti = utiForMimeType(mimeType);
- NSData* const blob = [NSData dataWithBytes:data length:len];
+ if (clipboard == PUGL_CLIPBOARD_GENERAL) {
+ NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard];
+ NSString* const mimeType = [NSString stringWithUTF8String:type];
+ NSString* const uti = utiForMimeType(mimeType);
+ NSData* const blob = [NSData dataWithBytes:data length:len];
- [pasteboard declareTypes:[NSArray arrayWithObjects:uti, nil] owner:nil];
+ [pasteboard declareTypes:[NSArray arrayWithObjects:uti, nil] owner:nil];
- if ([pasteboard setData:blob forType:uti]) {
- return PUGL_SUCCESS;
+ if ([pasteboard setData:blob forType:uti]) {
+ return PUGL_SUCCESS;
+ }
}
return PUGL_FAILURE;
diff --git a/src/win.c b/src/win.c
index 2562d5f..d118b36 100644
--- a/src/win.c
+++ b/src/win.c
@@ -1348,16 +1348,22 @@ puglSetTransientParent(PuglView* view, PuglNativeView parent)
}
uint32_t
-puglGetNumClipboardTypes(const PuglView* const PUGL_UNUSED(view))
+puglGetNumClipboardTypes(const PuglView* const PUGL_UNUSED(view),
+ const PuglClipboard clipboard)
{
- return IsClipboardFormatAvailable(CF_UNICODETEXT) ? 1U : 0U;
+ return (clipboard == PUGL_CLIPBOARD_GENERAL &&
+ IsClipboardFormatAvailable(CF_UNICODETEXT))
+ ? 1U
+ : 0U;
}
const char*
puglGetClipboardType(const PuglView* const PUGL_UNUSED(view),
- const uint32_t typeIndex)
+ const PuglClipboard clipboard,
+ const uint32_t PUGL_UNUSED(typeIndex))
{
- return (typeIndex == 0 && IsClipboardFormatAvailable(CF_UNICODETEXT))
+ return (clipboard == PUGL_CLIPBOARD_GENERAL && typeIndex == 0 &&
+ IsClipboardFormatAvailable(CF_UNICODETEXT))
? "text/plain"
: NULL;
}
@@ -1388,12 +1394,17 @@ puglAcceptOffer(PuglView* const view,
}
const void*
-puglGetClipboard(PuglView* const view,
- const uint32_t typeIndex,
- size_t* const len)
+puglGetClipboard(PuglView* const view,
+ const PuglClipboard clipboard,
+ const uint32_t typeIndex,
+ size_t* const len)
{
PuglInternals* const impl = view->impl;
+ if (clipboard != PUGL_CLIPBOARD_GENERAL) {
+ return NULL;
+ }
+
if (typeIndex > 0U || !IsClipboardFormatAvailable(CF_UNICODETEXT) ||
!OpenClipboard(impl->hwnd)) {
return NULL;
@@ -1418,13 +1429,18 @@ puglGetClipboard(PuglView* const view,
}
PuglStatus
-puglSetClipboard(PuglView* const view,
- const char* const type,
- const void* const data,
- const size_t len)
+puglSetClipboard(PuglView* const view,
+ const PuglClipboard clipboard,
+ const char* const type,
+ const void* const data,
+ const size_t len)
{
PuglInternals* const impl = view->impl;
+ if (clipboard != PUGL_CLIPBOARD_GENERAL) {
+ return PUGL_FAILURE;
+ }
+
PuglStatus st = puglSetBlob(&view->impl->clipboard, data, len);
if (st) {
return st;
diff --git a/src/x11.c b/src/x11.c
index 6306efd..5bdbbed 100644
--- a/src/x11.c
+++ b/src/x11.c
@@ -257,6 +257,7 @@ puglInitViewInternals(PuglWorld* const world)
{
PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
+ impl->clipboard.clipboard = PUGL_CLIPBOARD_GENERAL;
impl->clipboard.selection = world->impl->atoms.CLIPBOARD;
impl->clipboard.property = XA_PRIMARY;
@@ -951,10 +952,22 @@ getAtomProperty(PuglView* const view,
}
static PuglX11Clipboard*
+getX11Clipboard(PuglView* const view, const PuglClipboard clipboard)
+{
+ return clipboard == PUGL_CLIPBOARD_GENERAL ? &view->impl->clipboard : NULL;
+}
+
+static const PuglX11Clipboard*
+getConstX11Clipboard(const PuglView* const view, const PuglClipboard clipboard)
+{
+ return clipboard == PUGL_CLIPBOARD_GENERAL ? &view->impl->clipboard : NULL;
+}
+
+static PuglX11Clipboard*
getX11SelectionClipboard(PuglView* const view, const Atom selection)
{
return (selection == view->world->impl->atoms.CLIPBOARD)
- ? &view->impl->clipboard
+ ? getX11Clipboard(view, PUGL_CLIPBOARD_GENERAL)
: NULL;
}
@@ -1617,8 +1630,12 @@ handleSelectionNotify(const PuglWorld* const world,
if (!getAtomProperty(
view, event->requestor, event->property, &numFormats, &formats) &&
!setClipboardFormats(view, board, numFormats, formats)) {
- const PuglDataOfferEvent offer = {
- PUGL_DATA_OFFER, 0, (double)event->time / 1e3, 0.0, 0.0};
+ const PuglDataOfferEvent offer = {PUGL_DATA_OFFER,
+ 0,
+ (double)event->time / 1e3,
+ 0.0,
+ 0.0,
+ board->clipboard};
puglEvent.offer = offer;
board->acceptedFormatIndex = UINT32_MAX;
@@ -1640,6 +1657,7 @@ handleSelectionNotify(const PuglWorld* const world,
(double)event->time / 1e3,
0.0,
0.0,
+ board->clipboard,
board->acceptedFormatIndex};
puglEvent.data = data;
@@ -2072,12 +2090,13 @@ puglSetTransientParent(PuglView* const view, const PuglNativeView parent)
}
const void*
-puglGetClipboard(PuglView* const view,
- const uint32_t typeIndex,
- size_t* const len)
+puglGetClipboard(PuglView* const view,
+ const PuglClipboard clipboard,
+ const uint32_t typeIndex,
+ size_t* const len)
{
Display* const display = view->world->impl->display;
- PuglX11Clipboard* const board = &view->impl->clipboard;
+ PuglX11Clipboard* const board = getX11Clipboard(view, clipboard);
if (typeIndex != board->acceptedFormatIndex) {
return NULL;
@@ -2099,25 +2118,28 @@ puglAcceptOffer(PuglView* const view,
const uint32_t typeIndex,
const PuglRect region)
{
- (void)offer;
(void)region;
PuglInternals* const impl = view->impl;
Display* const display = view->world->impl->display;
- PuglX11Clipboard* const board = &view->impl->clipboard;
+ PuglX11Clipboard* const board = getX11Clipboard(view, offer->clipboard);
board->acceptedFormatIndex = typeIndex;
board->acceptedFormat = board->formats[typeIndex];
- // Request the data in the specified type from the general clipboard
- XConvertSelection(display,
- board->selection,
- board->acceptedFormat,
- board->property,
- impl->win,
- CurrentTime);
+ if (offer->clipboard == PUGL_CLIPBOARD_GENERAL) {
+ // Request the data in the specified type from the general clipboard
+ XConvertSelection(display,
+ board->selection,
+ board->acceptedFormat,
+ board->property,
+ impl->win,
+ CurrentTime);
- return PUGL_SUCCESS;
+ return PUGL_SUCCESS;
+ }
+
+ return PUGL_FAILURE;
}
PuglStatus
@@ -2125,7 +2147,7 @@ puglPaste(PuglView* const view)
{
Display* const display = view->world->impl->display;
const PuglX11Atoms* atoms = &view->world->impl->atoms;
- const PuglX11Clipboard* board = &view->impl->clipboard;
+ const PuglX11Clipboard* board = getX11Clipboard(view, PUGL_CLIPBOARD_GENERAL);
// Request a SelectionNotify for TARGETS (available datatypes)
XConvertSelection(display,
@@ -2139,28 +2161,32 @@ puglPaste(PuglView* const view)
}
uint32_t
-puglGetNumClipboardTypes(const PuglView* const view)
+puglGetNumClipboardTypes(const PuglView* const view,
+ const PuglClipboard clipboard)
{
- return (uint32_t)view->impl->clipboard.numFormats;
+ return (uint32_t)getConstX11Clipboard(view, clipboard)->numFormats;
}
const char*
-puglGetClipboardType(const PuglView* const view, const uint32_t typeIndex)
+puglGetClipboardType(const PuglView* const view,
+ const PuglClipboard clipboard,
+ const uint32_t typeIndex)
{
- const PuglX11Clipboard* const board = &view->impl->clipboard;
+ const PuglX11Clipboard* const board = getConstX11Clipboard(view, clipboard);
return typeIndex < board->numFormats ? board->formatStrings[typeIndex] : NULL;
}
PuglStatus
-puglSetClipboard(PuglView* const view,
- const char* const type,
- const void* const data,
- const size_t len)
+puglSetClipboard(PuglView* const view,
+ const PuglClipboard clipboard,
+ const char* const type,
+ const void* const data,
+ const size_t len)
{
PuglInternals* const impl = view->impl;
Display* const display = view->world->impl->display;
- PuglX11Clipboard* const board = &view->impl->clipboard;
+ PuglX11Clipboard* const board = getX11Clipboard(view, clipboard);
PuglStatus st = puglSetBlob(&board->data, data, len);
if (!st) {
diff --git a/src/x11.h b/src/x11.h
index bc93630..58073e5 100644
--- a/src/x11.h
+++ b/src/x11.h
@@ -54,6 +54,7 @@ typedef struct {
} PuglTimer;
typedef struct {
+ PuglClipboard clipboard;
Atom selection;
Atom property;
Window source;