x11: Add GdkX11Display:translate-event signal

This is supposed to replace gdk_window_add_filter() in the long run.
This commit is contained in:
Benjamin Otte 2017-12-13 00:43:30 +01:00
parent f34297cfba
commit 0d1ea05658
5 changed files with 113 additions and 35 deletions

View File

@ -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

View File

@ -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 ();
}

View File

@ -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,

View File

@ -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;
x11_screen = GDK_X11_DISPLAY (display)->screen;
dpy = GDK_DISPLAY_XDISPLAY (event_source->display);
#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
if (event)
g_signal_emit_by_name (display, "translate-event", &xevent, &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;

View File

@ -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