From b4b9a7c90ff97a078b33844c2e99bcaedd708745 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Tue, 12 Jul 2022 00:45:43 +0200 Subject: [PATCH] core: Move remaining default focus window handling to workspace Part-of: --- src/core/display-private.h | 3 - src/core/display.c | 24 ------ src/core/stack.c | 125 +------------------------------- src/core/stack.h | 67 +---------------- src/core/window.c | 10 ++- src/core/workspace-private.h | 8 +- src/core/workspace.c | 123 +++++++++++++++++++++++++++---- src/wayland/meta-xwayland-dnd.c | 8 +- src/x11/window-x11.c | 3 +- 9 files changed, 129 insertions(+), 242 deletions(-) diff --git a/src/core/display-private.h b/src/core/display-private.h index 37932095b..145509e91 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -411,9 +411,6 @@ gboolean meta_display_apply_startup_properties (MetaDisplay *display, void meta_display_queue_workarea_recalc (MetaDisplay *display); void meta_display_queue_check_fullscreen (MetaDisplay *display); -MetaWindow *meta_display_get_pointer_window (MetaDisplay *display, - MetaWindow *not_this_one); - MetaWindow *meta_display_get_window_from_id (MetaDisplay *display, uint64_t window_id); uint64_t meta_display_generate_window_id (MetaDisplay *display); diff --git a/src/core/display.c b/src/core/display.c index fb9224416..f10334665 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -3794,30 +3794,6 @@ meta_display_get_monitor_in_fullscreen (MetaDisplay *display, purposes */ return logical_monitor->in_fullscreen == TRUE; } -MetaWindow * -meta_display_get_pointer_window (MetaDisplay *display, - MetaWindow *not_this_one) -{ - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - MetaWindow *window; - graphene_point_t point; - - if (not_this_one) - meta_topic (META_DEBUG_FOCUS, - "Focusing mouse window excluding %s", not_this_one->desc); - - meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL); - - window = meta_stack_get_default_focus_window_at_point (display->stack, - workspace_manager->active_workspace, - not_this_one, - point.x, point.y); - - return window; -} - void meta_display_focus_default_window (MetaDisplay *display, guint32 timestamp) diff --git a/src/core/stack.c b/src/core/stack.c index 481e72232..2481adf78 100644 --- a/src/core/stack.c +++ b/src/core/stack.c @@ -50,6 +50,7 @@ static void stack_do_constrain (MetaStack *stack); static void stack_do_resort (MetaStack *stack); static void stack_ensure_sorted (MetaStack *stack); + enum { PROP_DISPLAY = 1, @@ -1007,110 +1008,6 @@ meta_stack_get_below (MetaStack *stack, return below; } -static gboolean -window_contains_point (MetaWindow *window, - int root_x, - int root_y) -{ - MetaRectangle rect; - - meta_window_get_frame_rect (window, &rect); - - return META_POINT_IN_RECT (root_x, root_y, rect); -} - -static gboolean -window_can_get_default_focus (MetaWindow *window, - MetaWorkspace *workspace) -{ - if (window->unmaps_pending > 0) - return FALSE; - - if (window->unmanaging) - return FALSE; - - if (!meta_window_is_focusable (window)) - return FALSE; - - if (!meta_window_showing_on_its_workspace (window)) - return FALSE; - - if (!meta_window_located_on_workspace (window, workspace)) - return FALSE; - - if (window->type == META_WINDOW_DOCK) - return FALSE; - - return TRUE; -} - -static MetaWindow * -get_default_focus_window (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one, - gboolean must_be_at_point, - int root_x, - int root_y) -{ - /* Find the topmost, focusable, mapped, window. - * not_this_one is being unfocused or going away, so exclude it. - */ - - GList *l; - - stack_ensure_sorted (stack); - - /* top of this layer is at the front of the list */ - for (l = stack->sorted; l != NULL; l = l->next) - { - MetaWindow *window = l->data; - - if (!window) - continue; - - if (window == not_this_one) - continue; - - if (!window_can_get_default_focus (window, workspace)) - continue; - - if (must_be_at_point && !window_contains_point (window, root_x, root_y)) - continue; - - return window; - } - - return NULL; -} - -MetaWindow * -meta_stack_get_default_focus_window_at_point (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one, - int root_x, - int root_y) -{ - g_return_val_if_fail (META_IS_STACK (stack), NULL); - g_return_val_if_fail (META_IS_WORKSPACE (workspace), NULL); - g_return_val_if_fail (!not_this_one || META_IS_WINDOW (not_this_one), NULL); - - return get_default_focus_window (stack, workspace, not_this_one, - TRUE, root_x, root_y); -} - -MetaWindow * -meta_stack_get_default_focus_window (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one) -{ - g_return_val_if_fail (META_IS_STACK (stack), NULL); - g_return_val_if_fail (META_IS_WORKSPACE (workspace), NULL); - g_return_val_if_fail (!not_this_one || META_IS_WINDOW (not_this_one), NULL); - - return get_default_focus_window (stack, workspace, not_this_one, - FALSE, 0, 0); -} - GList * meta_stack_list_windows (MetaStack *stack, MetaWorkspace *workspace) @@ -1139,26 +1036,6 @@ meta_stack_list_windows (MetaStack *stack, return workspace_windows; } -GList * -meta_stack_get_default_focus_candidates (MetaStack *stack, - MetaWorkspace *workspace) -{ - GList *windows = meta_stack_list_windows (stack, workspace); - GList *l; - - for (l = windows; l;) - { - GList *next = l->next; - - if (!window_can_get_default_focus (l->data, workspace)) - windows = g_list_delete_link (windows, l); - - l = next; - } - - return windows; -} - int meta_stack_windows_cmp (MetaStack *stack, MetaWindow *window_a, diff --git a/src/core/stack.h b/src/core/stack.h index ec5753fe7..a33fac45f 100644 --- a/src/core/stack.h +++ b/src/core/stack.h @@ -257,72 +257,6 @@ MetaWindow * meta_stack_get_below (MetaStack *stack, MetaWindow *window, gboolean only_within_layer); -/** - * meta_stack_get_default_focus_window: - * @stack: The stack to search. - * @workspace: %NULL to search all workspaces; otherwise only windows - * from that workspace will be returned. - * @not_this_one: Window to ignore because it's being unfocussed or - * going away. - * - * Find the topmost, focusable, mapped, window in a stack. If you supply - * a window as @not_this_one, we won't return that one (presumably - * because it's going to be going away). But if you do supply @not_this_one - * and we find its parent, we'll return that; and if @not_this_one is in - * a group, we'll return the top window of that group. - * - * Also, we are prejudiced against dock windows. Every kind of window, even - * the desktop, will be returned in preference to a dock window. - * - * Returns: The window matching all these constraints or %NULL if none does. - */ -MetaWindow * meta_stack_get_default_focus_window (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one); - -/** - * meta_stack_get_default_focus_window_at_point: - * @stack: The stack to search. - * @workspace: %NULL to search all workspaces; otherwise only windows - * from that workspace will be returned. - * @not_this_one: Window to ignore because it's being unfocussed or - * going away. - * @root_x: The returned window must contain this point, - * unless it's a dock. - * @root_y: See root_x. - * - * Find the topmost, focusable, mapped, window in a stack. If you supply - * a window as @not_this_one, we won't return that one (presumably - * because it's going to be going away). But if you do supply @not_this_one - * and we find its parent, we'll return that; and if @not_this_one is in - * a group, we'll return the top window of that group. - * - * Also, we are prejudiced against dock windows. Every kind of window, even - * the desktop, will be returned in preference to a dock window. - * - * Returns: The window matching all these constraints or %NULL if none does. - */ -MetaWindow * meta_stack_get_default_focus_window_at_point (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one, - int root_x, - int root_y); - -/** - * meta_stack_get_default_focus_candidates: - * @stack: The stack to examine. - * @workspace: If not %NULL, only windows on this workspace will be - * returned; otherwise all windows in the stack will be - * returned. - * - * Returns all the focus candidate windows in the stack, in order. - * - * Returns: (transfer container) (element-type Meta.Window): - * A #GList of #MetaWindow, in stacking order, honouring layers. - */ -GList * meta_stack_get_default_focus_candidates (MetaStack *stack, - MetaWorkspace *workspace); - /** * meta_stack_list_windows: * @stack: The stack to examine. @@ -403,4 +337,5 @@ void meta_stack_set_positions (MetaStack *stack, void meta_stack_update_window_tile_matches (MetaStack *stack, MetaWorkspace *workspace); + #endif diff --git a/src/core/window.c b/src/core/window.c index 0e27145e0..003437c3d 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -5058,9 +5058,15 @@ meta_window_update_appears_focused (MetaWindow *window) workspace = meta_window_get_workspace (window); if (workspace && workspace != workspace_manager->active_workspace) - appears_focused = window == meta_workspace_get_default_focus_window (workspace); + { + appears_focused = + window == meta_workspace_get_default_focus_window (workspace, NULL) && + meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK; + } else - appears_focused = window->has_focus || window->attached_focus_window; + { + appears_focused = window->has_focus || window->attached_focus_window; + } if (window->appears_focused == appears_focused) return; diff --git a/src/core/workspace-private.h b/src/core/workspace-private.h index f0d896f6c..6afd5562a 100644 --- a/src/core/workspace-private.h +++ b/src/core/workspace-private.h @@ -92,10 +92,16 @@ GList* meta_workspace_get_onscreen_region (MetaWorkspace *workspace); GList * meta_workspace_get_onmonitor_region (MetaWorkspace *workspace, MetaLogicalMonitor *logical_monitor); -MetaWindow * meta_workspace_get_default_focus_window (MetaWorkspace *workspace); void meta_workspace_focus_default_window (MetaWorkspace *workspace, MetaWindow *not_this_one, guint32 timestamp); +MetaWindow * meta_workspace_get_default_focus_window (MetaWorkspace *workspace, + MetaWindow *not_this_one); +MetaWindow * meta_workspace_get_default_focus_window_at_point (MetaWorkspace *workspace, + MetaWindow *not_this_one, + int root_x, + int root_y); +GList * meta_workspace_get_default_focus_candidates (MetaWorkspace *workspace); const char* meta_workspace_get_name (MetaWorkspace *workspace); diff --git a/src/core/workspace.c b/src/core/workspace.c index 29cc302ae..03b177e55 100644 --- a/src/core/workspace.c +++ b/src/core/workspace.c @@ -39,6 +39,7 @@ #include #include "backends/meta-backend-private.h" +#include "backends/meta-cursor-tracker-private.h" #include "backends/meta-logical-monitor.h" #include "cogl/cogl.h" #include "core/boxes-private.h" @@ -53,6 +54,8 @@ void meta_workspace_queue_calc_showing (MetaWorkspace *workspace); static void focus_ancestor_or_mru_window (MetaWorkspace *workspace, MetaWindow *not_this_one, guint32 timestamp); +static MetaWindow * get_pointer_window (MetaWorkspace *workspace, + MetaWindow *not_this_one); G_DEFINE_TYPE (MetaWorkspace, meta_workspace, G_TYPE_OBJECT); @@ -1330,7 +1333,8 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace, else { MetaWindow * window; - window = meta_display_get_pointer_window (workspace->display, not_this_one); + + window = get_pointer_window (workspace, not_this_one); if (window && window->type != META_WINDOW_DOCK && window->type != META_WINDOW_DESKTOP) @@ -1381,7 +1385,8 @@ is_focusable (MetaWindow *window, MetaWorkspace *workspace) { return !window->unmanaging && - window->mapped && + window->unmaps_pending == 0 && + window->type != META_WINDOW_DOCK && meta_window_is_focusable (window) && meta_window_located_on_workspace (window, workspace) && meta_window_showing_on_its_workspace (window); @@ -1402,11 +1407,91 @@ find_focusable_ancestor (MetaWindow *window, return TRUE; } -static MetaWindow * -get_default_focus_window (MetaWorkspace *workspace, - MetaWindow *not_this_one) +GList * +meta_workspace_get_default_focus_candidates (MetaWorkspace *workspace) { GList *l; + GList *candidates = NULL; + + for (l = workspace->mru_list; l; l = l->next) + { + MetaWindow *window = l->data; + + g_assert (window); + + if (!is_focusable (window, workspace)) + continue; + + candidates = g_list_prepend (candidates, window); + } + + return candidates; +} + +static gboolean +window_contains_point (MetaWindow *window, + int root_x, + int root_y) +{ + MetaRectangle rect; + + meta_window_get_frame_rect (window, &rect); + + return META_POINT_IN_RECT (root_x, root_y, rect); +} + +MetaWindow * +meta_workspace_get_default_focus_window_at_point (MetaWorkspace *workspace, + MetaWindow *not_this_one, + int root_x, + int root_y) +{ + g_autoptr (GList) sorted = NULL; + GList *l; + MetaStack *stack; + + g_return_val_if_fail (META_IS_WORKSPACE (workspace), NULL); + g_return_val_if_fail (!not_this_one || META_IS_WINDOW (not_this_one), NULL); + + stack = workspace->display->stack; + + g_return_val_if_fail (META_IS_STACK (stack), NULL); + + /* Find the topmost, focusable, mapped, window. + * not_this_one is being unfocused or going away, so exclude it. + */ + sorted = g_list_reverse (meta_stack_list_windows (stack, workspace)); + + /* top of this layer is at the front of the list */ + for (l = sorted; l != NULL; l = l->next) + { + MetaWindow *window = l->data; + + g_assert (window); + + if (window == not_this_one) + continue; + + if (!is_focusable (window, workspace)) + continue; + + if (!window_contains_point (window, root_x, root_y)) + continue; + + return window; + } + + return NULL; +} + +MetaWindow * +meta_workspace_get_default_focus_window (MetaWorkspace *workspace, + MetaWindow *not_this_one) +{ + GList *l; + + g_return_val_if_fail (META_IS_WORKSPACE (workspace), NULL); + g_return_val_if_fail (!not_this_one || META_IS_WINDOW (not_this_one), NULL); for (l = workspace->mru_list; l; l = l->next) { @@ -1426,17 +1511,23 @@ get_default_focus_window (MetaWorkspace *workspace, return NULL; } -MetaWindow * -meta_workspace_get_default_focus_window (MetaWorkspace *workspace) +static MetaWindow * +get_pointer_window (MetaWorkspace *workspace, + MetaWindow *not_this_one) { - if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK) - { - return get_default_focus_window (workspace, NULL); - } - else - { - return NULL; - } + MetaBackend *backend = meta_get_backend (); + MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); + graphene_point_t point; + + if (not_this_one) + meta_topic (META_DEBUG_FOCUS, + "Focusing mouse window excluding %s", not_this_one->desc); + + meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL); + + return meta_workspace_get_default_focus_window_at_point (workspace, + not_this_one, + point.x, point.y); } static gboolean @@ -1515,7 +1606,7 @@ focus_ancestor_or_mru_window (MetaWorkspace *workspace, } } - window = get_default_focus_window (workspace, not_this_one); + window = meta_workspace_get_default_focus_window (workspace, not_this_one); if (window) { diff --git a/src/wayland/meta-xwayland-dnd.c b/src/wayland/meta-xwayland-dnd.c index 0aa4c5efb..7c6de409b 100644 --- a/src/wayland/meta-xwayland-dnd.c +++ b/src/wayland/meta-xwayland-dnd.c @@ -35,6 +35,7 @@ #include #include "core/meta-workspace-manager-private.h" +#include "core/workspace-private.h" #include "meta/meta-x11-errors.h" #include "wayland/meta-wayland-data-device.h" #include "wayland/meta-xwayland-private.h" @@ -726,10 +727,9 @@ pick_drop_surface (MetaWaylandCompositor *compositor, graphene_point_t pos; clutter_event_get_coords (event, &pos.x, &pos.y); - focus_window = meta_stack_get_default_focus_window_at_point (display->stack, - workspace, - NULL, - pos.x, pos.y); + focus_window = meta_workspace_get_default_focus_window_at_point (workspace, + NULL, + pos.x, pos.y); return focus_window ? focus_window->surface : NULL; } diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c index 4e5ab9340..ac9450669 100644 --- a/src/x11/window-x11.c +++ b/src/x11/window-x11.c @@ -901,7 +901,6 @@ maybe_focus_default_window (MetaDisplay *display, guint32 timestamp) { MetaWorkspace *workspace; - MetaStack *stack = display->stack; g_autoptr (GList) focusable_windows = NULL; g_autoptr (GQueue) focus_candidates = NULL; GList *l; @@ -917,7 +916,7 @@ maybe_focus_default_window (MetaDisplay *display, * focused window, will stop the chained requests. */ focusable_windows = - meta_stack_get_default_focus_candidates (stack, workspace); + meta_workspace_get_default_focus_candidates (workspace); focus_candidates = g_queue_new (); for (l = g_list_last (focusable_windows); l; l = l->prev)