diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index a47f93e7..ef65a524 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -61,6 +61,9 @@ Actions are used in keyboard bindings. ** Toggle maximize state of focused window. +** + Toggle always-on-top of focused window. + # SEE ALSO labwc(1), labwc-config(5), labwc-theme(5) diff --git a/docs/menu.xml b/docs/menu.xml index 45c4ba98..485077d0 100644 --- a/docs/menu.xml +++ b/docs/menu.xml @@ -14,6 +14,9 @@ + + + diff --git a/include/labwc.h b/include/labwc.h index 2670a8ce..ac8732ee 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -175,6 +175,8 @@ struct server { /* Tree for all non-layer xdg/xwayland-shell surfaces */ struct wlr_scene_tree *view_tree; + /* Tree for all non-layer xdg/xwayland-shell surfaces with always-on-top */ + struct wlr_scene_tree *view_tree_always_on_top; #if HAVE_XWAYLAND /* Tree for unmanaged xsurfaces without initialized view (usually popups) */ struct wlr_scene_tree *unmanaged_tree; @@ -399,6 +401,7 @@ void view_set_fullscreen(struct view *view, bool fullscreen, struct wlr_output *wlr_output); void view_toggle_maximize(struct view *view); void view_toggle_decorations(struct view *view); +void view_toggle_always_on_top(struct view *view); void view_set_decorations(struct view *view, bool decorations); void view_toggle_fullscreen(struct view *view); void view_adjust_for_layout_change(struct view *view); diff --git a/src/action.c b/src/action.c index 314c0fe6..646ca4d8 100644 --- a/src/action.c +++ b/src/action.c @@ -24,6 +24,7 @@ enum action_type { ACTION_TYPE_TOGGLE_MAXIMIZE, ACTION_TYPE_TOGGLE_FULLSCREEN, ACTION_TYPE_TOGGLE_DECORATIONS, + ACTION_TYPE_TOGGLE_ALWAYS_ON_TOP, ACTION_TYPE_FOCUS, ACTION_TYPE_ICONIFY, ACTION_TYPE_MOVE, @@ -46,6 +47,7 @@ const char *action_names[] = { "ToggleMaximize", "ToggleFullscreen", "ToggleDecorations", + "ToggleAlwaysOnTop", "Focus", "Iconify", "Move", @@ -209,6 +211,11 @@ actions_run(struct view *activator, struct server *server, view_toggle_decorations(view); } break; + case ACTION_TYPE_TOGGLE_ALWAYS_ON_TOP: + if (view) { + view_toggle_always_on_top(view); + } + break; case ACTION_TYPE_FOCUS: view = desktop_view_at_cursor(server); if (view) { diff --git a/src/debug.c b/src/debug.c index 68dcbc2a..697aacdf 100644 --- a/src/debug.c +++ b/src/debug.c @@ -111,7 +111,12 @@ get_special(struct server *server, struct wlr_scene_node *node, if (node == &server->view_tree->node) { return "server->view_tree"; } - if (node->parent == &server->view_tree->node) { + if (node == &server->view_tree_always_on_top->node) { + return "server->view_tree_always_on_top"; + } + if (node->parent == &server->view_tree->node || + node->parent == &server->view_tree_always_on_top->node) { + *last_view = node_view_from_node(node); *last_view = node_view_from_node(node); } const char *view_part = get_view_part(*last_view, node); diff --git a/src/menu/menu.c b/src/menu/menu.c index 67bdeb44..c74b8daa 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -452,6 +452,8 @@ menu_init_windowmenu(struct server *server) fill_item("name.action", "ToggleFullscreen"); current_item = item_create(menu, "Decorations"); fill_item("name.action", "ToggleDecorations"); + current_item = item_create(menu, "AlwaysOnTop"); + fill_item("name.action", "ToggleAlwaysOnTop"); current_item = item_create(menu, "Close"); fill_item("name.action", "Close"); } diff --git a/src/server.c b/src/server.c index 4865c417..adeb4fb7 100644 --- a/src/server.c +++ b/src/server.c @@ -235,6 +235,7 @@ server_init(struct server *server) exit(EXIT_FAILURE); } server->view_tree = wlr_scene_tree_create(&server->scene->node); + server->view_tree_always_on_top = wlr_scene_tree_create(&server->scene->node); #if HAVE_XWAYLAND server->unmanaged_tree = wlr_scene_tree_create(&server->scene->node); #endif diff --git a/src/view.c b/src/view.c index c14731e6..2ce0084d 100644 --- a/src/view.c +++ b/src/view.c @@ -281,6 +281,25 @@ view_toggle_decorations(struct view *view) } } +static bool +is_always_on_top(struct view *view) +{ + return view->scene_tree->node.parent == + &view->server->view_tree_always_on_top->node; +} + +void +view_toggle_always_on_top(struct view *view) +{ + if (is_always_on_top(view)) { + wlr_scene_node_reparent(&view->scene_tree->node, + &view->server->view_tree->node); + } else { + wlr_scene_node_reparent(&view->scene_tree->node, + &view->server->view_tree_always_on_top->node); + } +} + void view_set_decorations(struct view *view, bool decorations) {