From 296e58079fce649abcd5b5211d6b1e4bf6fa57e1 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Tue, 26 Apr 2022 22:06:22 +0200 Subject: [PATCH 1/4] Prepare OSD for reimplementation of the preview feature --- include/labwc.h | 6 +++++- src/action.c | 8 ++++---- src/keyboard.c | 18 +++++++++--------- src/osd.c | 4 +++- src/view.c | 13 +++++++------ 5 files changed, 28 insertions(+), 21 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index 794b2671..5b9c25bb 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -231,7 +231,11 @@ struct server { struct wl_listener new_constraint; /* Set when in cycle (alt-tab) mode */ - struct view *cycle_view; + struct osd_state { + struct view *cycle_view; + struct wlr_scene_node *preview_node; + struct wlr_scene_node *preview_anchor; + } osd_state; struct theme *theme; diff --git a/src/action.c b/src/action.c index 3b6dd4d4..9604c306 100644 --- a/src/action.c +++ b/src/action.c @@ -235,13 +235,13 @@ actions_run(struct view *activator, struct server *server, } break; case ACTION_TYPE_NEXT_WINDOW: - server->cycle_view = desktop_cycle_view(server, - server->cycle_view, LAB_CYCLE_DIR_FORWARD); + server->osd_state.cycle_view = desktop_cycle_view(server, + server->osd_state.cycle_view, LAB_CYCLE_DIR_FORWARD); osd_update(server); break; case ACTION_TYPE_PREVIOUS_WINDOW: - server->cycle_view = desktop_cycle_view(server, - server->cycle_view, LAB_CYCLE_DIR_BACKWARD); + server->osd_state.cycle_view = desktop_cycle_view(server, + server->osd_state.cycle_view, LAB_CYCLE_DIR_BACKWARD); osd_update(server); break; case ACTION_TYPE_RECONFIGURE: diff --git a/src/keyboard.c b/src/keyboard.c index 93d91071..2cad76fc 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -39,18 +39,18 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data) struct seat *seat = wl_container_of(listener, seat, keyboard_modifiers); struct server *server = seat->server; - if (server->cycle_view || seat->workspace_osd_shown_by_modifier) { + if (server->osd_state.cycle_view || seat->workspace_osd_shown_by_modifier) { struct wlr_keyboard_key_event *event = data; struct wlr_keyboard *keyboard = &seat->keyboard_group->keyboard; if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED && !keyboard_any_modifiers_pressed(keyboard)) { - if (server->cycle_view) { + if (server->osd_state.cycle_view) { /* end cycle */ desktop_focus_and_activate_view(&server->seat, - server->cycle_view); - desktop_move_to_front(server->cycle_view); - server->cycle_view = NULL; + server->osd_state.cycle_view); + desktop_move_to_front(server->osd_state.cycle_view); + /* osd_finish() additionally resets cycle_view to NULL */ osd_finish(server); } if (seat->workspace_osd_shown_by_modifier) { @@ -145,12 +145,12 @@ handle_compositor_keybindings(struct wl_listener *listener, } } - if (server->cycle_view) { + if (server->osd_state.cycle_view) { if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { for (int i = 0; i < nsyms; i++) { if (syms[i] == XKB_KEY_Escape) { /* cancel */ - server->cycle_view = NULL; + /* osd_finish() additionally resets cycle_view to NULL */ osd_finish(server); return true; } @@ -168,8 +168,8 @@ handle_compositor_keybindings(struct wl_listener *listener, enum lab_cycle_dir dir = backwards ? LAB_CYCLE_DIR_BACKWARD : LAB_CYCLE_DIR_FORWARD; - server->cycle_view = desktop_cycle_view(server, - server->cycle_view, dir); + server->osd_state.cycle_view = desktop_cycle_view(server, + server->osd_state.cycle_view, dir); osd_update(server); } } diff --git a/src/osd.c b/src/osd.c index 529818a5..9cfc9ccb 100644 --- a/src/osd.c +++ b/src/osd.c @@ -109,6 +109,8 @@ osd_update_preview_outlines(struct view *view) void osd_finish(struct server *server) { + server->osd_state.cycle_view = NULL; + struct output *output; wl_list_for_each(output, &server->outputs, link) { destroy_osd_nodes(output); @@ -185,7 +187,7 @@ osd_update(struct server *server) if (!isfocusable(view)) { continue; } - if (view == server->cycle_view) { + if (view == server->osd_state.cycle_view) { set_cairo_color(cairo, theme->osd_label_text_color); cairo_rectangle(cairo, OSD_BORDER_WIDTH, y, OSD_ITEM_WIDTH, OSD_ITEM_HEIGHT); diff --git a/src/view.c b/src/view.c index 843c5c98..e8c55648 100644 --- a/src/view.c +++ b/src/view.c @@ -808,25 +808,26 @@ view_destroy(struct view *view) server->focused_view = NULL; } - if (server->cycle_view == view) { + struct osd_state *osd_state = &view->server->osd_state; + if (osd_state->cycle_view == view) { /* * If we are the current OSD selected view, cycle * to the next because we are dying. */ - server->cycle_view = desktop_cycle_view(server, - server->cycle_view, LAB_CYCLE_DIR_BACKWARD); + osd_state->cycle_view = desktop_cycle_view(server, + osd_state->cycle_view, LAB_CYCLE_DIR_BACKWARD); /* * If we cycled back to ourselves, then we have no windows. * just remove it and close the OSD for good. */ - if (server->cycle_view == view || !server->cycle_view) { - server->cycle_view = NULL; + if (osd_state->cycle_view == view || !osd_state->cycle_view) { + /* osd_finish() additionally resets cycle_view to NULL */ osd_finish(server); } } - if (server->cycle_view) { + if (osd_state->cycle_view) { /* Update the OSD to reflect the view has now gone. */ osd_update(server); } 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 2/4] 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; } From ca3c83aafce6cede062484f042b32eb955108c26 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Mon, 22 Aug 2022 00:42:01 +0200 Subject: [PATCH 3/4] src/osd.c: Integrate preview outline into OSD state --- include/labwc.h | 3 +-- src/osd.c | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index df328f41..ead72349 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -202,8 +202,6 @@ struct server { /* Tree for built in menu */ struct wlr_scene_tree *menu_tree; - struct multi_rect *osd_preview_outline; - /* Workspaces */ struct wl_list workspaces; /* struct workspace.link */ struct workspace *workspace_current; @@ -236,6 +234,7 @@ struct server { bool preview_was_enabled; struct wlr_scene_node *preview_node; struct wlr_scene_node *preview_anchor; + struct multi_rect *preview_outline; } osd_state; struct theme *theme; diff --git a/src/osd.c b/src/osd.c index e2b98d0f..acfdade1 100644 --- a/src/osd.c +++ b/src/osd.c @@ -90,7 +90,7 @@ osd_update_preview_outlines(struct view *view) { /* Create / Update preview outline tree */ struct server *server = view->server; - struct multi_rect *rect = view->server->osd_preview_outline; + struct multi_rect *rect = view->server->osd_state.preview_outline; if (!rect) { int line_width = server->theme->osd_border_width; float *colors[] = { @@ -100,7 +100,7 @@ osd_update_preview_outlines(struct view *view) }; rect = multi_rect_create(&server->scene->tree, colors, line_width); wlr_scene_node_place_above(&rect->tree->node, &server->menu_tree->node); - server->osd_preview_outline = rect; + server->osd_state.preview_outline = rect; } struct wlr_box geo = ssd_max_extents(view); @@ -120,10 +120,10 @@ osd_finish(struct server *server) destroy_osd_nodes(output); wlr_scene_node_set_enabled(&output->osd_tree->node, false); } - if (server->osd_preview_outline) { + if (server->osd_state.preview_outline) { /* Destroy the whole multi_rect so we can easily react to new themes */ - wlr_scene_node_destroy(&server->osd_preview_outline->tree->node); - server->osd_preview_outline = NULL; + wlr_scene_node_destroy(&server->osd_state.preview_outline->tree->node); + server->osd_state.preview_outline = NULL; } } From 2550c984f8dbe0d9783caab427ef4d707e6705c3 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Mon, 22 Aug 2022 02:54:40 +0200 Subject: [PATCH 4/4] Move OSD handler for view destruction to osd.c --- include/labwc.h | 2 ++ src/osd.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/view.c | 34 ++-------------------------------- 3 files changed, 50 insertions(+), 32 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index ead72349..c5d78aad 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -583,6 +583,8 @@ void osd_update(struct server *server); void osd_finish(struct server *server); /* Moves preview views back into their original stacking order and state */ void osd_preview_restore(struct server *server); +/* Notify OSD about a destroying view */ +void osd_on_view_destroy(struct view *view); /* * wlroots "input inhibitor" extension (required for swaylock) blocks diff --git a/src/osd.c b/src/osd.c index acfdade1..da6f5028 100644 --- a/src/osd.c +++ b/src/osd.c @@ -108,6 +108,52 @@ osd_update_preview_outlines(struct view *view) wlr_scene_node_set_position(&rect->tree->node, geo.x, geo.y); } +void +osd_on_view_destroy(struct view *view) +{ + assert(view); + struct osd_state *osd_state = &view->server->osd_state; + + if (!osd_state->cycle_view) { + /* OSD not active, no need for clean up */ + return; + } + + if (osd_state->cycle_view == view) { + /* + * If we are the current OSD selected view, cycle + * to the next because we are dying. + */ + osd_state->cycle_view = desktop_cycle_view(view->server, + osd_state->cycle_view, LAB_CYCLE_DIR_BACKWARD); + + /* + * If we cycled back to ourselves, then we have no more windows. + * Just close the OSD for good. + */ + if (osd_state->cycle_view == view || !osd_state->cycle_view) { + /* osd_finish() additionally resets cycle_view to NULL */ + osd_finish(view->server); + } + } + + 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); + } + } + + if (osd_state->cycle_view) { + /* Update the OSD to reflect the view has now gone. */ + osd_update(view->server); + } +} + void osd_finish(struct server *server) { diff --git a/src/view.c b/src/view.c index fa3a51ca..68ccd17b 100644 --- a/src/view.c +++ b/src/view.c @@ -809,41 +809,11 @@ view_destroy(struct view *view) server->focused_view = NULL; } - struct osd_state *osd_state = &view->server->osd_state; - if (osd_state->cycle_view == view) { - /* - * If we are the current OSD selected view, cycle - * to the next because we are dying. - */ - osd_state->cycle_view = desktop_cycle_view(server, - osd_state->cycle_view, LAB_CYCLE_DIR_BACKWARD); - - /* - * If we cycled back to ourselves, then we have no windows. - * just remove it and close the OSD for good. - */ - if (osd_state->cycle_view == view || !osd_state->cycle_view) { - /* osd_finish() additionally resets cycle_view to NULL */ - osd_finish(server); - } - } - - if (osd_state->cycle_view) { - /* Update the OSD to reflect the view has now gone. */ - osd_update(server); - } + osd_on_view_destroy(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(node); + wlr_scene_node_destroy(&view->scene_tree->node); view->scene_tree = NULL; }