aboutsummaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-05-25 15:39:14 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-06-01 23:14:58 +1000
commitdc83b158e12ae33f03165cfd64a50aa7f0a52e26 (patch)
treea618595ef3b8c2eb29004cf8479742dc012a4561 /sway
parentFix unfullscreening a floating view (diff)
downloadsway-dc83b158e12ae33f03165cfd64a50aa7f0a52e26.tar.gz
sway-dc83b158e12ae33f03165cfd64a50aa7f0a52e26.tar.zst
sway-dc83b158e12ae33f03165cfd64a50aa7f0a52e26.zip
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.
Diffstat (limited to 'sway')
-rw-r--r--sway/desktop/output.c7
-rw-r--r--sway/tree/container.c45
-rw-r--r--sway/tree/workspace.c35
3 files changed, 54 insertions, 33 deletions
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,
832 for (int j = 0; j < output->children->length; ++j) { 832 for (int j = 0; j < output->children->length; ++j) {
833 struct sway_container *workspace = output->children->items[j]; 833 struct sway_container *workspace = output->children->items[j];
834 struct sway_workspace *ws = workspace->sway_workspace; 834 struct sway_workspace *ws = workspace->sway_workspace;
835 bool ws_is_visible = workspace_is_visible(workspace); 835 if (!workspace_is_visible(workspace)) {
836 continue;
837 }
836 for (int k = 0; k < ws->floating->children->length; ++k) { 838 for (int k = 0; k < ws->floating->children->length; ++k) {
837 struct sway_container *floater = 839 struct sway_container *floater =
838 ws->floating->children->items[k]; 840 ws->floating->children->items[k];
839 if ((ws_is_visible || floater->is_sticky) 841 if (floater_intersects_output(floater, soutput->swayc)) {
840 && floater_intersects_output(floater, soutput->swayc)) {
841 render_floating_container(soutput, damage, floater); 842 render_floating_container(soutput, damage, floater);
842 } 843 }
843 } 844 }
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) {
64 } 64 }
65} 65}
66 66
67static void container_close_notify(struct sway_container *container) {
68 if (container == NULL) {
69 return;
70 }
71 // TODO send ipc event type based on the container type
72 if (container->type == C_VIEW || container->type == C_WORKSPACE) {
73 ipc_event_window(container, "close");
74 }
75}
76
77static void container_update_textures_recursive(struct sway_container *con) { 67static void container_update_textures_recursive(struct sway_container *con) {
78 container_update_title_textures(con); 68 container_update_title_textures(con);
79 69
@@ -143,7 +133,6 @@ static void _container_destroy(struct sway_container *cont) {
143 } 133 }
144 134
145 wl_signal_emit(&cont->events.destroy, cont); 135 wl_signal_emit(&cont->events.destroy, cont);
146 container_close_notify(cont);
147 136
148 struct sway_container *parent = cont->parent; 137 struct sway_container *parent = cont->parent;
149 if (cont->children != NULL && cont->children->length) { 138 if (cont->children != NULL && cont->children->length) {
@@ -151,6 +140,7 @@ static void _container_destroy(struct sway_container *cont) {
151 // container_remove_child, which removes child from this container 140 // container_remove_child, which removes child from this container
152 while (cont->children != NULL && cont->children->length > 0) { 141 while (cont->children != NULL && cont->children->length > 0) {
153 struct sway_container *child = cont->children->items[0]; 142 struct sway_container *child = cont->children->items[0];
143 ipc_event_window(child, "close");
154 container_remove_child(child); 144 container_remove_child(child);
155 _container_destroy(child); 145 _container_destroy(child);
156 } 146 }
@@ -188,12 +178,11 @@ static struct sway_container *container_workspace_destroy(
188 return NULL; 178 return NULL;
189 } 179 }
190 180
181 wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name);
182 ipc_event_window(workspace, "close");
183
191 struct sway_container *parent = workspace->parent; 184 struct sway_container *parent = workspace->parent;
192 if (workspace_is_empty(workspace)) { 185 if (!workspace_is_empty(workspace) && output) {
193 // destroy the WS if there are no children
194 wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name);
195 ipc_event_workspace(workspace, NULL, "empty");
196 } else if (output) {
197 // Move children to a different workspace on this output 186 // Move children to a different workspace on this output
198 struct sway_container *new_workspace = NULL; 187 struct sway_container *new_workspace = NULL;
199 for (int i = 0; i < output->children->length; i++) { 188 for (int i = 0; i < output->children->length; i++) {
@@ -357,10 +346,12 @@ struct sway_container *container_destroy(struct sway_container *con) {
357 if (con->children->length) { 346 if (con->children->length) {
358 for (int i = 0; i < con->children->length; ++i) { 347 for (int i = 0; i < con->children->length; ++i) {
359 struct sway_container *child = con->children->items[0]; 348 struct sway_container *child = con->children->items[0];
349 ipc_event_window(child, "close");
360 container_remove_child(child); 350 container_remove_child(child);
361 container_add_child(parent, child); 351 container_add_child(parent, child);
362 } 352 }
363 } 353 }
354 ipc_event_window(con, "close");
364 _container_destroy(con); 355 _container_destroy(con);
365 break; 356 break;
366 case C_VIEW: 357 case C_VIEW:
@@ -635,20 +626,20 @@ struct sway_container *floating_container_at(double lx, double ly,
635 for (int j = 0; j < output->children->length; ++j) { 626 for (int j = 0; j < output->children->length; ++j) {
636 struct sway_container *workspace = output->children->items[j]; 627 struct sway_container *workspace = output->children->items[j];
637 struct sway_workspace *ws = workspace->sway_workspace; 628 struct sway_workspace *ws = workspace->sway_workspace;
638 bool ws_is_visible = workspace_is_visible(workspace); 629 if (!workspace_is_visible(workspace)) {
630 continue;
631 }
639 for (int k = 0; k < ws->floating->children->length; ++k) { 632 for (int k = 0; k < ws->floating->children->length; ++k) {
640 struct sway_container *floater = 633 struct sway_container *floater =
641 ws->floating->children->items[k]; 634 ws->floating->children->items[k];
642 if (ws_is_visible || floater->is_sticky) { 635 struct wlr_box box = {
643 struct wlr_box box = { 636 .x = floater->x,
644 .x = floater->x, 637 .y = floater->y,
645 .y = floater->y, 638 .width = floater->width,
646 .width = floater->width, 639 .height = floater->height,
647 .height = floater->height, 640 };
648 }; 641 if (wlr_box_contains_point(&box, lx, ly)) {
649 if (wlr_box_contains_point(&box, lx, ly)) { 642 return container_at(floater, lx, ly, surface, sx, sy);
650 return container_at(floater, lx, ly, surface, sx, sy);
651 }
652 } 643 }
653 } 644 }
654 } 645 }
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) {
387 strcpy(prev_workspace_name, active_ws->name); 387 strcpy(prev_workspace_name, active_ws->name);
388 } 388 }
389 389
390 // TODO: Deal with sticky containers 390 // Move sticky containers to new workspace
391 struct sway_container *next_output = workspace->parent;
392 struct sway_container *next_output_prev_ws =
393 seat_get_active_child(seat, next_output);
394 struct sway_container *floating =
395 next_output_prev_ws->sway_workspace->floating;
396 bool has_sticky = false;
397 for (int i = 0; i < floating->children->length; ++i) {
398 struct sway_container *floater = floating->children->items[i];
399 if (floater->is_sticky) {
400 has_sticky = true;
401 container_remove_child(floater);
402 container_add_child(workspace->sway_workspace->floating, floater);
403 }
404 }
391 405
392 wlr_log(L_DEBUG, "Switching to workspace %p:%s", 406 wlr_log(L_DEBUG, "Switching to workspace %p:%s",
393 workspace, workspace->name); 407 workspace, workspace->name);
@@ -395,6 +409,16 @@ bool workspace_switch(struct sway_container *workspace) {
395 if (next == NULL) { 409 if (next == NULL) {
396 next = workspace; 410 next = workspace;
397 } 411 }
412 if (has_sticky) {
413 // If there's a sticky container, we might be setting focus to the same
414 // container that's already focused, so seat_set_focus is effectively a
415 // no op. We therefore need to send the IPC event and clean up the old
416 // workspace here.
417 ipc_event_workspace(active_ws, workspace, "focus");
418 if (!workspace_is_visible(active_ws) && workspace_is_empty(active_ws)) {
419 container_destroy(active_ws);
420 }
421 }
398 seat_set_focus(seat, next); 422 seat_set_focus(seat, next);
399 struct sway_container *output = container_parent(workspace, C_OUTPUT); 423 struct sway_container *output = container_parent(workspace, C_OUTPUT);
400 arrange_output(output); 424 arrange_output(output);
@@ -418,8 +442,13 @@ bool workspace_is_empty(struct sway_container *ws) {
418 if (ws->children->length) { 442 if (ws->children->length) {
419 return false; 443 return false;
420 } 444 }
421 if (ws->sway_workspace->floating->children->length) { 445 // Sticky views are not considered to be part of this workspace
422 return false; 446 struct sway_container *floating = ws->sway_workspace->floating;
447 for (int i = 0; i < floating->children->length; ++i) {
448 struct sway_container *floater = floating->children->items[i];
449 if (!floater->is_sticky) {
450 return false;
451 }
423 } 452 }
424 return true; 453 return true;
425} 454}