[gtk+] x11: Add GdkX11Display:translate-event signal



commit 0d1ea056580c41112c17b1dbdd6e3f500fdcf186
Author: Benjamin Otte <otte redhat com>
Date:   Wed Dec 13 00:43:30 2017 +0100

    x11: Add GdkX11Display:translate-event signal
    
    This is supposed to replace gdk_window_add_filter() in the long run.

 gdk/gdkmarshalers.list   |    1 +
 gdk/x11/gdkdisplay-x11.c |   75 +++++++++++++++++++++++++++++++++++++++++++++-
 gdk/x11/gdkdisplay-x11.h |    6 +++-
 gdk/x11/gdkeventsource.c |   62 ++++++++++++++++++--------------------
 gdk/x11/gdkeventsource.h |    4 ++
 5 files changed, 113 insertions(+), 35 deletions(-)
---
diff --git a/gdk/gdkmarshalers.list b/gdk/gdkmarshalers.list
index adc37b9..d70b190 100644
--- a/gdk/gdkmarshalers.list
+++ b/gdk/gdkmarshalers.list
@@ -4,5 +4,6 @@ VOID:POINTER,POINTER,POINTER
 OBJECT:VOID
 OBJECT:DOUBLE,DOUBLE
 BOXED:INT,INT
+BOXED:POINTER
 VOID:DOUBLE,DOUBLE,POINTER,POINTER
 VOID:POINTER,POINTER,BOOLEAN,BOOLEAN
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index a474443..b8eaff1 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -33,9 +33,9 @@
 #include "gdkeventtranslator.h"
 #include "gdkframeclockprivate.h"
 #include "gdkinternals.h"
-#include "gdkinternals.h"
 #include "gdkdeviceprivate.h"
 #include "gdkkeysprivate.h"
+#include "gdkmarshalers.h"
 #include "xsettings-client.h"
 #include "gdkclipboard-x11.h"
 #include "gdkprivate-x11.h"
@@ -76,6 +76,11 @@
 #include <X11/extensions/Xrandr.h>
 #endif
 
+enum {
+  TRANSLATE_EVENT,
+  LAST_SIGNAL
+};
+
 typedef struct _GdkErrorTrap  GdkErrorTrap;
 
 struct _GdkErrorTrap
@@ -176,6 +181,8 @@ static const char *const precache_atoms[] = {
 
 static char *gdk_sm_client_id;
 
+static guint signals[LAST_SIGNAL] = { 0 };
+
 G_DEFINE_TYPE_WITH_CODE (GdkX11Display, gdk_x11_display, GDK_TYPE_DISPLAY,
                          G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
                                                 gdk_x11_display_event_translator_init))
@@ -3156,6 +3163,24 @@ gdk_x11_display_get_last_seen_time (GdkDisplay *display)
   return gdk_x11_get_server_time (GDK_X11_DISPLAY (display)->leader_gdk_window);
 }
 
