This is supposed to replace gdk_window_add_filter() in the long run.
OBJECT:VOID
OBJECT:DOUBLE,DOUBLE
BOXED:INT,INT
+BOXED:POINTER
VOID:DOUBLE,DOUBLE,POINTER,POINTER
VOID:POINTER,POINTER,BOOLEAN,BOOLEAN
#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"
#include <X11/extensions/Xrandr.h>
#endif
+enum {
+ TRANSLATE_EVENT,
+ LAST_SIGNAL
+};
+
typedef struct _GdkErrorTrap GdkErrorTrap;
struct _GdkErrorTrap
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))
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)
{
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 ();
}
#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>
struct _GdkX11DisplayClass
{
GdkDisplayClass parent_class;
+
+ GdkEvent * (* translate_event) (GdkX11Display *display,
+ const XEvent *event);
};
GdkX11Screen *_gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
}
}
-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);
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)
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);
{
/* Event translator was gotten before in get_filter_window() */
event = _gdk_x11_event_translator_translate (event_translator,
- event_source->display,
+ display,
xevent);
}
else
list = list->next;
event = _gdk_x11_event_translator_translate (translator,
- event_source->display,
+ display,
xevent);
}
}
handle_touch_synthetic_crossing (event);
}
-#ifdef HAVE_XGENERICEVENTS
- if (xevent->type == GenericEvent)
- XFreeEventData (dpy, &xevent->xcookie);
-#endif
-
return event;
}
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))
{
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;
#define __GDK_X11_EVENT_SOURCE_H__
#include "gdkeventtranslator.h"
+#include "gdkx11display.h"
G_BEGIN_DECLS
GdkEventMask event_mask,
unsigned int extra_x_mask);
+GdkEvent *gdk_event_source_translate_event (GdkX11Display *display,
+ const XEvent *xevent);
+
G_END_DECLS