mirror of
https://github.com/labwc/labwc.git
synced 2026-02-04 04:06:25 -05:00
view: decouple always-on-top windows from the omnipresent state
Before this commit, always-on-{top,bottom} windows were always visible
on all workspaces (omnipresent) because the they were not in
per-workspace trees like normal windows.
This commit fixes this by removing per-workspace trees and instead
showing/hiding views individually based on view->workspace.
This commit is contained in:
parent
55a256f2fa
commit
cf401a6394
8 changed files with 25 additions and 72 deletions
|
|
@ -62,10 +62,7 @@ enum lab_view_criteria {
|
|||
/* No filter -> all focusable views */
|
||||
LAB_VIEW_CRITERIA_NONE = 0,
|
||||
|
||||
/*
|
||||
* Includes always-on-top views, e.g.
|
||||
* what is visible on the current workspace
|
||||
*/
|
||||
/* Includes omnipresent (visible on all desktops) views */
|
||||
LAB_VIEW_CRITERIA_CURRENT_WORKSPACE = 1 << 0,
|
||||
|
||||
/* Positive criteria */
|
||||
|
|
|
|||
|
|
@ -8,14 +8,12 @@
|
|||
|
||||
struct seat;
|
||||
struct server;
|
||||
struct wlr_scene_tree;
|
||||
|
||||
struct workspace {
|
||||
struct wl_list link; /* struct server.workspaces */
|
||||
struct server *server;
|
||||
|
||||
char *name;
|
||||
struct wlr_scene_tree *tree;
|
||||
|
||||
struct lab_cosmic_workspace *cosmic_workspace;
|
||||
struct {
|
||||
|
|
|
|||
|
|
@ -106,15 +106,6 @@ get_special(struct server *server, struct wlr_scene_node *node)
|
|||
if (node == &server->view_tree_always_on_top->node) {
|
||||
return "server->always_on_top";
|
||||
}
|
||||
if (node->parent == server->view_tree) {
|
||||
struct workspace *workspace;
|
||||
wl_list_for_each(workspace, &server->workspaces.all, link) {
|
||||
if (&workspace->tree->node == node) {
|
||||
return workspace->name;
|
||||
}
|
||||
}
|
||||
return "unknown workspace";
|
||||
}
|
||||
if (node->parent == &server->scene->tree) {
|
||||
struct output *output;
|
||||
wl_list_for_each(output, &server->outputs, link) {
|
||||
|
|
|
|||
|
|
@ -96,9 +96,9 @@ desktop_focus_view(struct view *view, bool raise)
|
|||
|
||||
/*
|
||||
* Switch workspace if necessary to make the view visible
|
||||
* (unnecessary for "always on {top,bottom}" views).
|
||||
* (unnecessary for omnipresent views).
|
||||
*/
|
||||
if (!view_is_always_on_top(view) && !view_is_always_on_bottom(view)) {
|
||||
if (!view->visible_on_all_workspaces) {
|
||||
workspaces_switch_to(view->workspace, /*update_focus*/ false);
|
||||
}
|
||||
|
||||
|
|
|
|||
27
src/view.c
27
src/view.c
|
|
@ -267,13 +267,7 @@ matches_criteria(struct view *view, enum lab_view_criteria criteria)
|
|||
return false;
|
||||
}
|
||||
if (criteria & LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
|
||||
/*
|
||||
* Always-on-top views are always on the current desktop and are
|
||||
* special in that they live in a different tree.
|
||||
*/
|
||||
struct server *server = view->server;
|
||||
if (view->scene_tree->node.parent != server->workspaces.current->tree
|
||||
&& !view_is_always_on_top(view)) {
|
||||
if (view->workspace != view->server->workspaces.current) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -303,11 +297,7 @@ matches_criteria(struct view *view, enum lab_view_criteria criteria)
|
|||
}
|
||||
}
|
||||
if (criteria & LAB_VIEW_CRITERIA_NO_OMNIPRESENT) {
|
||||
/*
|
||||
* TODO: Once always-on-top views use a per-workspace
|
||||
* sub-tree we can remove the check from this condition.
|
||||
*/
|
||||
if (view->visible_on_all_workspaces || view_is_always_on_top(view)) {
|
||||
if (view->visible_on_all_workspaces) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1562,9 +1552,8 @@ view_toggle_always_on_top(struct view *view)
|
|||
{
|
||||
assert(view);
|
||||
if (view_is_always_on_top(view)) {
|
||||
view->workspace = view->server->workspaces.current;
|
||||
wlr_scene_node_reparent(&view->scene_tree->node,
|
||||
view->workspace->tree);
|
||||
view->server->view_tree);
|
||||
} else {
|
||||
wlr_scene_node_reparent(&view->scene_tree->node,
|
||||
view->server->view_tree_always_on_top);
|
||||
|
|
@ -1584,9 +1573,8 @@ view_toggle_always_on_bottom(struct view *view)
|
|||
{
|
||||
assert(view);
|
||||
if (view_is_always_on_bottom(view)) {
|
||||
view->workspace = view->server->workspaces.current;
|
||||
wlr_scene_node_reparent(&view->scene_tree->node,
|
||||
view->workspace->tree);
|
||||
view->server->view_tree);
|
||||
} else {
|
||||
wlr_scene_node_reparent(&view->scene_tree->node,
|
||||
view->server->view_tree_always_on_bottom);
|
||||
|
|
@ -1608,8 +1596,7 @@ view_move_to_workspace(struct view *view, struct workspace *workspace)
|
|||
assert(workspace);
|
||||
if (view->workspace != workspace) {
|
||||
view->workspace = workspace;
|
||||
wlr_scene_node_reparent(&view->scene_tree->node,
|
||||
workspace->tree);
|
||||
view_update_visibility(view);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2411,7 +2398,9 @@ mappable_disconnect(struct mappable *mappable)
|
|||
void
|
||||
view_update_visibility(struct view *view)
|
||||
{
|
||||
bool visible = view->mapped && !view->minimized;
|
||||
struct server *server = view->server;
|
||||
bool visible = view->mapped && !view->minimized
|
||||
&& view->workspace == server->workspaces.current;
|
||||
if (visible == view->scene_tree->node.enabled) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,9 +234,7 @@ add_workspace(struct server *server, const char *name)
|
|||
struct workspace *workspace = znew(*workspace);
|
||||
workspace->server = server;
|
||||
workspace->name = xstrdup(name);
|
||||
workspace->tree = wlr_scene_tree_create(server->view_tree);
|
||||
wl_list_append(&server->workspaces.all, &workspace->link);
|
||||
wlr_scene_node_set_enabled(&workspace->tree->node, false);
|
||||
|
||||
/* cosmic */
|
||||
workspace->cosmic_workspace = lab_cosmic_workspace_create(server->workspaces.cosmic_group);
|
||||
|
|
@ -435,7 +433,6 @@ workspaces_init(struct server *server)
|
|||
}
|
||||
|
||||
server->workspaces.current = initial;
|
||||
wlr_scene_node_set_enabled(&initial->tree->node, true);
|
||||
lab_cosmic_workspace_set_active(initial->cosmic_workspace, true);
|
||||
lab_ext_workspace_set_active(initial->ext_workspace, true);
|
||||
}
|
||||
|
|
@ -454,28 +451,11 @@ workspaces_switch_to(struct workspace *target, bool update_focus)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Disable the old workspace */
|
||||
wlr_scene_node_set_enabled(
|
||||
&server->workspaces.current->tree->node, false);
|
||||
|
||||
lab_cosmic_workspace_set_active(
|
||||
server->workspaces.current->cosmic_workspace, false);
|
||||
lab_ext_workspace_set_active(
|
||||
server->workspaces.current->ext_workspace, false);
|
||||
|
||||
/* Move Omnipresent views to new workspace */
|
||||
struct view *view;
|
||||
enum lab_view_criteria criteria =
|
||||
LAB_VIEW_CRITERIA_CURRENT_WORKSPACE;
|
||||
for_each_view_reverse(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);
|
||||
|
||||
/* Save the last visited workspace */
|
||||
server->workspaces.last = server->workspaces.current;
|
||||
|
||||
|
|
@ -483,24 +463,26 @@ workspaces_switch_to(struct workspace *target, bool update_focus)
|
|||
server->workspaces.current = target;
|
||||
|
||||
struct view *grabbed_view = server->grabbed_view;
|
||||
if (grabbed_view && !view_is_always_on_top(grabbed_view)) {
|
||||
if (grabbed_view) {
|
||||
view_move_to_workspace(grabbed_view, target);
|
||||
}
|
||||
|
||||
struct view *view;
|
||||
wl_list_for_each(view, &server->views, link) {
|
||||
/* Omnipresent views are always in the current workspace */
|
||||
if (view->visible_on_all_workspaces) {
|
||||
view->workspace = target;
|
||||
}
|
||||
view_update_visibility(view);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we are focusing what the user sees. Only refocus if
|
||||
* the focus is not already on an omnipresent or always-on-top view.
|
||||
*
|
||||
* TODO: Decouple always-on-top views from the omnipresent state.
|
||||
* One option for that would be to create a new scene tree
|
||||
* as child of every workspace tree and then reparent a-o-t
|
||||
* windows to that one. Combined with adjusting the condition
|
||||
* below that should take care of the issue.
|
||||
* the focus is not already on an omnipresent.
|
||||
*/
|
||||
if (update_focus) {
|
||||
struct view *active_view = server->active_view;
|
||||
if (!active_view || (!active_view->visible_on_all_workspaces
|
||||
&& !view_is_always_on_top(active_view))) {
|
||||
if (!active_view || !active_view->visible_on_all_workspaces) {
|
||||
desktop_focus_topmost_view(server);
|
||||
}
|
||||
}
|
||||
|
|
@ -514,9 +496,6 @@ workspaces_switch_to(struct workspace *target, bool update_focus)
|
|||
*/
|
||||
cursor_update_focus(server);
|
||||
|
||||
/* Ensure that only currently visible fullscreen windows hide the top layer */
|
||||
desktop_update_top_layer_visibility(server);
|
||||
|
||||
lab_cosmic_workspace_set_active(target->cosmic_workspace, true);
|
||||
lab_ext_workspace_set_active(target->ext_workspace, true);
|
||||
}
|
||||
|
|
@ -569,7 +548,6 @@ workspaces_find(struct workspace *anchor, const char *name, bool wrap)
|
|||
static void
|
||||
destroy_workspace(struct workspace *workspace)
|
||||
{
|
||||
wlr_scene_node_destroy(&workspace->tree->node);
|
||||
zfree(workspace->name);
|
||||
wl_list_remove(&workspace->link);
|
||||
wl_list_remove(&workspace->on_cosmic.activate.link);
|
||||
|
|
|
|||
|
|
@ -1019,7 +1019,7 @@ handle_new_xdg_toplevel(struct wl_listener *listener, void *data)
|
|||
}
|
||||
|
||||
view->workspace = server->workspaces.current;
|
||||
view->scene_tree = wlr_scene_tree_create(view->workspace->tree);
|
||||
view->scene_tree = wlr_scene_tree_create(server->view_tree);
|
||||
wlr_scene_node_set_enabled(&view->scene_tree->node, false);
|
||||
|
||||
struct wlr_scene_tree *tree = wlr_scene_xdg_surface_create(
|
||||
|
|
|
|||
|
|
@ -1010,7 +1010,7 @@ xwayland_view_create(struct server *server,
|
|||
xsurface->data = view;
|
||||
|
||||
view->workspace = server->workspaces.current;
|
||||
view->scene_tree = wlr_scene_tree_create(view->workspace->tree);
|
||||
view->scene_tree = wlr_scene_tree_create(server->view_tree);
|
||||
node_descriptor_create(&view->scene_tree->node,
|
||||
LAB_NODE_VIEW, view, /*data*/ NULL);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue