aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pugl/pugl/detail/implementation.c6
-rw-r--r--pugl/pugl/detail/mac.m4
-rw-r--r--pugl/pugl/detail/types.h1
-rw-r--r--pugl/pugl/detail/win.c4
-rw-r--r--pugl/pugl/detail/x11.c60
-rw-r--r--pugl/pugl/detail/x11.h1
6 files changed, 59 insertions, 17 deletions
diff --git a/pugl/pugl/detail/implementation.c b/pugl/pugl/detail/implementation.c
index 055e917..6cc4490 100644
--- a/pugl/pugl/detail/implementation.c
+++ b/pugl/pugl/detail/implementation.c
@@ -228,6 +228,7 @@ puglFreeView(PuglView* view)
free(view->title);
free(view->clipboard.data);
+ free(view->clipboardType.data);
puglFreeViewInternals(view);
free(view);
}
@@ -447,7 +448,7 @@ puglGetInternalClipboard(const PuglView* const view,
}
if (type) {
- *type = "text/plain";
+ *type = view->clipboardType.data;
}
return view->clipboard.data;
@@ -459,10 +460,11 @@ puglSetInternalClipboard(PuglView* const view,
const void* const data,
const size_t len)
{
- if (type && strcmp(type, "text/plain")) {
+ if (!type) {
return PUGL_UNSUPPORTED_TYPE;
}
+ puglSetBlob(&view->clipboardType, type, strlen(type) + 1);
puglSetBlob(&view->clipboard, data, len);
return PUGL_SUCCESS;
}
diff --git a/pugl/pugl/detail/mac.m b/pugl/pugl/detail/mac.m
index 23671ae..5f3b89f 100644
--- a/pugl/pugl/detail/mac.m
+++ b/pugl/pugl/detail/mac.m
@@ -1395,6 +1395,10 @@ puglSetClipboard(PuglView* const view,
NSPasteboard* const pasteboard = [NSPasteboard generalPasteboard];
const char* const str = (const char*)data;
+ if (type && strcmp(type, "text/plain")) {
+ return PUGL_UNSUPPORTED_TYPE;
+ }
+
PuglStatus st = puglSetInternalClipboard(view, type, data, len);
if (st) {
return st;
diff --git a/pugl/pugl/detail/types.h b/pugl/pugl/detail/types.h
index edd2bd0..6f676fd 100644
--- a/pugl/pugl/detail/types.h
+++ b/pugl/pugl/detail/types.h
@@ -61,6 +61,7 @@ struct PuglViewImpl {
PuglEventFunc eventFunc;
char* title;
PuglBlob clipboard;
+ PuglBlob clipboardType;
PuglNativeView parent;
uintptr_t transientParent;
PuglRect frame;
diff --git a/pugl/pugl/detail/win.c b/pugl/pugl/detail/win.c
index 4f7afee..ce81ede 100644
--- a/pugl/pugl/detail/win.c
+++ b/pugl/pugl/detail/win.c
@@ -1065,6 +1065,10 @@ puglSetClipboard(PuglView* const view,
{
PuglInternals* const impl = view->impl;
+ if (type && strcmp(type, "text/plain")) {
+ return PUGL_UNSUPPORTED_TYPE;
+ }
+
PuglStatus st = puglSetInternalClipboard(view, type, data, len);
if (st) {
return st;
diff --git a/pugl/pugl/detail/x11.c b/pugl/pugl/detail/x11.c
index 7b8daf2..01058a3 100644
--- a/pugl/pugl/detail/x11.c
+++ b/pugl/pugl/detail/x11.c
@@ -128,6 +128,7 @@ puglInitWorldInternals(PuglWorldType type, PuglWorldFlags flags)
// Intern the various atoms we will need
impl->atoms.CLIPBOARD = XInternAtom(display, "CLIPBOARD", 0);
impl->atoms.UTF8_STRING = XInternAtom(display, "UTF8_STRING", 0);
+ impl->atoms.TARGETS = XInternAtom(display, "TARGETS", 0);
impl->atoms.WM_PROTOCOLS = XInternAtom(display, "WM_PROTOCOLS", 0);
impl->atoms.WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", 0);
impl->atoms.PUGL_CLIENT_MSG = XInternAtom(display, "_PUGL_CLIENT_MSG", 0);
@@ -900,8 +901,14 @@ handleSelectionNotify(const PuglWorld* world, PuglView* view)
&left,
&str);
- if (str && fmt == 8 && type == world->impl->atoms.UTF8_STRING &&
- left == 0) {
+ if (str && fmt == 8 && left == 0) {
+ char *type_name = XGetAtomName(world->impl->display, type);
+ if (type_name) {
+ puglSetBlob(&view->clipboardType, type_name, strlen(type_name) + 1);
+ XFree(type_name);
+ } else {
+ puglSetBlob(&view->clipboardType, NULL, 0);
+ }
puglSetBlob(&view->clipboard, str, len);
}
@@ -926,17 +933,35 @@ handleSelectionRequest(const PuglWorld* world,
const char* type = NULL;
size_t len = 0;
const void* data = puglGetInternalClipboard(view, &type, &len);
- if (data && request->selection == world->impl->atoms.CLIPBOARD &&
- request->target == world->impl->atoms.UTF8_STRING) {
- note.property = request->property;
- XChangeProperty(world->impl->display,
- note.requestor,
- note.property,
- note.target,
- 8,
- PropModeReplace,
- (const uint8_t*)data,
- (int)len);
+ if (data && request->selection == world->impl->atoms.CLIPBOARD) {
+ const Atom types [2] = {
+ world->impl->atoms.TARGETS,
+ XInternAtom(world->impl->display, type, 0)
+ };
+
+ if (request->target == world->impl->atoms.TARGETS) {
+ note.property = request->property;
+ XChangeProperty(world->impl->display,
+ note.requestor,
+ note.property,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ (const uint8_t*)types,
+ (int)(sizeof(types) / sizeof(Atom)));
+ } else if (request->target == types[1]) {
+ note.property = request->property;
+ XChangeProperty(world->impl->display,
+ note.requestor,
+ note.property,
+ note.target,
+ 8,
+ PropModeReplace,
+ (const uint8_t*)data,
+ (int)len);
+ } else {
+ note.property = None;
+ }
} else {
note.property = None;
}
@@ -1034,10 +1059,10 @@ puglDispatchX11Events(PuglWorld* world)
} else if (xevent.type == FocusOut) {
XUnsetICFocus(impl->xic);
} else if (xevent.type == SelectionClear) {
+ puglSetBlob(&view->clipboardType, NULL, 0);
puglSetBlob(&view->clipboard, NULL, 0);
} else if (xevent.type == SelectionNotify &&
xevent.xselection.selection == atoms->CLIPBOARD &&
- xevent.xselection.target == atoms->UTF8_STRING &&
xevent.xselection.property == XA_PRIMARY) {
handleSelectionNotify(world, view);
} else if (xevent.type == SelectionRequest) {
@@ -1252,12 +1277,17 @@ puglGetClipboard(PuglView* const view,
const Window owner = XGetSelectionOwner(impl->display, atoms->CLIPBOARD);
if (owner != None && owner != impl->win) {
// Clear internal selection
+ puglSetBlob(&view->clipboardType, NULL, 0);
puglSetBlob(&view->clipboard, NULL, 0);
+ const Atom type_atom = type && *type
+ ? XInternAtom(impl->display, *type, 0)
+ : atoms->UTF8_STRING;
+
// Request selection from the owner
XConvertSelection(impl->display,
atoms->CLIPBOARD,
- atoms->UTF8_STRING,
+ type_atom,
XA_PRIMARY,
impl->win,
CurrentTime);
diff --git a/pugl/pugl/detail/x11.h b/pugl/pugl/detail/x11.h
index cf647ed..cedba56 100644
--- a/pugl/pugl/detail/x11.h
+++ b/pugl/pugl/detail/x11.h
@@ -33,6 +33,7 @@
typedef struct {
Atom CLIPBOARD;
Atom UTF8_STRING;
+ Atom TARGETS;
Atom WM_PROTOCOLS;
Atom WM_DELETE_WINDOW;
Atom PUGL_CLIENT_MSG;