diff --git a/sway/desktop/output.c b/sway/desktop/output.c index c0e368d0..fb80fd87 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -832,12 +832,13 @@ static void render_floating(struct sway_output *soutput, for (int j = 0; j < output->children->length; ++j) { struct sway_container *workspace = output->children->items[j]; struct sway_workspace *ws = workspace->sway_workspace; - bool ws_is_visible = workspace_is_visible(workspace); + if (!workspace_is_visible(workspace)) { + continue; + } for (int k = 0; k < ws->floating->children->length; ++k) { struct sway_container *floater = ws->floating->children->items[k]; - if ((ws_is_visible || floater->is_sticky) - && floater_intersects_output(floater, soutput->swayc)) { + if (floater_intersects_output(floater, soutput->swayc)) { render_floating_container(soutput, damage, floater); } } diff --git a/sway/tree/container.c b/sway/tree/container.c index fd7ee2c3..532722e8 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -64,16 +64,6 @@ void container_create_notify(struct sway_container *container) { } } -static void container_close_notify(struct sway_container *container) { - if (container == NULL) { - return; - } - // TODO send ipc event type based on the container type - if (container->type == C_VIEW || container->type == C_WORKSPACE) { - ipc_event_window(container, "close"); - } -} - static void container_update_textures_recursive(struct sway_container *con) { container_update_title_textures(con); @@ -143,7 +133,6 @@ static void _container_destroy(struct sway_container *cont) { } wl_signal_emit(&cont->events.destroy, cont); - container_close_notify(cont); struct sway_container *parent = cont->parent; if (cont->children != NULL && cont->children->length) { @@ -151,6 +140,7 @@ static void _container_destroy(struct sway_container *cont) { // container_remove_child, which removes child from this container while (cont->children != NULL && cont->children->length > 0) { struct sway_container *child = cont->children->items[0]; + ipc_event_window(child, "close"); container_remove_child(child); _container_destroy(child); } @@ -188,12 +178,11 @@ static struct sway_container *container_workspace_destroy( return NULL; } + wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); + ipc_event_window(workspace, "close"); + struct sway_container *parent = workspace->parent; - if (workspace_is_empty(workspace)) { - // destroy the WS if there are no children - wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); - ipc_event_workspace(workspace, NULL, "empty"); - } else if (output) { + if (!workspace_is_empty(workspace) && output) { // Move children to a different workspace on this output struct sway_container *new_workspace = NULL; for (int i = 0; i < output->children->length; i++) { @@ -357,10 +346,12 @@ struct sway_container *container_destroy(struct sway_container *con) { if (con->children->length) { for (int i = 0; i < con->children->length; ++i) { struct sway_container *child = con->children->items[0]; + ipc_event_window(child, "close"); container_remove_child(child); container_add_child(parent, child); } } + ipc_event_window(con, "close"); _container_destroy(con); break; case C_VIEW: @@ -635,20 +626,20 @@ struct sway_container *floating_container_at(double lx, double ly, for (int j = 0; j < output->children->length; ++j) { struct sway_container *workspace = output->children->items[j]; struct sway_workspace *ws = workspace->sway_workspace; - bool ws_is_visible = workspace_is_visible(workspace); + if (!workspace_is_visible(workspace)) { + continue; + } for (int k = 0; k < ws->floating->children->length; ++k) { struct sway_container *floater = ws->floating->children->items[k]; - if (ws_is_visible || floater->is_sticky) { - struct wlr_box box = { - .x = floater->x, - .y = floater->y, - .width = floater->width, - .height = floater->height, - }; - if (wlr_box_contains_point(&box, lx, ly)) { - return container_at(floater, lx, ly, surface, sx, sy); - } + struct wlr_box box = { + .x = floater->x, + .y = floater->y, + .width = floater->width, + .height = floater->height, + }; + if (wlr_box_contains_point(&box, lx, ly)) { + return container_at(floater, lx, ly, surface, sx, sy); } } } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 37d4a06a..f78ae9a5 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -387,7 +387,21 @@ bool workspace_switch(struct sway_container *workspace) { strcpy(prev_workspace_name, active_ws->name); } - // TODO: Deal with sticky containers + // Move sticky containers to new workspace + struct sway_container *next_output = workspace->parent; + struct sway_container *next_output_prev_ws = + seat_get_active_child(seat, next_output); + struct sway_container *floating = + next_output_prev_ws->sway_workspace->floating; + bool has_sticky = false; + for (int i = 0; i < floating->children->length; ++i) { + struct sway_container *floater = floating->children->items[i]; + if (floater->is_sticky) { + has_sticky = true; + container_remove_child(floater); + container_add_child(workspace->sway_workspace->floating, floater); + } + } wlr_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); @@ -395,6 +409,16 @@ bool workspace_switch(struct sway_container *workspace) { if (next == NULL) { next = workspace; } + if (has_sticky) { + // If there's a sticky container, we might be setting focus to the same + // container that's already focused, so seat_set_focus is effectively a + // no op. We therefore need to send the IPC event and clean up the old + // workspace here. + ipc_event_workspace(active_ws, workspace, "focus"); + if (!workspace_is_visible(active_ws) && workspace_is_empty(active_ws)) { + container_destroy(active_ws); + } + } seat_set_focus(seat, next); struct sway_container *output = container_parent(workspace, C_OUTPUT); arrange_output(output); @@ -418,8 +442,13 @@ bool workspace_is_empty(struct sway_container *ws) { if (ws->children->length) { return false; } - if (ws->sway_workspace->floating->children->length) { - return false; + // Sticky views are not considered to be part of this workspace + struct sway_container *floating = ws->sway_workspace->floating; + for (int i = 0; i < floating->children->length; ++i) { + struct sway_container *floater = floating->children->items[i]; + if (!floater->is_sticky) { + return false; + } } return true; }