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; +}