Fix issues with sticky containers and workspaces

* Attach sticky containers to new workspaces when switching
* Fire the close event *before* we start destroying the workspace to
prevent a crash

Because the sticky container now follows the visible workspace, this
simplifies the rendering and container_at logic.
This commit is contained in:
Ryan Dwyer 2018-05-25 15:39:14 +10:00
parent 13a4b0512e
commit dc83b158e1
3 changed files with 54 additions and 33 deletions

View file

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