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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2779>
This commit is contained in:
Carlos Garnacho 2022-09-27 21:31:33 +02:00
parent 45bda2d969
commit a799ac8ff0
4 changed files with 103 additions and 0 deletions

View File

@ -27,6 +27,10 @@
#include <meta/prefs.h>
#include <meta/types.h>
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 */

View File

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

View File

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

View File

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