From 15a5b710dbfca0dfdbc1235c256ad80ddd884411 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Tue, 26 Apr 2022 23:56:27 +0200 Subject: [PATCH] alt-tab preview: restore functionality after move to scene-graph --- include/common/scene-helpers.h | 12 +++++++- include/labwc.h | 8 +++-- src/common/scene-helpers.c | 12 ++++++++ src/desktop.c | 3 ++ src/keyboard.c | 1 + src/osd.c | 55 ++++++++++++++++++++++++++++++++++ src/view.c | 11 ++++++- 7 files changed, 98 insertions(+), 4 deletions(-) diff --git a/include/common/scene-helpers.h b/include/common/scene-helpers.h index a124d0a3..921ff56a 100644 --- a/include/common/scene-helpers.h +++ b/include/common/scene-helpers.h @@ -1,7 +1,17 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -#include +struct wlr_scene_node; +struct wlr_scene_rect; +struct wlr_scene_tree; +struct wlr_surface; struct wlr_scene_rect *lab_wlr_scene_get_rect(struct wlr_scene_node *node); struct wlr_scene_tree *lab_scene_tree_from_node(struct wlr_scene_node *node); struct wlr_surface *lab_wlr_surface_from_node(struct wlr_scene_node *node); + +/** + * lab_get_prev_node - return previous (sibling) node + * @node: node to find the previous node from + * Return NULL if previous link is list-head which means node is bottom-most + */ +struct wlr_scene_node *lab_wlr_scene_get_prev_node(struct wlr_scene_node *node); diff --git a/include/labwc.h b/include/labwc.h index 5b9c25bb..df328f41 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -233,6 +233,7 @@ struct server { /* Set when in cycle (alt-tab) mode */ struct osd_state { struct view *cycle_view; + bool preview_was_enabled; struct wlr_scene_node *preview_node; struct wlr_scene_node *preview_anchor; } osd_state; @@ -577,9 +578,12 @@ void server_init(struct server *server); void server_start(struct server *server); void server_finish(struct server *server); -/* update onscreen display 'alt-tab' buffer */ -void osd_finish(struct server *server); +/* Updates onscreen display 'alt-tab' buffer */ void osd_update(struct server *server); +/* Closes the OSD */ +void osd_finish(struct server *server); +/* Moves preview views back into their original stacking order and state */ +void osd_preview_restore(struct server *server); /* * wlroots "input inhibitor" extension (required for swaylock) blocks diff --git a/src/common/scene-helpers.c b/src/common/scene-helpers.c index ae1220bf..6bda9bd7 100644 --- a/src/common/scene-helpers.c +++ b/src/common/scene-helpers.c @@ -32,3 +32,15 @@ lab_wlr_surface_from_node(struct wlr_scene_node *node) } return NULL; } + +struct wlr_scene_node * +lab_wlr_scene_get_prev_node(struct wlr_scene_node *node) +{ + assert(node); + struct wlr_scene_node *prev; + prev = wl_container_of(node->link.prev, node, link); + if (&prev->link == &node->parent->children) { + return NULL; + } + return prev; +} diff --git a/src/desktop.c b/src/desktop.c index ab5e00ce..224cdf49 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -203,6 +203,9 @@ desktop_cycle_view(struct server *server, struct view *start_view, /* Scene nodes are ordered like last node == displayed topmost */ iter = dir == LAB_CYCLE_DIR_FORWARD ? get_prev_item : get_next_item; + /* Make sure to have all nodes in their actual ordering */ + osd_preview_restore(server); + do { list_item = iter(list_item); if (list_item == list_head) { diff --git a/src/keyboard.c b/src/keyboard.c index 2cad76fc..2d44a9db 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -150,6 +150,7 @@ handle_compositor_keybindings(struct wl_listener *listener, for (int i = 0; i < nsyms; i++) { if (syms[i] == XKB_KEY_Escape) { /* cancel */ + osd_preview_restore(server); /* osd_finish() additionally resets cycle_view to NULL */ osd_finish(server); return true; diff --git a/src/osd.c b/src/osd.c index 9cfc9ccb..e2b98d0f 100644 --- a/src/osd.c +++ b/src/osd.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only #include "config.h" +#include #include #include #include @@ -8,6 +9,7 @@ #include "common/buf.h" #include "common/font.h" #include "common/graphic-helpers.h" +#include "common/scene-helpers.h" #include "config/rcxml.h" #include "labwc.h" #include "theme.h" @@ -110,6 +112,8 @@ void osd_finish(struct server *server) { server->osd_state.cycle_view = NULL; + server->osd_state.preview_node = NULL; + server->osd_state.preview_anchor = NULL; struct output *output; wl_list_for_each(output, &server->outputs, link) { @@ -123,6 +127,53 @@ osd_finish(struct server *server) } } +void +osd_preview_restore(struct server *server) +{ + struct osd_state *osd_state = &server->osd_state; + if (osd_state->preview_node) { + if (osd_state->preview_anchor) { + wlr_scene_node_place_above(osd_state->preview_node, + osd_state->preview_anchor); + } else { + /* Selected view was the first node */ + wlr_scene_node_lower_to_bottom(osd_state->preview_node); + } + + /* Node was disabled / minimized before, disable again */ + if (!osd_state->preview_was_enabled) { + wlr_scene_node_set_enabled(osd_state->preview_node, false); + } + osd_state->preview_node = NULL; + osd_state->preview_anchor = NULL; + } +} + +static void +preview_cycled_view(struct view *view) +{ + assert(view); + assert(view->scene_tree); + struct osd_state *osd_state = &view->server->osd_state; + + /* Move previous selected node back to its original place */ + osd_preview_restore(view->server); + + /* Remember the sibling right before the selected node */ + osd_state->preview_node = &view->scene_tree->node; + osd_state->preview_anchor = lab_wlr_scene_get_prev_node( + osd_state->preview_node); + + /* Store node enabled / minimized state and force-enable if disabled */ + osd_state->preview_was_enabled = osd_state->preview_node->enabled; + if (!osd_state->preview_was_enabled) { + wlr_scene_node_set_enabled(osd_state->preview_node, true); + } + + /* Finally raise selected node to the top */ + wlr_scene_node_raise_to_top(osd_state->preview_node); +} + void osd_update(struct server *server) { @@ -294,4 +345,8 @@ osd_update(struct server *server) wlr_scene_node_set_enabled(&output->osd_tree->node, true); } free(buf.buf); + + if (rc.cycle_preview_contents) { + preview_cycled_view(server->osd_state.cycle_view); + } } diff --git a/src/view.c b/src/view.c index e8c55648..fa3a51ca 100644 --- a/src/view.c +++ b/src/view.c @@ -3,6 +3,7 @@ #include #include #include +#include "common/scene-helpers.h" #include "labwc.h" #include "ssd.h" #include "menu/menu.h" @@ -833,8 +834,16 @@ view_destroy(struct view *view) } if (view->scene_tree) { + struct wlr_scene_node *node = &view->scene_tree->node; + if (osd_state->preview_anchor == node) { + /* + * If we are the anchor for the current OSD selected view, + * replace the anchor with the node before us. + */ + osd_state->preview_anchor = lab_wlr_scene_get_prev_node(node); + } ssd_destroy(view); - wlr_scene_node_destroy(&view->scene_tree->node); + wlr_scene_node_destroy(node); view->scene_tree = NULL; }