From 79d9cfcda6fbe8177dbe8b0ed810a347b2cb26e8 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Fri, 2 Sep 2022 16:41:27 -0400 Subject: [PATCH] desktop: Cycle first to topmost view if not already focused The topmost view may not always be the focused view; for example, when Audacious's main window is focused but the floating Search Tool window remains on top of it. In that case the floating window (not the main window) should be the first view selected in the window switcher. --- src/desktop.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/desktop.c b/src/desktop.c index 224cdf49..e6d09080 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -188,11 +188,38 @@ struct view * desktop_cycle_view(struct server *server, struct view *start_view, enum lab_cycle_dir dir) { - struct view *view = start_view ? start_view : first_view(server); - if (!view) { - return NULL; + /* + * Views are listed in stacking order, topmost first. Usually + * the topmost view is already focused, so we pre-select the + * view second from the top: + * + * View #1 (on top, currently focused) + * View #2 (pre-selected) + * View #3 + * ... + * + * This assumption doesn't always hold with XWayland views, + * where a main application window may be focused but an + * focusable sub-view (e.g. an about dialog) may still be on + * top of it. In that case, we pre-select the sub-view: + * + * Sub-view of #1 (on top, pre-selected) + * Main view #1 (currently focused) + * Main view #2 + * ... + * + * The general rule is: + * + * - Pre-select the top view if NOT already focused + * - Otherwise select the view second from the top + */ + if (!start_view) { + start_view = first_view(server); + if (!start_view || start_view != desktop_focused_view(server)) { + return start_view; /* may be NULL */ + } } - start_view = view; + struct view *view = start_view; struct wlr_scene_node *node = &view->scene_tree->node; assert(node->parent);