[mutter] compositor: Spoof events on the guard window



commit 5e9621ed8077a6b5f53574a9350ee4f8846f9753
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri Dec 21 07:32:41 2012 -0500

    compositor: Spoof events on the guard window
    
    This allows events generated for the guard window to be picked up
    by Clutter as if they were events for the mutter stage.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=681540

 src/compositor/compositor.c |   48 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 48 insertions(+), 0 deletions(-)
---
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index bb9cc38..1103751 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -812,6 +812,52 @@ meta_compositor_window_shape_changed (MetaCompositor *compositor,
   meta_window_actor_update_shape (window_actor);
 }
 
+/* Clutter makes the assumption that there is only one X window
+ * per stage, which is a valid assumption to make for a generic
+ * application toolkit. As such, it will ignore any events sent
+ * to the a stage that isn't its X window.
+ *
+ * When a user clicks on what she thinks is the wallpaper, she
+ * is actually clicking on the guard window, which is an entirely
+ * separate top-level override-redirect window in the hierarchy.
+ * We want to recieve events on this guard window so that users
+ * can right-click on the background actor. We do this by telling
+ * Clutter a little white lie, by transforming clicks on the guard
+ * window to become clicks on the stage window, allowing Clutter
+ * to process the event normally.
+ */
+static void
+maybe_spoof_guard_window_event_as_stage_event (MetaCompScreen *info,
+                                               XEvent         *event)
+{
+  MetaDisplay *display = meta_screen_get_display (info->screen);
+
+  if (event->type == GenericEvent &&
+      event->xcookie.extension == display->xinput_opcode)
+    {
+      XIEvent *input_event = (XIEvent *) event->xcookie.data;
+
+      /* Only care about pointer events for now. */
+      switch (input_event->evtype)
+        {
+        case XI_Motion:
+        case XI_ButtonPress:
+        case XI_ButtonRelease:
+          {
+            XIDeviceEvent *device_event = ((XIDeviceEvent *) input_event);
+            if (device_event->event == info->screen->guard_window)
+              {
+                Window xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
+                device_event->event = xwin;
+              }
+          }
+          break;
+        default:
+          break;
+        }
+    }
+}
+
 /**
  * meta_compositor_process_event: (skip)
  *
@@ -860,6 +906,8 @@ meta_compositor_process_event (MetaCompositor *compositor,
 
          info = meta_screen_get_compositor_data (screen);
 
+          maybe_spoof_guard_window_event_as_stage_event (info, event);
+
          if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
            {
              DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]