diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index 0e47d8bb..0e346a31 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -80,6 +80,13 @@ Actions are used in menus and keyboard/mouse bindings. ** Toggle always-on-top of focused window. +** + Toggle bewteen layers 'always-on-bottom' and 'normal'. When a window is + in the 'always-on-bottom' layer, it is rendered below all other + top-level windows. It is anticipated that this action will be useful + when defining window-rules for desktop-management tools that do not + support the wlr-layer-shell protocol. + ** Stop handling keybinds other than ToggleKeybinds itself. This can be used to allow A-Tab and similar keybinds to be delivered diff --git a/include/labwc.h b/include/labwc.h index cbd61424..d2d16aeb 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -263,6 +263,7 @@ struct server { /* Tree for all non-layer xdg/xwayland-shell surfaces with always-on-top/below */ struct wlr_scene_tree *view_tree_always_on_top; + struct wlr_scene_tree *view_tree_always_on_bottom; #if HAVE_XWAYLAND /* Tree for unmanaged xsurfaces without initialized view (usually popups) */ struct wlr_scene_tree *unmanaged_tree; diff --git a/include/view.h b/include/view.h index 08e3f273..53f8de73 100644 --- a/include/view.h +++ b/include/view.h @@ -171,8 +171,11 @@ void view_maximize(struct view *view, bool maximize, void view_set_fullscreen(struct view *view, bool fullscreen); void view_toggle_maximize(struct view *view); void view_toggle_decorations(struct view *view); -void view_toggle_always_on_top(struct view *view); + bool view_is_always_on_top(struct view *view); +void view_toggle_always_on_top(struct view *view); +void view_toggle_always_on_bottom(struct view *view); + bool view_is_tiled(struct view *view); bool view_is_floating(struct view *view); void view_move_to_workspace(struct view *view, struct workspace *workspace); diff --git a/src/action.c b/src/action.c index 0134270a..3699a39f 100644 --- a/src/action.c +++ b/src/action.c @@ -61,6 +61,7 @@ enum action_type { ACTION_TYPE_TOGGLE_FULLSCREEN, ACTION_TYPE_TOGGLE_DECORATIONS, ACTION_TYPE_TOGGLE_ALWAYS_ON_TOP, + ACTION_TYPE_TOGGLE_ALWAYS_ON_BOTTOM, ACTION_TYPE_FOCUS, ACTION_TYPE_ICONIFY, ACTION_TYPE_MOVE, @@ -93,6 +94,7 @@ const char *action_names[] = { "ToggleFullscreen", "ToggleDecorations", "ToggleAlwaysOnTop", + "ToggleAlwaysOnBottom", "Focus", "Iconify", "Move", @@ -519,6 +521,11 @@ actions_run(struct view *activator, struct server *server, view_toggle_always_on_top(view); } break; + case ACTION_TYPE_TOGGLE_ALWAYS_ON_BOTTOM: + if (view) { + view_toggle_always_on_bottom(view); + } + break; case ACTION_TYPE_FOCUS: if (view) { desktop_focus_and_activate_view(&server->seat, view); diff --git a/src/server.c b/src/server.c index 9e9ad428..4e3c3d69 100644 --- a/src/server.c +++ b/src/server.c @@ -307,6 +307,7 @@ server_init(struct server *server) * | layer-shell | background-layer | Yes | swaybg */ + server->view_tree_always_on_bottom = wlr_scene_tree_create(&server->scene->tree); server->view_tree = wlr_scene_tree_create(&server->scene->tree); server->view_tree_always_on_top = wlr_scene_tree_create(&server->scene->tree); server->xdg_popup_tree = wlr_scene_tree_create(&server->scene->tree); diff --git a/src/view-impl-common.c b/src/view-impl-common.c index dacfc9b0..ce227537 100644 --- a/src/view-impl-common.c +++ b/src/view-impl-common.c @@ -27,13 +27,13 @@ view_impl_move_to_back(struct view *view) void view_impl_map(struct view *view) { - if (!view->been_mapped) { - window_rules_apply(view, LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP); - } desktop_focus_and_activate_view(&view->server->seat, view); view_move_to_front(view); view_update_title(view); view_update_app_id(view); + if (!view->been_mapped) { + window_rules_apply(view, LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP); + } } static bool diff --git a/src/view.c b/src/view.c index ea7ce086..6f287b3a 100644 --- a/src/view.c +++ b/src/view.c @@ -627,6 +627,28 @@ view_toggle_always_on_top(struct view *view) } } +static bool +view_is_always_on_bottom(struct view *view) +{ + assert(view); + return view->scene_tree->node.parent == + view->server->view_tree_always_on_bottom; +} + +void +view_toggle_always_on_bottom(struct view *view) +{ + assert(view); + if (view_is_always_on_bottom(view)) { + view->workspace = view->server->workspace_current; + wlr_scene_node_reparent(&view->scene_tree->node, + view->workspace->tree); + } else { + wlr_scene_node_reparent(&view->scene_tree->node, + view->server->view_tree_always_on_bottom); + } +} + void view_move_to_workspace(struct view *view, struct workspace *workspace) {