From a799ac8ff0d965c346dea6af845722e59a0ffc02 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Tue, 27 Sep 2022 21:31:33 +0200 Subject: [PATCH] x11: Add public API to handle X11 events This API will be used by GNOME Shell to handle X11 events in the relevant places, as a substitute to gdk_window_add_filter(). It is ATM still a bit ironic, since the Mutter X11 event handler is itself a GdkFilterFunc, but it may move away from that eventually. Part-of: --- src/meta/meta-x11-display.h | 14 +++++ src/x11/events.c | 2 + src/x11/meta-x11-display-private.h | 5 ++ src/x11/meta-x11-display.c | 82 ++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+) diff --git a/src/meta/meta-x11-display.h b/src/meta/meta-x11-display.h index bff6c69e0..b910389bf 100644 --- a/src/meta/meta-x11-display.h +++ b/src/meta/meta-x11-display.h @@ -27,6 +27,10 @@ #include #include +typedef void (* MetaX11DisplayEventFunc) (MetaX11Display *x11_display, + XEvent *xev, + gpointer user_data); + #define META_TYPE_X11_DISPLAY (meta_x11_display_get_type ()) META_EXPORT @@ -67,4 +71,14 @@ void meta_x11_display_set_stage_input_region (MetaX11Display *x11_display, META_EXPORT void meta_x11_display_clear_stage_input_region (MetaX11Display *x11_display); +META_EXPORT +unsigned int meta_x11_display_add_event_func (MetaX11Display *x11_display, + MetaX11DisplayEventFunc event_func, + gpointer user_data, + GDestroyNotify destroy_notify); + +META_EXPORT +void meta_x11_display_remove_event_func (MetaX11Display *x11_display, + unsigned int id); + #endif /* META_X11_DISPLAY_H */ diff --git a/src/x11/events.c b/src/x11/events.c index 89733ba33..bda06fbea 100644 --- a/src/x11/events.c +++ b/src/x11/events.c @@ -1923,6 +1923,8 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display, meta_spew_event_print (x11_display, event); #endif + meta_x11_display_run_event_funcs (x11_display, event); + if (meta_x11_startup_notification_handle_xevent (x11_display, event)) { bypass_gtk = bypass_compositor = TRUE; diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h index a4e4b07e3..3763dc969 100644 --- a/src/x11/meta-x11-display-private.h +++ b/src/x11/meta-x11-display-private.h @@ -121,6 +121,8 @@ struct _MetaX11Display GHashTable *xids; GHashTable *alarms; + GList *event_funcs; + gboolean has_xinerama_indices; /* Managed by group.c */ @@ -282,4 +284,7 @@ void meta_x11_display_sync_input_focus (MetaX11Display *x11_display); MetaDisplay * meta_x11_display_get_display (MetaX11Display *x11_display); +void meta_x11_display_run_event_funcs (MetaX11Display *x11_display, + XEvent *xevent); + #endif /* META_X11_DISPLAY_PRIVATE_H */ diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c index 16b564d55..4ea0bbc91 100644 --- a/src/x11/meta-x11-display.c +++ b/src/x11/meta-x11-display.c @@ -77,6 +77,16 @@ G_DEFINE_TYPE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) static GQuark quark_x11_display_logical_monitor_data = 0; +typedef struct _MetaX11EventFilter MetaX11EventFilter; + +struct _MetaX11EventFilter +{ + unsigned int id; + MetaX11DisplayEventFunc func; + gpointer user_data; + GDestroyNotify destroy_notify; +}; + typedef struct _MetaX11DisplayLogicalMonitorData { int xinerama_index; @@ -126,6 +136,14 @@ meta_x11_display_unmanage_windows (MetaX11Display *x11_display) g_list_free_full (windows, g_object_unref); } +static void +meta_x11_event_filter_free (MetaX11EventFilter *filter) +{ + if (filter->destroy_notify && filter->user_data) + filter->destroy_notify (filter->user_data); + g_free (filter); +} + static void meta_x11_display_dispose (GObject *object) { @@ -135,6 +153,9 @@ meta_x11_display_dispose (GObject *object) g_clear_pointer (&x11_display->alarm_filters, g_ptr_array_unref); + g_clear_list (&x11_display->event_funcs, + (GDestroyNotify) meta_x11_event_filter_free); + if (x11_display->frames_client_cancellable) { g_cancellable_cancel (x11_display->frames_client_cancellable); @@ -2472,3 +2493,64 @@ meta_x11_display_clear_stage_input_region (MetaX11Display *x11_display) meta_x11_display_set_stage_input_region (x11_display, x11_display->empty_region); } + +/** + * meta_x11_display_add_event_func: (skip): + **/ +unsigned int +meta_x11_display_add_event_func (MetaX11Display *x11_display, + MetaX11DisplayEventFunc event_func, + gpointer user_data, + GDestroyNotify destroy_notify) +{ + MetaX11EventFilter *filter; + static unsigned int id = 0; + + filter = g_new0 (MetaX11EventFilter, 1); + filter->func = event_func; + filter->user_data = user_data; + filter->destroy_notify = destroy_notify; + filter->id = ++id; + + x11_display->event_funcs = g_list_prepend (x11_display->event_funcs, filter); + + return filter->id; +} + +/** + * meta_x11_display_remove_event_func: (skip): + **/ +void +meta_x11_display_remove_event_func (MetaX11Display *x11_display, + unsigned int id) +{ + MetaX11EventFilter *filter; + GList *l; + + for (l = x11_display->event_funcs; l; l = l->next) + { + filter = l->data; + + if (filter->id != id) + continue; + + x11_display->event_funcs = + g_list_delete_link (x11_display->event_funcs, l); + meta_x11_event_filter_free (filter); + break; + } +} + +void +meta_x11_display_run_event_funcs (MetaX11Display *x11_display, + XEvent *xevent) +{ + MetaX11EventFilter *filter; + GList *l; + + for (l = x11_display->event_funcs; l; l = l->next) + { + filter = l->data; + filter->func (x11_display, xevent, filter->user_data); + } +}