[mutter] core: Focus on most recently focused window when switching workspaces



commit 3a96ef023b9e881d51d8c3b89c59c5f2ffb18852
Author: Sebastian Wick <sebastian wick redhat com>
Date:   Wed Jun 29 15:44:11 2022 +0200

    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>

 src/core/workspace.c | 85 +++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 58 insertions(+), 27 deletions(-)
---
diff --git a/src/core/workspace.c b/src/core/workspace.c
index e0e64a6b49..29cc302aef 100644
--- a/src/core/workspace.c
+++ b/src/core/workspace.c
@@ -50,7 +50,7 @@
 #include "x11/meta-x11-display-private.h"
 
 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,
                                           guint32        timestamp);
 
@@ -1313,20 +1313,6 @@ meta_workspace_get_name (MetaWorkspace *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
 meta_workspace_focus_default_window (MetaWorkspace *workspace,
                                      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 ||
       !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
     {
       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)
-        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)
         {
           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
 find_focusable_ancestor (MetaWindow *window,
                          gpointer    user_data)
 {
   MetaWorkspaceFocusableAncestorData *data = user_data;
 
-  if (!window->unmanaging &&
-      window->mapped &&
-      !window->hidden &&
-      meta_window_is_focusable (window) &&
-      meta_window_located_on_workspace (window, data->workspace) &&
-      meta_window_showing_on_its_workspace (window))
+  if (is_focusable (window, data->workspace) && !window->hidden)
     {
       data->out_window = window;
       return FALSE;
@@ -1406,6 +1402,43 @@ find_focusable_ancestor (MetaWindow *window,
   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
 try_to_set_focus_and_check (MetaWindow *window,
                             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 */
 static void
-focus_ancestor_or_top_window (MetaWorkspace *workspace,
+focus_ancestor_or_mru_window (MetaWorkspace *workspace,
                               MetaWindow    *not_this_one,
                               guint32        timestamp)
 {
@@ -1482,9 +1515,7 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
         }
     }
 
-  window = meta_stack_get_default_focus_window (workspace->display->stack,
-                                                workspace,
-                                                not_this_one);
+  window = get_default_focus_window (workspace, not_this_one);
 
   if (window)
     {


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