+static gboolean
+gdk_x11_display_translate_event_accumulator (GSignalInvocationHint *ihint,
+                                             GValue                *return_accu,
+                                             const GValue          *handler_return,
+                                             gpointer               dummy)
+{
+  GdkEvent *event;
+
+  event = g_value_get_boxed (handler_return);
+  if (event == NULL)
+    return TRUE;
+
+  if (event->type != GDK_NOTHING)
+    g_value_set_boxed (return_accu, event);
+
+  return FALSE;
+}
+
 static void
 gdk_x11_display_class_init (GdkX11DisplayClass * class)
 {
@@ -3216,5 +3241,53 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
   display_class->get_last_seen_time = gdk_x11_display_get_last_seen_time;
   display_class->set_cursor_theme = gdk_x11_display_set_cursor_theme;
 
+  class->translate_event = gdk_event_source_translate_event;
+
+  /**
+   * GdkX11Display::translate-event:
+   * @display: the object on which the signal is emitted
+   * @xevent: a pointer to the XEvent to process
+   *
+   * The ::translate-event signal is a low level signal that is emitted
+   * whenever an XEvent needs to be translated to a #GdkEvent.
+   *
+   * Handlers to this signal can return one of 3 possible values:
+   * 
+   * 1. %NULL
+   * 
+   * This will result in the next handler being invoked.
+   *
+   * 2. a #GdkEvent
+   *
+   * This will result in no further handlers being invoked and the returned
+   * event being enqueued for further processing by GDK.
+   *
+   * 3. gdk_event_new(GDK_NOTHING)
+   *
+   * If a handler returns an event of type GDK_NOTHING, the event will be
+   * discarded and no further handlers will be invoked. Use this if your
+   * function completely handled the @xevent.
+   *
+   * Note that the default handler for this function is GDK's own event
+   * translation mechanism, so by translating an event that GDK expects to
+   * translate, you may break GDK and/or GTK+ in interesting ways, so you
+   * have to know what you're doing.
+   *
+   * If you are interested in X GenericEvents, bear in mind that
+   * XGetEventData() has been already called on the event, and
+   * XFreeEventData() will be called afterwards.
+   *
+   * Returns: The translated #GdkEvent or %NULL to invoke further handlers to
+   *     translate the event.
+   */
+  signals[TRANSLATE_EVENT] =
+    g_signal_new (g_intern_static_string ("translate-event"),
+                 G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_LAST,
+                 G_STRUCT_OFFSET (GdkX11DisplayClass, translate_event),
+                  gdk_x11_display_translate_event_accumulator, NULL,
+                  _gdk_marshal_BOXED__POINTER,
+                  GDK_TYPE_EVENT, 1, G_TYPE_POINTER);
+
   _gdk_x11_windowing_init ();
 }
diff --git a/gdk/x11/gdkdisplay-x11.h b/gdk/x11/gdkdisplay-x11.h
index 6da7cf6..555b855 100644
--- a/gdk/x11/gdkdisplay-x11.h
+++ b/gdk/x11/gdkdisplay-x11.h
@@ -26,8 +26,9 @@
 #include "gdkkeys.h"
 #include "gdkwindow.h"
 #include "gdkinternals.h"
-#include "gdkx11screen.h"
 #include "gdkx11devicemanager.h"
+#include "gdkx11display.h"
+#include "gdkx11screen.h"
 
 #include <X11/X.h>
 #include <X11/Xlib.h>
@@ -166,6 +167,9 @@ struct _GdkX11Display
 struct _GdkX11DisplayClass
 {
   GdkDisplayClass parent_class;
+
+  GdkEvent *            (* translate_event)             (GdkX11Display          *display,
+                                                         const XEvent           *event);
 };
 
 GdkX11Screen *_gdk_x11_display_screen_for_xrootwin (GdkDisplay  *display,
diff --git a/gdk/x11/gdkeventsource.c b/gdk/x11/gdkeventsource.c
index 5de5b7b..ccf4c59 100644
--- a/gdk/x11/gdkeventsource.c
+++ b/gdk/x11/gdkeventsource.c
@@ -263,29 +263,23 @@ handle_touch_synthetic_crossing (GdkEvent *event)
     }
 }
 
