diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd
index 5b2463bb..2af1f0bc 100644
--- a/docs/labwc-actions.5.scd
+++ b/docs/labwc-actions.5.scd
@@ -133,6 +133,9 @@ Actions are used in menus and keyboard/mouse bindings.
when defining window-rules for desktop-management tools that do not
support the wlr-layer-shell protocol.
+**
+ Toggle omnipresent (visible on all workspaces / sticky) for the focused window.
+
**
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/view.h b/include/view.h
index f7329fdc..04460f3b 100644
--- a/include/view.h
+++ b/include/view.h
@@ -149,6 +149,7 @@ struct view {
bool minimized;
enum view_axis maximized;
bool fullscreen;
+ bool visible_on_all_workspaces;
enum view_edge tiled;
bool inhibits_keybinds;
xkb_layout_index_t keyboard_layout;
@@ -400,8 +401,10 @@ void view_toggle_decorations(struct view *view);
bool view_is_always_on_top(struct view *view);
bool view_is_always_on_bottom(struct view *view);
+bool view_is_omnipresent(struct view *view);
void view_toggle_always_on_top(struct view *view);
void view_toggle_always_on_bottom(struct view *view);
+void view_toggle_visible_on_all_workspaces(struct view *view);
bool view_is_tiled(struct view *view);
bool view_is_floating(struct view *view);
diff --git a/src/action.c b/src/action.c
index bd0b7051..07a52dd2 100644
--- a/src/action.c
+++ b/src/action.c
@@ -78,6 +78,7 @@ enum action_type {
ACTION_TYPE_TOGGLE_DECORATIONS,
ACTION_TYPE_TOGGLE_ALWAYS_ON_TOP,
ACTION_TYPE_TOGGLE_ALWAYS_ON_BOTTOM,
+ ACTION_TYPE_TOGGLE_OMNIPRESENT,
ACTION_TYPE_FOCUS,
ACTION_TYPE_UNFOCUS,
ACTION_TYPE_ICONIFY,
@@ -120,6 +121,7 @@ const char *action_names[] = {
"ToggleDecorations",
"ToggleAlwaysOnTop",
"ToggleAlwaysOnBottom",
+ "ToggleOmnipresent",
"Focus",
"Unfocus",
"Iconify",
@@ -744,6 +746,11 @@ actions_run(struct view *activator, struct server *server,
view_toggle_always_on_bottom(view);
}
break;
+ case ACTION_TYPE_TOGGLE_OMNIPRESENT:
+ if (view) {
+ view_toggle_visible_on_all_workspaces(view);
+ }
+ break;
case ACTION_TYPE_FOCUS:
if (view) {
desktop_focus_view(view, /*raise*/ false);
diff --git a/src/menu/menu.c b/src/menu/menu.c
index eca82925..3e36d3ad 100644
--- a/src/menu/menu.c
+++ b/src/menu/menu.c
@@ -723,6 +723,8 @@ init_windowmenu(struct server *server)
fill_item("name.action", "ToggleDecorations");
current_item = item_create(menu, _("AlwaysOnTop"), false);
fill_item("name.action", "ToggleAlwaysOnTop");
+ current_item = item_create(menu, _("ToggleOmnipresent"), false);
+ fill_item("name.action", "ToggleOmnipresent");
/* Workspace sub-menu */
struct menu *workspace_menu = menu_create(server, "workspaces", "");
diff --git a/src/view.c b/src/view.c
index 4a2008df..f26ca4ac 100644
--- a/src/view.c
+++ b/src/view.c
@@ -1045,6 +1045,13 @@ view_toggle_always_on_bottom(struct view *view)
}
}
+void
+view_toggle_visible_on_all_workspaces(struct view *view)
+{
+ assert(view);
+ view->visible_on_all_workspaces = !view->visible_on_all_workspaces;
+}
+
void
view_move_to_workspace(struct view *view, struct workspace *workspace)
{
diff --git a/src/workspaces.c b/src/workspaces.c
index c04bc34a..e7707c5f 100644
--- a/src/workspaces.c
+++ b/src/workspaces.c
@@ -276,6 +276,16 @@ workspaces_switch_to(struct workspace *target, bool update_focus)
wlr_scene_node_set_enabled(
&server->workspace_current->tree->node, false);
+ /* Move Omnipresent views to new workspace */
+ struct view *view;
+ enum lab_view_criteria criteria =
+ LAB_VIEW_CRITERIA_CURRENT_WORKSPACE;
+ for_each_view(view, &server->views, criteria) {
+ if (view->visible_on_all_workspaces) {
+ view_move_to_workspace(view, target);
+ }
+ }
+
/* Enable the new workspace */
wlr_scene_node_set_enabled(&target->tree->node, true);