From 0e758a9e655fa2658b9e2eef834f68e42d217419 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Fri, 15 Aug 2014 13:12:22 -0400 Subject: [PATCH] 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 13991457e..a649cb47d 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 4843deacc..b52a85bcd 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 da2bec2b2..736258e82 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 849855d83..14a301593 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 05a5f2522..ce32c77d3 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 50836e9fb..73502333c 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) {