[mutter] display: Establish a separate state variable for routing events



commit 0e758a9e655fa2658b9e2eef834f68e42d217419
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri Aug 15 13:12:22 2014 -0400

    display: Establish a separate state variable for routing events
    
    We've long used a switch statement on the grab operation to determine
    where events should go. The issue with MetaGrabOp is that it's a mixture
    of a few different things, including event routing, state management,
    and the behavior to choose during operations.
    
    This leads to poorly defined event routing and hard-to-follow logic,
    since it's sometimes unclear what should point where, and our utility
    methods for determining grab operations apart can be poorly named.
    
    To fix this, establish the concept of a "event route", which describes
    where events should be routed to.

 src/backends/meta-cursor-tracker.c |    2 +-
 src/compositor/compositor.c        |    4 +-
 src/core/display-private.h         |   24 +++++++++++-
 src/core/display.c                 |   78 +++++++++++++++++++++++++++++-------
 src/core/events.c                  |   13 ++----
 src/wayland/meta-wayland-pointer.c |   20 ++++++---
 6 files changed, 107 insertions(+), 34 deletions(-)
---
diff --git a/src/backends/meta-cursor-tracker.c b/src/backends/meta-cursor-tracker.c
index 1399145..a649cb4 100644
--- a/src/backends/meta-cursor-tracker.c
+++ b/src/backends/meta-cursor-tracker.c
@@ -61,7 +61,7 @@ get_displayed_cursor (MetaCursorTracker *tracker)
   if (!tracker->is_showing)
     return NULL;
 
