diff --git a/src/ui/ui.c b/src/ui/ui.c index cb1f36b3d..a11adbb8e 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -26,6 +26,7 @@ #include #include "core.h" #include "theme-private.h" +#include "x11/events.h" #include #include @@ -232,15 +233,11 @@ maybe_redirect_mouse_event (XEvent *xevent) return TRUE; } -static GdkFilterReturn -ui_filter_func (GdkXEvent *xevent, - GdkEvent *event, +static void +ui_filter_func (gpointer xevent, gpointer data) { - if (maybe_redirect_mouse_event (xevent)) - return GDK_FILTER_REMOVE; - else - return GDK_FILTER_CONTINUE; + maybe_redirect_mouse_event (xevent); } MetaUI* @@ -266,7 +263,7 @@ meta_ui_new (Display *xdisplay, */ gtk_widget_show (GTK_WIDGET (ui->frames)); - gdk_window_add_filter (NULL, ui_filter_func, NULL); + meta_display_events_x11_add_func (ui_filter_func, NULL); g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui); @@ -283,7 +280,7 @@ meta_ui_free (MetaUI *ui) gdisplay = gdk_x11_lookup_xdisplay (ui->xdisplay); g_object_set_data (G_OBJECT (gdisplay), "meta-ui", NULL); - gdk_window_remove_filter (NULL, ui_filter_func, NULL); + meta_display_events_x11_add_func (ui_filter_func, NULL); g_free (ui); } diff --git a/src/x11/events.c b/src/x11/events.c index 7355714f2..66a1068df 100644 --- a/src/x11/events.c +++ b/src/x11/events.c @@ -38,6 +38,16 @@ #include "wayland/meta-xwayland.h" #include "wayland/meta-wayland-private.h" +typedef struct _EventFuncData EventFuncData; + +struct _EventFuncData +{ + GFunc func; + gpointer data; +}; + +static GList *event_funcs = NULL; + static XIEvent * get_input_event (MetaDisplay *display, XEvent *event) @@ -1801,11 +1811,37 @@ xevent_filter (GdkXEvent *xevent, gpointer data) { MetaDisplay *display = data; + EventFuncData *event_data; + XIEvent *input_event; + GList *l; - if (meta_display_handle_xevent (display, xevent)) - return GDK_FILTER_REMOVE; - else + meta_display_handle_xevent (display, xevent); + + for (l = event_funcs; l; l = l->next) + { + event_data = l->data; + event_data->func (xevent, event_data->data); + } + + input_event = get_input_event (display, xevent); + + if (!input_event) return GDK_FILTER_CONTINUE; + + /* Filter all pointer and touch events, those are emulated + * above by the filters, and Gdk is bypassed there on purpose. + */ + if (input_event->evtype == XI_ButtonPress || + input_event->evtype == XI_ButtonRelease || + input_event->evtype == XI_Motion || + input_event->evtype == XI_Enter || + input_event->evtype == XI_Leave || + input_event->evtype == XI_TouchBegin || + input_event->evtype == XI_TouchUpdate || + input_event->evtype == XI_TouchEnd) + return GDK_FILTER_REMOVE; + + return GDK_FILTER_CONTINUE; } void @@ -1819,3 +1855,37 @@ meta_display_free_events_x11 (MetaDisplay *display) { gdk_window_remove_filter (NULL, xevent_filter, display); } + +void +meta_display_events_x11_add_func (GFunc func, + gpointer user_data) +{ + EventFuncData *data; + + data = g_slice_new0 (EventFuncData); + data->func = func; + data->data = user_data; + event_funcs = g_list_prepend (event_funcs, data); +} + +void +meta_display_events_x11_remove_func (GFunc func, + gpointer user_data) +{ + EventFuncData *data; + GList *l; + + data = g_slice_new0 (EventFuncData); + + for (l = event_funcs; l; l = l->next) + { + data = l->data; + + if (data->func != func || data->data != user_data) + continue; + + event_funcs = g_list_delete_link (event_funcs, l); + g_slice_free (EventFuncData, data); + break; + } +} diff --git a/src/x11/events.h b/src/x11/events.h index 6aa073b1d..cc12ddb8f 100644 --- a/src/x11/events.h +++ b/src/x11/events.h @@ -28,4 +28,9 @@ void meta_display_init_events_x11 (MetaDisplay *display); void meta_display_free_events_x11 (MetaDisplay *display); +void meta_display_events_x11_add_func (GFunc func, + gpointer user_data); +void meta_display_events_x11_remove_func (GFunc func, + gpointer user_data); + #endif