core: Focus on most recently focused window when switching workspaces

When switching workspaces we previously focused on whatever window is on
top of the stack. If a window is marked as "always on top" then it would
always receive focus when switching workspaces.

Fixes #2240
Fixes gnome-shell#5162
Fixes #178
Fixes #678

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2489>
This commit is contained in:
Sebastian Wick 2022-06-29 15:44:11 +02:00 committed by Marge Bot
parent deae8aa7b1
commit 3a96ef023b

View File

@ -50,7 +50,7 @@
#include "x11/meta-x11-display-private.h" #include "x11/meta-x11-display-private.h"
void meta_workspace_queue_calc_showing (MetaWorkspace *workspace); void meta_workspace_queue_calc_showing (MetaWorkspace *workspace);
static void focus_ancestor_or_top_window (MetaWorkspace *workspace, static void focus_ancestor_or_mru_window (MetaWorkspace *workspace,
MetaWindow *not_this_one, MetaWindow *not_this_one,
guint32 timestamp); guint32 timestamp);
@ -1313,20 +1313,6 @@ meta_workspace_get_name (MetaWorkspace *workspace)
return meta_prefs_get_workspace_name (meta_workspace_index (workspace)); return meta_prefs_get_workspace_name (meta_workspace_index (workspace));
} }
MetaWindow *
meta_workspace_get_default_focus_window (MetaWorkspace *workspace)
{
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
{
return meta_stack_get_default_focus_window (workspace->display->stack,
workspace, NULL);
}
else
{
return NULL;
}
}
void void
meta_workspace_focus_default_window (MetaWorkspace *workspace, meta_workspace_focus_default_window (MetaWorkspace *workspace,
MetaWindow *not_this_one, MetaWindow *not_this_one,
@ -1338,7 +1324,9 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK || if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
!workspace->display->mouse_mode) !workspace->display->mouse_mode)
focus_ancestor_or_top_window (workspace, not_this_one, timestamp); {
focus_ancestor_or_mru_window (workspace, not_this_one, timestamp);
}
else else
{ {
MetaWindow * window; MetaWindow * window;
@ -1375,7 +1363,9 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
} }
} }
else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_SLOPPY) else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_SLOPPY)
focus_ancestor_or_top_window (workspace, not_this_one, timestamp); {
focus_ancestor_or_mru_window (workspace, not_this_one, timestamp);
}
else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_MOUSE) else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_MOUSE)
{ {
meta_topic (META_DEBUG_FOCUS, meta_topic (META_DEBUG_FOCUS,
@ -1386,18 +1376,24 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
} }
} }
static gboolean
is_focusable (MetaWindow *window,
MetaWorkspace *workspace)
{
return !window->unmanaging &&
window->mapped &&
meta_window_is_focusable (window) &&
meta_window_located_on_workspace (window, workspace) &&
meta_window_showing_on_its_workspace (window);
}
static gboolean static gboolean
find_focusable_ancestor (MetaWindow *window, find_focusable_ancestor (MetaWindow *window,
gpointer user_data) gpointer user_data)
{ {
MetaWorkspaceFocusableAncestorData *data = user_data; MetaWorkspaceFocusableAncestorData *data = user_data;
if (!window->unmanaging && if (is_focusable (window, data->workspace) && !window->hidden)
window->mapped &&
!window->hidden &&
meta_window_is_focusable (window) &&
meta_window_located_on_workspace (window, data->workspace) &&
meta_window_showing_on_its_workspace (window))
{ {
data->out_window = window; data->out_window = window;
return FALSE; return FALSE;
@ -1406,6 +1402,43 @@ find_focusable_ancestor (MetaWindow *window,
return TRUE; return TRUE;
} }
static MetaWindow *
get_default_focus_window (MetaWorkspace *workspace,
MetaWindow *not_this_one)
{
GList *l;
for (l = workspace->mru_list; l; l = l->next)
{
MetaWindow *window = l->data;
g_assert (window);
if (window == not_this_one)
continue;
if (!is_focusable (window, workspace))
continue;
return window;
}
return NULL;
}
MetaWindow *
meta_workspace_get_default_focus_window (MetaWorkspace *workspace)
{
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
{
return get_default_focus_window (workspace, NULL);
}
else
{
return NULL;
}
}
static gboolean static gboolean
try_to_set_focus_and_check (MetaWindow *window, try_to_set_focus_and_check (MetaWindow *window,
MetaWindow *not_this_one, MetaWindow *not_this_one,
@ -1440,7 +1473,7 @@ try_to_set_focus_and_check (MetaWindow *window,
/* Focus ancestor of not_this_one if there is one */ /* Focus ancestor of not_this_one if there is one */
static void static void
focus_ancestor_or_top_window (MetaWorkspace *workspace, focus_ancestor_or_mru_window (MetaWorkspace *workspace,
MetaWindow *not_this_one, MetaWindow *not_this_one,
guint32 timestamp) guint32 timestamp)
{ {
@ -1482,9 +1515,7 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
} }
} }
window = meta_stack_get_default_focus_window (workspace->display->stack, window = get_default_focus_window (workspace, not_this_one);
workspace,
not_this_one);
if (window) if (window)
{ {