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