From 0e4165e54bca02eb343775c97ab49addd6c10a85 Mon Sep 17 00:00:00 2001 From: Alex Maese Date: Sat, 8 Jul 2023 12:52:41 -0500 Subject: [PATCH] X11: Use XFixes to detect clipboard updates Currently, SDL_CLIPBOARDUPDATE events are only sent when an SDL window has its selection cleared. This change sends the event anytime the XFixesSelectionNotify event is raised, and when the selection is either the clipboard or the primary selection. --- src/video/x11/SDL_x11events.c | 21 +++++++++++++++++++++ src/video/x11/SDL_x11sym.h | 1 + src/video/x11/SDL_x11xfixes.c | 15 +++++++++++++++ src/video/x11/SDL_x11xfixes.h | 2 +- 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index f391992b71..d70dcda0c6 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -891,6 +891,27 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) xevent->type, xevent->xany.display, xevent->xany.window); #endif +#ifdef SDL_VIDEO_DRIVER_X11_XFIXES + if (SDL_X11_HAVE_XFIXES && + xevent->type == X11_GetXFixesSelectionNotifyEvent()) { + XFixesSelectionNotifyEvent *ev = (XFixesSelectionNotifyEvent *) xevent; + + /* !!! FIXME: cache atoms */ + Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0); + +#ifdef DEBUG_XEVENTS + printf("window CLIPBOARD: XFixesSelectionNotify (selection = %s)\n", + X11_XGetAtomName(display, ev->selection)); +#endif + + if (ev->selection == XA_PRIMARY || + (XA_CLIPBOARD != None && ev->selection == XA_CLIPBOARD)) { + SDL_SendClipboardUpdate(); + return; + } + } +#endif /* SDL_VIDEO_DRIVER_X11_XFIXES */ + if ((videodata->clipboard_window != None) && (videodata->clipboard_window == xevent->xany.window)) { X11_HandleClipboardEvent(_this, xevent); diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 0a5fe38d56..08447ebd40 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -170,6 +170,7 @@ SDL_X11_SYM(PointerBarrier, XFixesCreatePointerBarrier, (Display* a, Window b, i SDL_X11_SYM(void, XFixesDestroyPointerBarrier, (Display* a, PointerBarrier b), (a,b),) SDL_X11_SYM(int, XIBarrierReleasePointer,(Display* a, int b, PointerBarrier c, BarrierEventID d), (a,b,c,d), return) /* this is actually Xinput2 */ SDL_X11_SYM(Status, XFixesQueryVersion,(Display* a, int* b, int* c), (a,b,c), return) +SDL_X11_SYM(Status, XFixesSelectSelectionInput, (Display* a, Window b, Atom c, unsigned long d), (a,b,c,d), return) #endif #ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS diff --git a/src/video/x11/SDL_x11xfixes.c b/src/video/x11/SDL_x11xfixes.c index 5c69eb1402..28ea7a6adb 100644 --- a/src/video/x11/SDL_x11xfixes.c +++ b/src/video/x11/SDL_x11xfixes.c @@ -29,6 +29,7 @@ #include "../../events/SDL_touch_c.h" static int xfixes_initialized = 0; +static int xfixes_selection_notify_event = 0; static int query_xfixes_version(Display *display, int major, int minor) { @@ -50,11 +51,20 @@ void X11_InitXfixes(SDL_VideoDevice *_this) int event, error; int fixes_opcode; + Atom XA_CLIPBOARD = X11_XInternAtom(data->display, "CLIPBOARD", 0); + if (!SDL_X11_HAVE_XFIXES || !X11_XQueryExtension(data->display, "XFIXES", &fixes_opcode, &event, &error)) { return; } + /* Selection tracking is available in all versions of XFixes */ + xfixes_selection_notify_event = event + XFixesSelectionNotify; + X11_XFixesSelectSelectionInput(data->display, DefaultRootWindow(data->display), + XA_CLIPBOARD, XFixesSetSelectionOwnerNotifyMask); + X11_XFixesSelectSelectionInput(data->display, DefaultRootWindow(data->display), + XA_PRIMARY, XFixesSetSelectionOwnerNotifyMask); + /* We need at least 5.0 for barriers. */ version = query_xfixes_version(data->display, 5, 0); if (!xfixes_version_atleast(version, 5, 0)) { @@ -69,6 +79,11 @@ int X11_XfixesIsInitialized(void) return xfixes_initialized; } +int X11_GetXFixesSelectionNotifyEvent() +{ + return xfixes_selection_notify_event; +} + void X11_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window) { if (SDL_RectEmpty(&window->mouse_rect)) { diff --git a/src/video/x11/SDL_x11xfixes.h b/src/video/x11/SDL_x11xfixes.h index 328fc5aae2..2c92794508 100644 --- a/src/video/x11/SDL_x11xfixes.h +++ b/src/video/x11/SDL_x11xfixes.h @@ -33,7 +33,7 @@ extern int X11_XfixesIsInitialized(void); extern void X11_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window); extern int X11_ConfineCursorWithFlags(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rect, int flags); extern void X11_DestroyPointerBarrier(SDL_VideoDevice *_this, SDL_Window *window); - +extern int X11_GetXFixesSelectionNotifyEvent(void); #endif /* SDL_VIDEO_DRIVER_X11_XFIXES */ #endif /* SDL_x11xfixes_h_ */