소스 검색

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.
Alex Maese 2 년 전
부모
커밋
acdde129bb
4개의 변경된 파일38개의 추가작업 그리고 1개의 파일을 삭제
  1. 21 0
      src/video/x11/SDL_x11events.c
  2. 1 0
      src/video/x11/SDL_x11sym.h
  3. 15 0
      src/video/x11/SDL_x11xfixes.c
  4. 1 1
      src/video/x11/SDL_x11xfixes.h

+ 21 - 0
src/video/x11/SDL_x11events.c

@@ -869,6 +869,27 @@ static void X11_DispatchEvent(_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);

+ 1 - 0
src/video/x11/SDL_x11sym.h

@@ -162,6 +162,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
 
 #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS

+ 15 - 0
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(_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()
     return xfixes_initialized;
 }
 
+int X11_GetXFixesSelectionNotifyEvent()
+{
+    return xfixes_selection_notify_event;
+}
+
 void X11_SetWindowMouseRect(_THIS, SDL_Window *window)
 {
     if (SDL_RectEmpty(&window->mouse_rect)) {

+ 1 - 1
src/video/x11/SDL_x11xfixes.h

@@ -33,7 +33,7 @@ extern int X11_XfixesIsInitialized(void);
 extern void X11_SetWindowMouseRect(_THIS, SDL_Window *window);
 extern int X11_ConfineCursorWithFlags(_THIS, SDL_Window *window, const SDL_Rect *rect, int flags);
 extern void X11_DestroyPointerBarrier(_THIS, SDL_Window *window);
-
+extern int X11_GetXFixesSelectionNotifyEvent(void);
 #endif /* SDL_VIDEO_DRIVER_X11_XFIXES */
 
 #endif /* SDL_x11xfixes_h_ */