From 2fc880db192cd995bb86697f999295b20fefeed7 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 15 Aug 2003 22:09:55 +0000 Subject: [PATCH] Changed MRU list to be per workspace instead of per display, so sticky 2003-08-15 Ray Strode Changed MRU list to be per workspace instead of per display, so sticky windows don't hijack the window focus after workspace switching (Bug #97635). * src/delete.c (meta_window_delete): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/display.c (meta_display_open): Stop using display->mru_list. (find_tab_forward): (find_tab_backward): (meta_display_get_tab_list): Use workspace->mru_list instead of display->mru_list and remove unneeded calls to meta_window_visible_on_workspace * src/display.h: Remove mru_list from MetaDisplay * src/keybindings.c (handle_toggle_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.c (meta_screen_focus_top_window): (meta_screen_focus_default_window): Remove functions. (meta_screen_show_desktop): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window. * src/screen.h: Remove meta_screen_focus_top_window and meta_screen_focus_default_window declarations. * src/window.c (meta_window_new): Stop using display->mru_list. (meta_window_free): Use meta_workspace_focus_top_window instead of meta_screen_focus_top_window and stop using display->mru_list. (meta_window_stick): Add sticky window to all workspace MRU lists. (meta_window_unstick): Remove non-sticky window from the workspace MRU lists it doesn't belong in. (meta_window_notify_focus): Move newly focused window to the front of active workspace's MRU list. * src/workspace.c (meta_workspace_new): Initialize workspace->mru_list to NULL. (meta_workspace_add_window): Add window to workspace's MRU list. (meta_workspace_remove_window): Remove window from workspace's MRU list. (meta_workspace_activate_with_focus): Use meta_workspace_focus_default_window instead of meta_screen_focus_default_window. (meta_workspace_focus_default_window): (meta_workspace_focus_mru_window): (meta_workspace_focus_top_window): Add functions. * src/workspace.h: Add mru_list to MetaWorkspace and add function declarations for meta_workspace_focus_default_window, meta_workspace_focus_mru_window, meta_workspace_focus_top_window. --- ChangeLog | 57 ++++++++++++++++++++++++++++ src/delete.c | 4 +- src/display.c | 37 +++++++------------ src/display.h | 5 --- src/keybindings.c | 2 +- src/screen.c | 45 +---------------------- src/screen.h | 5 --- src/window.c | 61 ++++++++++++++++++++++-------- src/workspace.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++- src/workspace.h | 10 +++-- 10 files changed, 221 insertions(+), 99 deletions(-) diff --git a/ChangeLog b/ChangeLog index 970ae378e..a50f1f1d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,60 @@ +2003-08-15 Ray Strode + + Changed MRU list to be per workspace instead of per display, so + sticky windows don't hijack the window focus after workspace + switching (Bug #97635). + + * src/delete.c (meta_window_delete): Use + meta_workspace_focus_top_window instead of + meta_screen_focus_top_window. + + * src/display.c (meta_display_open): Stop using display->mru_list. + (find_tab_forward): + (find_tab_backward): + (meta_display_get_tab_list): Use workspace->mru_list instead of + display->mru_list and remove unneeded calls to + meta_window_visible_on_workspace + + * src/display.h: Remove mru_list from MetaDisplay + + * src/keybindings.c (handle_toggle_desktop): Use + meta_workspace_focus_top_window instead of + meta_screen_focus_top_window. + + * src/screen.c (meta_screen_focus_top_window): + (meta_screen_focus_default_window): Remove functions. + (meta_screen_show_desktop): Use meta_workspace_focus_top_window + instead of meta_screen_focus_top_window. + + * src/screen.h: Remove meta_screen_focus_top_window and + meta_screen_focus_default_window declarations. + + * src/window.c (meta_window_new): Stop using display->mru_list. + (meta_window_free): Use meta_workspace_focus_top_window + instead of meta_screen_focus_top_window and stop using + display->mru_list. + (meta_window_stick): Add sticky window to all workspace MRU lists. + (meta_window_unstick): Remove non-sticky window from the workspace + MRU lists it doesn't belong in. + (meta_window_notify_focus): Move newly focused window to the front + of active workspace's MRU list. + + * src/workspace.c (meta_workspace_new): Initialize + workspace->mru_list to NULL. + (meta_workspace_add_window): Add window to workspace's MRU list. + (meta_workspace_remove_window): Remove window from workspace's MRU + list. + (meta_workspace_activate_with_focus): Use + meta_workspace_focus_default_window instead of + meta_screen_focus_default_window. + (meta_workspace_focus_default_window): + (meta_workspace_focus_mru_window): + (meta_workspace_focus_top_window): Add functions. + + * src/workspace.h: Add mru_list to MetaWorkspace and add function + declarations for meta_workspace_focus_default_window, + meta_workspace_focus_mru_window, meta_workspace_focus_top_window. + 2003-08-14 Rob Adams Allow windows that are too tall for the workarea to break the diff --git a/src/delete.c b/src/delete.c index 5e95449b6..061c892e8 100644 --- a/src/delete.c +++ b/src/delete.c @@ -23,6 +23,7 @@ #include "util.h" #include "window.h" #include "errors.h" +#include "workspace.h" #include #include @@ -387,7 +388,8 @@ meta_window_delete (MetaWindow *window, meta_topic (META_DEBUG_FOCUS, "Focusing top window because focus window %s was deleted/killed\n", window->desc); - meta_screen_focus_top_window (window->screen, window); + meta_workspace_focus_top_window (window->screen->active_workspace, + window); } else { diff --git a/src/display.c b/src/display.c index 2856dbc76..d04e0b359 100644 --- a/src/display.c +++ b/src/display.c @@ -310,7 +310,6 @@ meta_display_open (const char *name) display->autoraise_timeout_id = 0; display->focus_window = NULL; display->expected_focus_window = NULL; - display->mru_list = NULL; #ifdef HAVE_XSYNC display->grab_update_alarm = None; @@ -3417,6 +3416,7 @@ find_tab_forward (MetaDisplay *display, GList *tmp; g_return_val_if_fail (start != NULL, NULL); + g_return_val_if_fail (workspace != NULL, NULL); tmp = start->next; while (tmp != NULL) @@ -3424,22 +3424,18 @@ find_tab_forward (MetaDisplay *display, MetaWindow *window = tmp->data; if (window->screen == screen && - IN_TAB_CHAIN (window, type) && - (workspace == NULL || - meta_window_visible_on_workspace (window, workspace))) + IN_TAB_CHAIN (window, type)) return window; tmp = tmp->next; } - tmp = display->mru_list; + tmp = workspace->mru_list; while (tmp != start) { MetaWindow *window = tmp->data; - if (IN_TAB_CHAIN (window, type) && - (workspace == NULL || - meta_window_visible_on_workspace (window, workspace))) + if (IN_TAB_CHAIN (window, type)) return window; tmp = tmp->next; @@ -3458,6 +3454,7 @@ find_tab_backward (MetaDisplay *display, GList *tmp; g_return_val_if_fail (start != NULL, NULL); + g_return_val_if_fail (workspace != NULL, NULL); tmp = start->prev; while (tmp != NULL) @@ -3465,22 +3462,18 @@ find_tab_backward (MetaDisplay *display, MetaWindow *window = tmp->data; if (window->screen == screen && - IN_TAB_CHAIN (window, type) && - (workspace == NULL || - meta_window_visible_on_workspace (window, workspace))) + IN_TAB_CHAIN (window, type)) return window; tmp = tmp->prev; } - tmp = g_list_last (display->mru_list); + tmp = g_list_last (workspace->mru_list); while (tmp != start) { MetaWindow *window = tmp->data; - if (IN_TAB_CHAIN (window, type) && - (workspace == NULL || - meta_window_visible_on_workspace (window, workspace))) + if (IN_TAB_CHAIN (window, type)) return window; tmp = tmp->prev; @@ -3497,7 +3490,7 @@ meta_display_get_tab_list (MetaDisplay *display, { GList *tab_list; - /* workspace can be NULL for all workspaces */ + g_return_val_if_fail (workspace != NULL, NULL); /* Windows sellout mode - MRU order. Collect unminimized windows * then minimized so minimized windows aren't in the way so much. @@ -3506,16 +3499,14 @@ meta_display_get_tab_list (MetaDisplay *display, GList *tmp; tab_list = NULL; - tmp = screen->display->mru_list; + tmp = workspace->mru_list; while (tmp != NULL) { MetaWindow *window = tmp->data; if (!window->minimized && window->screen == screen && - IN_TAB_CHAIN (window, type) && - (workspace == NULL || - meta_window_visible_on_workspace (window, workspace))) + IN_TAB_CHAIN (window, type)) tab_list = g_list_prepend (tab_list, window); tmp = tmp->next; @@ -3525,16 +3516,14 @@ meta_display_get_tab_list (MetaDisplay *display, { GList *tmp; - tmp = screen->display->mru_list; + tmp = workspace->mru_list; while (tmp != NULL) { MetaWindow *window = tmp->data; if (window->minimized && window->screen == screen && - IN_TAB_CHAIN (window, type) && - (workspace == NULL || - meta_window_visible_on_workspace (window, workspace))) + IN_TAB_CHAIN (window, type)) tab_list = g_list_prepend (tab_list, window); tmp = tmp->next; diff --git a/src/display.h b/src/display.h index 4c8800250..f96253d61 100644 --- a/src/display.h +++ b/src/display.h @@ -179,11 +179,6 @@ struct _MetaDisplay */ MetaWindow *expected_focus_window; - /* Most recently focused list. Always contains all - * live windows. - */ - GList *mru_list; - guint static_gravity_works : 1; /*< private-ish >*/ diff --git a/src/keybindings.c b/src/keybindings.c index 0b2eb6671..ab0a91406 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -2609,7 +2609,7 @@ handle_toggle_desktop (MetaDisplay *display, if (screen->showing_desktop) { meta_screen_unshow_desktop (screen); - meta_screen_focus_top_window (screen, NULL); + meta_workspace_focus_top_window (screen->active_workspace, NULL); } else meta_screen_show_desktop (screen); diff --git a/src/screen.c b/src/screen.c index 7a287f171..348d467bb 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1188,39 +1188,6 @@ meta_screen_ensure_workspace_popup (MetaScreen *screen) /* don't show tab popup, since proper space isn't selected yet */ } -/* Focus top window on active workspace */ -void -meta_screen_focus_top_window (MetaScreen *screen, - MetaWindow *not_this_one) -{ - MetaWindow *window; - - if (not_this_one) - meta_topic (META_DEBUG_FOCUS, - "Focusing top window excluding %s\n", not_this_one->desc); - - window = meta_stack_get_default_focus_window (screen->stack, - screen->active_workspace, - not_this_one); - - /* FIXME I'm a loser on the CurrentTime front */ - if (window) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing top window %s\n", window->desc); - - meta_window_focus (window, meta_display_get_current_time (screen->display)); - - /* Also raise the window if in click-to-focus */ - if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK) - meta_window_raise (window); - } - else - { - meta_topic (META_DEBUG_FOCUS, "No top window to focus found\n"); - } -} - void meta_screen_focus_mouse_window (MetaScreen *screen, MetaWindow *not_this_one) @@ -1271,16 +1238,6 @@ meta_screen_focus_mouse_window (MetaScreen *screen, } } -void -meta_screen_focus_default_window (MetaScreen *screen, - MetaWindow *not_this_one) -{ - if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK) - meta_screen_focus_top_window (screen, not_this_one); - else - meta_screen_focus_mouse_window (screen, not_this_one); -} - const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_rect (MetaScreen *screen, MetaRectangle *rect) @@ -2199,7 +2156,7 @@ meta_screen_show_desktop (MetaScreen *screen) update_showing_desktop_hint (screen); - meta_screen_focus_top_window (screen, NULL); + meta_workspace_focus_top_window (screen->active_workspace, NULL); } void diff --git a/src/screen.h b/src/screen.h index 677f7faa9..64fa4948c 100644 --- a/src/screen.h +++ b/src/screen.h @@ -134,13 +134,8 @@ void meta_screen_ensure_tab_popup (MetaScreen *scree void meta_screen_ensure_workspace_popup (MetaScreen *screen); -void meta_screen_focus_top_window (MetaScreen *screen, - MetaWindow *not_this_one); void meta_screen_focus_mouse_window (MetaScreen *screen, MetaWindow *not_this_one); -void meta_screen_focus_default_window (MetaScreen *screen, - MetaWindow *not_this_one); - const MetaXineramaScreenInfo* meta_screen_get_current_xinerama (MetaScreen *screen); const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_rect (MetaScreen *screen, diff --git a/src/window.c b/src/window.c index b831c1cf5..c18e59ea4 100644 --- a/src/window.c +++ b/src/window.c @@ -657,10 +657,6 @@ meta_window_new (MetaDisplay *display, window->size_hints.width, window->size_hints.height); - /* add to MRU list */ - window->display->mru_list = - g_list_append (window->display->mru_list, window); - meta_stack_add (window->screen->stack, window); @@ -883,7 +879,7 @@ meta_window_free (MetaWindow *window) meta_topic (META_DEBUG_FOCUS, "Focusing top window since we're unmanaging %s\n", window->desc); - meta_screen_focus_top_window (window->screen, window); + meta_workspace_focus_top_window (window->screen->active_workspace, window); } else if (window->display->expected_focus_window == window) { @@ -891,7 +887,7 @@ meta_window_free (MetaWindow *window) "Focusing top window since expected focus window freed %s\n", window->desc); window->display->expected_focus_window = NULL; - meta_screen_focus_top_window (window->screen, window); + meta_workspace_focus_top_window (window->screen->active_workspace, window); } else { @@ -920,9 +916,6 @@ meta_window_free (MetaWindow *window) if (window->display->focus_window == window) window->display->focus_window = NULL; - window->display->mru_list = - g_list_remove (window->display->mru_list, window); - meta_window_unqueue_calc_showing (window); meta_window_unqueue_move_resize (window); meta_window_unqueue_update_icon (window); @@ -1763,7 +1756,7 @@ meta_window_minimize (MetaWindow *window) meta_topic (META_DEBUG_FOCUS, "Focusing top window due to minimization of focus window %s\n", window->desc); - meta_screen_focus_top_window (window->screen, window); + meta_workspace_focus_top_window (window->screen->active_workspace, window); } else { @@ -3194,6 +3187,9 @@ meta_window_change_workspace (MetaWindow *window, void meta_window_stick (MetaWindow *window) { + GList *tmp; + MetaWorkspace *workspace; + meta_verbose ("Sticking window %s current on_all_workspaces = %d\n", window->desc, window->on_all_workspaces); @@ -3206,6 +3202,18 @@ meta_window_stick (MetaWindow *window) */ window->on_all_workspaces = TRUE; + /* We do, however, change the MRU lists of all the workspaces + */ + tmp = window->workspaces; + while (tmp) + { + workspace = (MetaWorkspace *) tmp->data; + if (!g_list_find (workspace->mru_list, window)) + g_list_append (workspace->mru_list, window); + + tmp = tmp->next; + } + meta_window_set_current_workspace_hint (window); meta_window_queue_calc_showing (window); @@ -3214,6 +3222,9 @@ meta_window_stick (MetaWindow *window) void meta_window_unstick (MetaWindow *window) { + GList *tmp; + MetaWorkspace *workspace; + if (!window->on_all_workspaces) return; @@ -3221,6 +3232,16 @@ meta_window_unstick (MetaWindow *window) window->on_all_workspaces = FALSE; + /* Remove window from MRU lists that it doesn't belong in */ + tmp = window->workspaces; + while (tmp) + { + workspace = (MetaWorkspace *) tmp->data; + if (!meta_workspace_contains_window (workspace, window)) + g_list_remove (workspace->mru_list, window); + tmp = tmp->next; + } + /* We change ourselves to the active workspace, since otherwise you'd get * a weird window-vaporization effect. Once we have UI for being * on more than one workspace this should probably be add_workspace @@ -3946,11 +3967,21 @@ meta_window_notify_focus (MetaWindow *window, "* Focus --> %s\n", window->desc); window->display->focus_window = window; window->has_focus = TRUE; - /* Move to the front of the MRU list */ - window->display->mru_list = - g_list_remove (window->display->mru_list, window); - window->display->mru_list = - g_list_prepend (window->display->mru_list, window); + + /* Move to the front of the focusing workspace's MRU list + * FIXME: is the active workspace guaranteed to be the focusing + * workspace? + */ + if (window->screen->active_workspace) + { + window->screen->active_workspace->mru_list = + g_list_remove (window->screen->active_workspace->mru_list, + window); + window->screen->active_workspace->mru_list = + g_list_prepend (window->screen->active_workspace->mru_list, + window); + } + if (window->frame) meta_frame_queue_draw (window->frame); diff --git a/src/workspace.c b/src/workspace.c index 09dc25a51..dc73879f7 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -41,6 +41,7 @@ meta_workspace_new (MetaScreen *screen) workspace->screen->workspaces = g_list_append (workspace->screen->workspaces, workspace); workspace->windows = NULL; + workspace->mru_list = NULL; workspace->work_areas = NULL; workspace->work_areas_invalid = TRUE; @@ -113,6 +114,8 @@ meta_workspace_add_window (MetaWorkspace *workspace, workspace->windows = g_list_prepend (workspace->windows, window); window->workspaces = g_list_prepend (window->workspaces, workspace); + workspace->mru_list = g_list_append (workspace->mru_list, window); + meta_window_set_current_workspace_hint (window); meta_window_queue_calc_showing (window); @@ -138,6 +141,7 @@ meta_workspace_remove_window (MetaWorkspace *workspace, workspace->windows = g_list_remove (workspace->windows, window); window->workspaces = g_list_remove (window->workspaces, workspace); + workspace->mru_list = g_list_remove (workspace->mru_list, window); meta_window_set_current_workspace_hint (window); @@ -239,7 +243,7 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace, else { meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n"); - meta_screen_focus_default_window (workspace->screen, NULL); + meta_workspace_focus_default_window (workspace, NULL); } } @@ -687,3 +691,91 @@ meta_workspace_get_name (MetaWorkspace *workspace) { return meta_prefs_get_workspace_name (meta_workspace_index (workspace)); } + +void +meta_workspace_focus_default_window (MetaWorkspace *workspace, + MetaWindow *not_this_one) +{ + if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK) + meta_workspace_focus_mru_window (workspace, not_this_one); + else + meta_screen_focus_mouse_window (workspace->screen, not_this_one); +} + +/* Focus MRU window (or top window if failed) on active workspace */ +void +meta_workspace_focus_mru_window (MetaWorkspace *workspace, + MetaWindow *not_this_one) +{ + MetaWindow *window = NULL; + GList *tmp; + + if (not_this_one) + meta_topic (META_DEBUG_FOCUS, + "Focusing MRU window excluding %s\n", not_this_one->desc); + + tmp = workspace->mru_list; + + while (tmp) + { + if (((MetaWindow*) tmp->data) != not_this_one) + { + window = tmp->data; + break; + } + + tmp = tmp->next; + } + + if (window) + { + meta_topic (META_DEBUG_FOCUS, + "Focusing workspace MRU window %s\n", window->desc); + + meta_window_focus (window, + meta_display_get_current_time (workspace->screen->display)); + + /* Also raise the window if in click-to-focus */ + if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK) + meta_window_raise (window); + } + else + { + meta_topic (META_DEBUG_FOCUS, "No MRU window to focus found\n"); + meta_workspace_focus_top_window (workspace, not_this_one); + } +} + +/* Focus top window on workspace */ +void +meta_workspace_focus_top_window (MetaWorkspace *workspace, + MetaWindow *not_this_one) +{ + MetaWindow *window; + + if (not_this_one) + meta_topic (META_DEBUG_FOCUS, + "Focusing top window excluding %s\n", not_this_one->desc); + + window = meta_stack_get_default_focus_window (workspace->screen->stack, + workspace, + not_this_one); + + /* FIXME I'm a loser on the CurrentTime front */ + if (window) + { + meta_topic (META_DEBUG_FOCUS, + "Focusing top window %s\n", window->desc); + + meta_window_focus (window, + meta_display_get_current_time (workspace->screen->display)); + + /* Also raise the window if in click-to-focus */ + if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK) + meta_window_raise (window); + } + else + { + meta_topic (META_DEBUG_FOCUS, "No top window to focus found\n"); + } +} diff --git a/src/workspace.h b/src/workspace.h index b89f5673d..5a45c60ce 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -40,6 +40,7 @@ struct _MetaWorkspace MetaScreen *screen; GList *windows; + GList *mru_list; MetaRectangle all_work_areas; MetaRectangle *work_areas; @@ -76,9 +77,12 @@ void meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace, void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace, MetaRectangle *area); - - - +void meta_workspace_focus_mru_window (MetaWorkspace *workspace, + MetaWindow *not_this_one); +void meta_workspace_focus_default_window (MetaWorkspace *workspace, + MetaWindow *not_this_one); +void meta_workspace_focus_top_window (MetaWorkspace *workspace, + MetaWindow *not_this_one); MetaWorkspace* meta_workspace_get_neighbor (MetaWorkspace *workspace, MetaMotionDirection direction);