summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Kareh <[email protected]>2026-02-09 15:20:10 -0500
committerVictor Kareh <[email protected]>2026-02-09 15:44:58 -0500
commitbedb38d90427cb1de69fe618cb536d5e3a3514e7 (patch)
treec21400b7ce5d8c19331f75b002d113f5a0e045db
parent7e6aede0af4db55a2db687bae64f5ffdbf05e92f (diff)
downloadmarco-global-mru-window-list.tar.bz2
marco-global-mru-window-list.tar.xz
display: Use global MRU list for switch-windows-allglobal-mru-window-list
When using switch-windows-all to cycle through windows across all workspaces, marco was grouping windows by workspace rather than using a global MRU (most-recently-used) list. This caused several issues: - Sticky windows appeared multiple times, once per workspace - Window order was confusing (since they were grouped by workspace number) - Behavior was different from other window managers Fixed by collecting all windows, sorting them by recency, then building the tab list from this global list. Fixes #286
-rw-r--r--src/core/display.c88
-rw-r--r--src/core/window-private.h2
-rw-r--r--src/core/window.c6
3 files changed, 57 insertions, 39 deletions
diff --git a/src/core/display.c b/src/core/display.c
index 88b7e907..ac63a3c6 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -4705,72 +4705,80 @@ find_tab_backward (MetaDisplay *display,
return NULL;
}
+static int
+mru_cmp (gconstpointer a,
+ gconstpointer b)
+{
+ guint32 time_a, time_b;
+
+ time_a = meta_window_get_user_time ((MetaWindow *)a);
+ time_b = meta_window_get_user_time ((MetaWindow *)b);
+
+ if (time_a > time_b)
+ return -1;
+ else if (time_a < time_b)
+ return 1;
+ else
+ return 0;
+}
+
GList*
meta_display_get_tab_list (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *active_workspace)
{
- GList *tab_list, *workspace_list, *l, link;
- MetaWorkspace *workspace;
+ GList *tab_list, *mru_list, *l;
g_return_val_if_fail (active_workspace != NULL, NULL);
+ /* Build MRU list based on whether we use global or per-workspace */
if (type == META_TAB_LIST_NORMAL_ALL_WORKSPACES)
{
- workspace_list = screen->workspaces;
+ /* Create global MRU list sorted by user_time */
+ GSList *windows = meta_display_list_windows (display);
+ GSList *w;
+
+ mru_list = NULL;
+ for (w = windows; w; w = w->next)
+ {
+ MetaWindow *window = w->data;
+ if (window->screen == screen)
+ mru_list = g_list_prepend (mru_list, window);
+ }
+
+ mru_list = g_list_sort (mru_list, mru_cmp);
+
+ g_slist_free (windows);
type = META_TAB_LIST_NORMAL;
}
else
{
- link.next = NULL;
- link.prev = NULL;
- link.data = active_workspace;
- workspace_list = &link;
+ mru_list = g_list_copy (active_workspace->mru_list);
}
tab_list = NULL;
/* Windows sellout mode - MRU order. Collect unminimized windows
* then minimized so minimized windows aren't in the way so much.
*/
- for (l = workspace_list; l != NULL; l = l->next)
+ for (l = mru_list; l != NULL; l = l->next)
{
- GList *tmp;
-
- workspace = l->data;
+ MetaWindow *window = l->data;
- tmp = workspace->mru_list;
- while (tmp != NULL)
- {
- MetaWindow *window = tmp->data;
-
- if (!window->minimized &&
- window->screen == screen &&
- IN_TAB_CHAIN (window, type))
- tab_list = g_list_prepend (tab_list, window);
-
- tmp = tmp->next;
- }
+ if (!window->minimized &&
+ window->screen == screen &&
+ IN_TAB_CHAIN (window, type))
+ tab_list = g_list_prepend (tab_list, window);
}
- for (l = workspace_list; l != NULL; l = l->next)
+ for (l = mru_list; l != NULL; l = l->next)
{
- GList *tmp;
-
- workspace = l->data;
+ MetaWindow *window = l->data;
- tmp = workspace->mru_list;
- while (tmp != NULL)
- {
- MetaWindow *window = tmp->data;
-
- if (window->minimized &&
- window->screen == screen &&
- IN_TAB_CHAIN (window, type))
- tab_list = g_list_prepend (tab_list, window);
-
- tmp = tmp->next;
- }
+ if (window->minimized &&
+ window->screen == screen &&
+ IN_TAB_CHAIN (window, type))
+ tab_list = g_list_prepend (tab_list, window);
}
tab_list = g_list_reverse (tab_list);
@@ -4801,6 +4809,8 @@ meta_display_get_tab_list (MetaDisplay *display,
g_slist_free (windows);
}
+ g_list_free (mru_list);
+
return tab_list;
}
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 06d4fd65..8ce9a121 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -695,6 +695,8 @@ void meta_window_stack_just_below (MetaWindow *window,
void meta_window_set_user_time (MetaWindow *window,
guint32 timestamp);
+guint32 meta_window_get_user_time (MetaWindow *window);
+
void meta_window_set_demands_attention (MetaWindow *window);
void meta_window_unset_demands_attention (MetaWindow *window);
diff --git a/src/core/window.c b/src/core/window.c
index 134cf7bb..cdf7ab3b 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -8839,6 +8839,12 @@ meta_window_set_user_time (MetaWindow *window,
}
}
+guint32
+meta_window_get_user_time (MetaWindow *window)
+{
+ return window->net_wm_user_time;
+}
+
/* Sets the demands_attention hint on a window, but only
* if it's at least partially obscured (see #305882).
*/