core: Move remaining default focus window handling to workspace

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2489>
This commit is contained in:
Sebastian Wick 2022-07-12 00:45:43 +02:00 committed by Marge Bot
parent 3a96ef023b
commit b4b9a7c90f
9 changed files with 129 additions and 242 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -39,6 +39,7 @@
#include <string.h>
#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)
{

View File

@ -35,6 +35,7 @@
#include <X11/extensions/Xfixes.h>
#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;
}

View File

@ -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)