From 32788a93f23eaa683f7a88694c778cd084607754 Mon Sep 17 00:00:00 2001 From: mwenzkowski <29407878+mwenzkowski@users.noreply.github.com> Date: Wed, 28 Oct 2020 00:02:08 +0100 Subject: [PATCH 1/3] output: evacuate sticky containers only if new output has a workspace Sticky floating containers on an otherwise empty workspace can only be evacuated if the new output has an active workspace. The noop output may not have one and in that case we have to move the whole workspace to the new output. --- include/sway/tree/workspace.h | 2 ++ sway/tree/output.c | 49 +++++++++++++++++++---------------- sway/tree/workspace.c | 13 ++++++++++ 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 1adbe68a2..fe200ec00 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -132,4 +132,6 @@ void workspace_get_box(struct sway_workspace *workspace, struct wlr_box *box); size_t workspace_num_tiling_views(struct sway_workspace *ws); +size_t workspace_num_sticky_containers(struct sway_workspace *ws); + #endif diff --git a/sway/tree/output.c b/sway/tree/output.c index d600c5c31..4dc22755a 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -152,21 +152,18 @@ void output_enable(struct sway_output *output) { arrange_root(); } -static void evacuate_sticky(struct sway_workspace *old_ws, - struct sway_output *new_output) { - struct sway_workspace *new_ws = output_get_active_workspace(new_output); - if (!sway_assert(new_ws, "New output does not have a workspace")) { - return; +static void evacuate_sticky(struct sway_container *con, void *data) { + if (container_is_floating(con) && con->is_sticky) { + struct sway_workspace *new_ws = data; + if (!sway_assert(new_ws, "Expected workspace to not be null")) { + return; + } + container_detach(con); + workspace_add_floating(new_ws, con); + container_handle_fullscreen_reparent(con); + container_floating_move_to_center(con); + ipc_event_window(con, "move"); } - while (old_ws->floating->length) { - struct sway_container *sticky = old_ws->floating->items[0]; - container_detach(sticky); - workspace_add_floating(new_ws, sticky); - container_handle_fullscreen_reparent(sticky); - container_floating_move_to_center(sticky); - ipc_event_window(sticky, "move"); - } - workspace_detect_urgent(new_ws); } static void output_evacuate(struct sway_output *output) { @@ -195,18 +192,24 @@ static void output_evacuate(struct sway_output *output) { new_output = root->noop_output; } - if (workspace_is_empty(workspace)) { - // If floating is not empty, there are sticky containers to move - if (workspace->floating->length) { - evacuate_sticky(workspace, new_output); - } - workspace_begin_destroy(workspace); - continue; - } - struct sway_workspace *new_output_ws = output_get_active_workspace(new_output); + if (workspace_is_empty(workspace)) { + // If the new output has an active workspace (the noop output may + // not have one), move all sticky containers to it + if (new_output_ws) { + workspace_for_each_container(workspace, evacuate_sticky, + new_output_ws); + workspace_detect_urgent(new_output_ws); + } + + if (workspace_num_sticky_containers(workspace) == 0) { + workspace_begin_destroy(workspace); + continue; + } + } + workspace_output_add_priority(workspace, new_output); output_add_workspace(new_output, workspace); output_sort_workspaces(new_output); diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 3bcba8e54..476c25681 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -817,3 +817,16 @@ size_t workspace_num_tiling_views(struct sway_workspace *ws) { workspace_for_each_container(ws, count_tiling_views, &count); return count; } + +static void count_sticky_containers(struct sway_container *con, void *data) { + if (container_is_floating(con) && con->is_sticky) { + size_t *count = data; + *count += 1; + } +} + +size_t workspace_num_sticky_containers(struct sway_workspace *ws) { + size_t count = 0; + workspace_for_each_container(ws, count_sticky_containers, &count); + return count; +} From 39328ca4e4b97bd76153869f6a0a20fef3c17112 Mon Sep 17 00:00:00 2001 From: Dimitris Triantafyllidis Date: Tue, 27 Oct 2020 21:24:30 +0200 Subject: [PATCH 2/3] In container_split, set a floating container's view to tiled Currently, when a floating container with a view is split and children are added to it, the new views are rendered as tiled, while the first view stays in floating style. Here this is addressed by setting the view to tiled as soon as the container is split, by duplicating the "view part" of the logic in container_set_floating(..., false). Since the new container of the view is no longer considered floating, it makes sense to set the view to tiling at this point. The view would have to be set back to floating if it was possible to "unsplit" the container. --- sway/tree/container.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sway/tree/container.c b/sway/tree/container.c index 3e2341864..8557210f5 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -1413,6 +1413,13 @@ struct sway_container *container_split(struct sway_container *child, struct sway_seat *seat = input_manager_get_default_seat(); bool set_focus = (seat_get_focus(seat) == &child->node); + if (container_is_floating(child) && child->view) { + view_set_tiled(child->view, true); + if (child->view->using_csd) { + child->border = child->saved_border; + } + } + struct sway_container *cont = container_create(NULL); cont->width = child->width; cont->height = child->height; From 4799cb09606ba8b3cc3969c24637b3c6c9eac485 Mon Sep 17 00:00:00 2001 From: mwenzkowski <29407878+mwenzkowski@users.noreply.github.com> Date: Wed, 28 Oct 2020 13:50:24 +0100 Subject: [PATCH 3/3] output: Revert implementation of evacuate_sticky() The function evacuate_sticky() was changed in commit 32788a93 to be used by workspace_for_each_container() to make the code more readable. But I overlooked that it is not safe to use workspace_for_each_container() to remove container from a workspace. This commit restores the previous implementation for evacuate_sticky(). --- sway/tree/output.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/sway/tree/output.c b/sway/tree/output.c index 4dc22755a..f15a84b34 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -152,18 +152,21 @@ void output_enable(struct sway_output *output) { arrange_root(); } -static void evacuate_sticky(struct sway_container *con, void *data) { - if (container_is_floating(con) && con->is_sticky) { - struct sway_workspace *new_ws = data; - if (!sway_assert(new_ws, "Expected workspace to not be null")) { - return; - } - container_detach(con); - workspace_add_floating(new_ws, con); - container_handle_fullscreen_reparent(con); - container_floating_move_to_center(con); - ipc_event_window(con, "move"); +static void evacuate_sticky(struct sway_workspace *old_ws, + struct sway_output *new_output) { + struct sway_workspace *new_ws = output_get_active_workspace(new_output); + if (!sway_assert(new_ws, "New output does not have a workspace")) { + return; } + while(old_ws->floating->length) { + struct sway_container *sticky = old_ws->floating->items[0]; + container_detach(sticky); + workspace_add_floating(new_ws, sticky); + container_handle_fullscreen_reparent(sticky); + container_floating_move_to_center(sticky); + ipc_event_window(sticky, "move"); + } + workspace_detect_urgent(new_ws); } static void output_evacuate(struct sway_output *output) { @@ -198,10 +201,9 @@ static void output_evacuate(struct sway_output *output) { if (workspace_is_empty(workspace)) { // If the new output has an active workspace (the noop output may // not have one), move all sticky containers to it - if (new_output_ws) { - workspace_for_each_container(workspace, evacuate_sticky, - new_output_ws); - workspace_detect_urgent(new_output_ws); + if (new_output_ws && + workspace_num_sticky_containers(workspace) > 0) { + evacuate_sticky(workspace, new_output); } if (workspace_num_sticky_containers(workspace) == 0) {