-  if (meta_grab_op_windows_are_interactable (display->grab_op))
+  if (meta_display_windows_are_interactable (display))
     {
       if (tracker->has_window_cursor)
         return tracker->window_cursor;
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 4843dea..b52a85b 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -87,7 +87,7 @@
 static gboolean
 is_modal (MetaDisplay *display)
 {
-  return display->grab_op == META_GRAB_OP_COMPOSITOR;
+  return display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB;
 }
 
 static void sync_actor_stacking (MetaCompositor *compositor);
@@ -343,6 +343,7 @@ meta_begin_modal_for_plugin (MetaCompositor   *compositor,
     return FALSE;
 
   display->grab_op = META_GRAB_OP_COMPOSITOR;
+  display->event_route = META_EVENT_ROUTE_COMPOSITOR_GRAB;
   display->grab_window = NULL;
   display->grab_have_pointer = TRUE;
   display->grab_have_keyboard = TRUE;
@@ -375,6 +376,7 @@ meta_end_modal_for_plugin (MetaCompositor *compositor,
                          display->grab_window, display->grab_op);
 
   display->grab_op = META_GRAB_OP_NONE;
+  display->event_route = META_EVENT_ROUTE_NORMAL;
   display->grab_window = NULL;
   display->grab_have_pointer = FALSE;
   display->grab_have_keyboard = FALSE;
diff --git a/src/core/display-private.h b/src/core/display-private.h
index da2bec2..736258e 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -79,6 +79,24 @@ typedef enum {
   META_TILE_MAXIMIZED
 } MetaTileMode;
 
+typedef enum {
+  /* Normal interaction where you're interacting with windows.
+   * Events go to windows normally. */
+  META_EVENT_ROUTE_NORMAL,
+
+  /* In a compositor grab operation. All events go to the
+   * compositor plugin. */
+  META_EVENT_ROUTE_COMPOSITOR_GRAB,
+
+  /* A Wayland application has a popup open. All events go to
+   * the Wayland application. */
+  META_EVENT_ROUTE_WAYLAND_POPUP,
+
+  /* In a window operation like moving or resizing. All events
+   * goes to MetaWindow, but not to the actual client window. */
+  META_EVENT_ROUTE_WINDOW_OP,
+} MetaEventRoute;
+
 struct _MetaDisplay
 {
   GObject parent_instance;
@@ -174,6 +192,9 @@ struct _MetaDisplay
   guint       autoraise_timeout_id;
   MetaWindow* autoraise_window;
 
+  /* Event routing */
+  MetaEventRoute event_route;
+
   /* current window operation */
   MetaGrabOp  grab_op;
   MetaWindow *grab_window;
@@ -380,7 +401,6 @@ gboolean meta_grab_op_is_resizing (MetaGrabOp op);
 gboolean meta_grab_op_is_moving_or_resizing (MetaGrabOp op);
 gboolean meta_grab_op_is_mouse    (MetaGrabOp op);
 gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
-gboolean meta_grab_op_windows_are_interactable (MetaGrabOp op);
 
 void meta_display_increment_focus_sentinel (MetaDisplay *display);
 void meta_display_decrement_focus_sentinel (MetaDisplay *display);
@@ -432,4 +452,6 @@ void meta_restart_finish (void);
 
 void meta_display_cancel_touch (MetaDisplay *display);
 
+gboolean meta_display_windows_are_interactable (MetaDisplay *display);
+
 #endif
diff --git a/src/core/display.c b/src/core/display.c
index 849855d..14a3015 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -1264,15 +1264,15 @@ meta_grab_op_is_moving_or_resizing (MetaGrabOp op)
  * meta_grab_op_windows_are_interactable:
  * @op: A #MetaGrabOp
  *
- * Whether windows can be interacted with in this grab operation.
+ * Whether windows can be interacted with.
  */
 gboolean
-meta_grab_op_windows_are_interactable (MetaGrabOp op)
+meta_display_windows_are_interactable (MetaDisplay *display)
 {
-  switch (op)
+  switch (display->event_route)
     {
-    case META_GRAB_OP_WAYLAND_POPUP:
-    case META_GRAB_OP_NONE:
+    case META_EVENT_ROUTE_NORMAL:
+    case META_EVENT_ROUTE_WAYLAND_POPUP:
       return TRUE;
     default:
       return FALSE;
@@ -1444,7 +1444,7 @@ meta_display_sync_wayland_input_focus (MetaDisplay *display)
   MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
   MetaWindow *focus_window = NULL;
 
-  if (!meta_grab_op_windows_are_interactable (display->grab_op))
+  if (!meta_display_windows_are_interactable (display))
     focus_window = NULL;
   else if (meta_display_xwindow_is_a_no_focus_window (display, display->focus_xwindow))
     focus_window = NULL;
@@ -1753,6 +1753,48 @@ get_first_freefloating_window (MetaWindow *window)
   return window;
 }
 
+static MetaEventRoute
+get_event_route_from_grab_op (MetaGrabOp op)
+{
+  switch (op)
+    {
+    case META_GRAB_OP_NONE:
+      /* begin_grab_op shouldn't be called with META_GRAB_OP_NONE. */
+      g_assert_not_reached ();
+
+    case META_GRAB_OP_MOVING:
+    case META_GRAB_OP_RESIZING_SE:
+    case META_GRAB_OP_RESIZING_S:
+    case META_GRAB_OP_RESIZING_SW:
+    case META_GRAB_OP_RESIZING_N:
+    case META_GRAB_OP_RESIZING_NE:
+    case META_GRAB_OP_RESIZING_NW:
+    case META_GRAB_OP_RESIZING_W:
+    case META_GRAB_OP_RESIZING_E:
+    case META_GRAB_OP_KEYBOARD_MOVING:
+    case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
+    case META_GRAB_OP_KEYBOARD_RESIZING_S:
+    case META_GRAB_OP_KEYBOARD_RESIZING_N:
+    case META_GRAB_OP_KEYBOARD_RESIZING_W:
+    case META_GRAB_OP_KEYBOARD_RESIZING_E:
+    case META_GRAB_OP_KEYBOARD_RESIZING_SE:
+    case META_GRAB_OP_KEYBOARD_RESIZING_NE:
+    case META_GRAB_OP_KEYBOARD_RESIZING_SW:
+    case META_GRAB_OP_KEYBOARD_RESIZING_NW:
+      return META_EVENT_ROUTE_WINDOW_OP;
+
+    case META_GRAB_OP_COMPOSITOR:
+      /* begin_grab_op shouldn't be called with META_GRAB_OP_COMPOSITOR. */
+      g_assert_not_reached ();
+
+    case META_GRAB_OP_WAYLAND_POPUP:
+      return META_EVENT_ROUTE_WAYLAND_POPUP;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
 gboolean
 meta_display_begin_grab_op (MetaDisplay *display,
                            MetaScreen  *screen,
@@ -1768,6 +1810,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
 {
   MetaBackend *backend = meta_get_backend ();
   MetaWindow *grab_window = NULL;
+  MetaEventRoute event_route;
 
   g_assert (window != NULL);
 
@@ -1784,7 +1827,9 @@ meta_display_begin_grab_op (MetaDisplay *display,
       return FALSE;
     }
 
-  if (meta_grab_op_is_moving_or_resizing (op))
+  event_route = get_event_route_from_grab_op (op);
+
+  if (event_route == META_EVENT_ROUTE_WINDOW_OP)
     {
       if (meta_prefs_get_raise_on_click ())
         meta_window_raise (window);
@@ -1830,8 +1875,8 @@ meta_display_begin_grab_op (MetaDisplay *display,
       return FALSE;
     }
 
-  /* Grab keys for keyboard ops and mouse move/resizes; see #126497 */
-  if (meta_grab_op_is_moving_or_resizing (op))
+  /* Grab keys when beginning window ops; see #126497 */
+  if (event_route == META_EVENT_ROUTE_WINDOW_OP)
     {
       display->grab_have_keyboard = meta_window_grab_all_keys (grab_window, timestamp);
 
@@ -1844,6 +1889,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
         }
     }
 
+  display->event_route = event_route;
   display->grab_op = op;
   display->grab_window = grab_window;
   display->grab_button = button;
@@ -1884,7 +1930,8 @@ meta_display_begin_grab_op (MetaDisplay *display,
   g_signal_emit (display, display_signals[GRAB_OP_BEGIN], 0,
                  screen, display->grab_window, display->grab_op);
 
-  meta_window_grab_op_began (display->grab_window, display->grab_op);
+  if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
+    meta_window_grab_op_began (display->grab_window, display->grab_op);
 
   return TRUE;
 }
@@ -1899,13 +1946,13 @@ meta_display_end_grab_op (MetaDisplay *display,
   meta_topic (META_DEBUG_WINDOW_OPS,
               "Ending grab op %u at time %u\n", grab_op, timestamp);
 
-  if (display->grab_op == META_GRAB_OP_NONE)
+  if (display->event_route == META_EVENT_ROUTE_NORMAL)
     return;
 
   g_signal_emit (display, display_signals[GRAB_OP_END], 0,
                  display->screen, grab_window, grab_op);
 
-  if (meta_grab_op_is_moving_or_resizing (grab_op))
+  if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
     {
       /* Clear out the edge cache */
       meta_display_cleanup_edges (display);
@@ -1919,6 +1966,8 @@ meta_display_end_grab_op (MetaDisplay *display,
       if (!meta_prefs_get_raise_on_click () &&
           display->grab_threshold_movement_reached)
         meta_window_raise (display->grab_window);
+
+      meta_window_grab_op_ended (grab_window, grab_op);
     }
 
   if (display->grab_have_pointer)
@@ -1934,10 +1983,11 @@ meta_display_end_grab_op (MetaDisplay *display,
       meta_window_ungrab_all_keys (grab_window, timestamp);
     }
 
+  display->event_route = META_EVENT_ROUTE_NORMAL;
+  display->grab_op = META_GRAB_OP_NONE;
   display->grab_window = NULL;
   display->grab_tile_mode = META_TILE_NONE;
   display->grab_tile_monitor_number = -1;
-  display->grab_op = META_GRAB_OP_NONE;
 
   meta_display_update_cursor (display);
 
@@ -1947,8 +1997,6 @@ meta_display_end_grab_op (MetaDisplay *display,
       display->grab_resize_timeout_id = 0;
     }
 
-  meta_window_grab_op_ended (grab_window, grab_op);
-
   if (meta_is_wayland_compositor ())
     meta_display_sync_wayland_input_focus (display);
 }
diff --git a/src/core/events.c b/src/core/events.c
index 05a5f25..ce32c77 100644
--- a/src/core/events.c
+++ b/src/core/events.c
@@ -45,9 +45,6 @@ get_window_for_event (MetaDisplay        *display,
 {
   ClutterActor *source;
 
-  if (display->grab_op != META_GRAB_OP_NONE)
-    return display->grab_window;
-
   /* Always use the key focused window for key events. */
   switch (event->type)
     {
@@ -214,8 +211,7 @@ meta_display_handle_event (MetaDisplay        *display,
       goto out;
     }
 
-  if (display->grab_window == window &&
-      meta_grab_op_is_moving_or_resizing (display->grab_op))
+  if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
     {
       if (meta_window_handle_mouse_grab_op_event (window, event))
         {
@@ -256,8 +252,7 @@ meta_display_handle_event (MetaDisplay        *display,
        * event, and if it doesn't, replay the event to release our
        * own sync grab. */
 
-      if (display->grab_window == window &&
-          meta_grab_op_is_moving_or_resizing (display->grab_op))
+      if (display->event_route == META_EVENT_ROUTE_WINDOW_OP)
         {
           bypass_clutter = TRUE;
           bypass_wayland = TRUE;
@@ -285,11 +280,11 @@ meta_display_handle_event (MetaDisplay        *display,
 
  out:
   /* If the compositor has a grab, don't pass that through to Wayland */
-  if (display->grab_op == META_GRAB_OP_COMPOSITOR)
+  if (display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB)
     bypass_wayland = TRUE;
 
   /* If a Wayland client has a grab, don't pass that through to Clutter */
-  if (display->grab_op == META_GRAB_OP_WAYLAND_POPUP)
+  if (display->event_route == META_EVENT_ROUTE_WAYLAND_POPUP)
     bypass_clutter = TRUE;
 
 #ifdef HAVE_WAYLAND
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 50836e9..7350233 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -246,14 +246,20 @@ sync_focus_surface (MetaWaylandPointer *pointer)
   MetaDisplay *display = meta_get_display ();
   MetaWaylandSurface *focus_surface;
 
-  /* Don't update the focus surface while we have a move/resize grab. */
-  if (meta_grab_op_is_moving_or_resizing (display->grab_op))
-    return;
+  switch (display->event_route)
+    {
+    case META_EVENT_ROUTE_WINDOW_OP:
+      /* Don't update the focus surface while we're grabbing a window. */
+      return;
 
-  if (!meta_grab_op_windows_are_interactable (display->grab_op))
-    focus_surface = NULL;
-  else
-    focus_surface = pointer->current;
+    case META_EVENT_ROUTE_COMPOSITOR_GRAB:
+      /* The compositor has focus, so remove our focus... */
+      focus_surface = NULL;
+
+    case META_EVENT_ROUTE_NORMAL:
+    case META_EVENT_ROUTE_WAYLAND_POPUP:
+      focus_surface = pointer->current;
+    }
 
   if (focus_surface != pointer->focus_surface)
     {


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