diff options
| author | Victor Kareh <[email protected]> | 2026-02-09 15:20:10 -0500 |
|---|---|---|
| committer | Victor Kareh <[email protected]> | 2026-02-09 15:44:58 -0500 |
| commit | bedb38d90427cb1de69fe618cb536d5e3a3514e7 (patch) | |
| tree | c21400b7ce5d8c19331f75b002d113f5a0e045db | |
| parent | 7e6aede0af4db55a2db687bae64f5ffdbf05e92f (diff) | |
| download | marco-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.c | 88 | ||||
| -rw-r--r-- | src/core/window-private.h | 2 | ||||
| -rw-r--r-- | src/core/window.c | 6 |
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). */ |