-static GdkEvent *
-gdk_event_source_translate_event (GdkEventSource *event_source,
-                                  XEvent         *xevent)
+GdkEvent *
+gdk_event_source_translate_event (GdkX11Display  *x11_display,
+                                  const XEvent   *xevent)
 {
+  GdkEventSource *event_source = (GdkEventSource *) x11_display->event_source;
   GdkEvent *event = gdk_event_new (GDK_NOTHING);
   GdkFilterReturn result = GDK_FILTER_CONTINUE;
+  GdkDisplay *display = GDK_DISPLAY (x11_display);
   GdkEventTranslator *event_translator;
   GdkWindow *filter_window;
   Display *dpy;
   GdkX11Screen *x11_screen;
   gpointer cache;
 
-  x11_screen = GDK_X11_DISPLAY (event_source->display)->screen;
-
-  dpy = GDK_DISPLAY_XDISPLAY (event_source->display);
+  x11_screen = GDK_X11_DISPLAY (display)->screen;
 
-#ifdef HAVE_XGENERICEVENTS
-  /* Get cookie data here so it's available
-   * to every event translator and event filter.
-   */
-  if (xevent->type == GenericEvent)
-    XGetEventData (dpy, &xevent->xcookie);
-#endif
+  dpy = GDK_DISPLAY_XDISPLAY (display);
 
   filter_window = gdk_event_source_get_filter_window (event_source, xevent,
                                                       &event_translator);
@@ -300,7 +294,7 @@ gdk_event_source_translate_event (GdkEventSource *event_source,
       xevent->xany.window == x11_screen->xsettings_manager_window)
     result = gdk_xsettings_manager_window_filter (xevent, event, x11_screen);
 
-  cache = gdk_window_cache_get (event_source->display);
+  cache = gdk_window_cache_get (display);
   if (cache)
     {
       if (result == GDK_FILTER_CONTINUE)
@@ -328,11 +322,6 @@ gdk_event_source_translate_event (GdkEventSource *event_source,
 
   if (result != GDK_FILTER_CONTINUE)
     {
-#ifdef HAVE_XGENERICEVENTS
-      if (xevent->type == GenericEvent)
-        XFreeEventData (dpy, &xevent->xcookie);
-#endif
-
       if (result == GDK_FILTER_REMOVE)
         {
           gdk_event_free (event);
@@ -349,7 +338,7 @@ gdk_event_source_translate_event (GdkEventSource *event_source,
     {
       /* Event translator was gotten before in get_filter_window() */
       event = _gdk_x11_event_translator_translate (event_translator,
-                                                   event_source->display,
+                                                   display,
                                                    xevent);
     }
   else
@@ -362,7 +351,7 @@ gdk_event_source_translate_event (GdkEventSource *event_source,
 
           list = list->next;
           event = _gdk_x11_event_translator_translate (translator,
-                                                       event_source->display,
+                                                       display,
                                                        xevent);
         }
     }
@@ -386,11 +375,6 @@ gdk_event_source_translate_event (GdkEventSource *event_source,
       handle_touch_synthetic_crossing (event);
     }
 
-#ifdef HAVE_XGENERICEVENTS
-  if (xevent->type == GenericEvent)
-    XFreeEventData (dpy, &xevent->xcookie);
-#endif
-
   return event;
 }
 
@@ -449,11 +433,6 @@ _gdk_x11_display_queue_events (GdkDisplay *display)
   GdkEvent *event;
   XEvent xevent;
   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
-  GdkEventSource *event_source;
-  GdkX11Display *display_x11;
-
-  display_x11 = GDK_X11_DISPLAY (display);
-  event_source = (GdkEventSource *) display_x11->event_source;
 
   while (!_gdk_event_queue_find_first (display) && XPending (xdisplay))
     {
@@ -469,9 +448,26 @@ _gdk_x11_display_queue_events (GdkDisplay *display)
             continue;
         }
 
-      event = gdk_event_source_translate_event (event_source, &xevent);
+#ifdef HAVE_XGENERICEVENTS
+      /* Get cookie data here so it's available
+       * to every event translator and event filter.
+       */
+      if (xevent.type == GenericEvent)
+        XGetEventData (xdisplay, &xevent.xcookie);
+#endif
+
+      g_signal_emit_by_name (display, "translate-event", &xevent, &event);
 
-      if (event)
+#ifdef HAVE_XGENERICEVENTS
+      if (xevent.type == GenericEvent)
+        XFreeEventData (xdisplay, &xevent.xcookie);
+#endif
+
+      if (event && event->type == GDK_NOTHING)
+        {
+          gdk_event_free (event);
+        }
+      else if (event)
         {
           GList *node;
 
diff --git a/gdk/x11/gdkeventsource.h b/gdk/x11/gdkeventsource.h
index 8338fdd..5398f4f 100644
--- a/gdk/x11/gdkeventsource.h
+++ b/gdk/x11/gdkeventsource.h
@@ -19,6 +19,7 @@
 #define __GDK_X11_EVENT_SOURCE_H__
 
 #include "gdkeventtranslator.h"
+#include "gdkx11display.h"
 
 G_BEGIN_DECLS
 
@@ -37,6 +38,9 @@ void      gdk_x11_event_source_select_events  (GdkEventSource *source,
                                                GdkEventMask    event_mask,
                                                unsigned int    extra_x_mask);
 
+GdkEvent *gdk_event_source_translate_event    (GdkX11Display  *display,
+                                               const XEvent   *xevent);
+
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]