aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-06-07 19:36:16 -0400
committerLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-06-08 13:08:00 -0400
commit5c9a917df9453f0463040b1164ba639b430f7833 (patch)
tree581a2b3056df2625de3d6dbcbb970b20fff260cb
parentMerge pull request #2121 from martinetd/swaylock-ctrl-u (diff)
downloadsway-5c9a917df9453f0463040b1164ba639b430f7833.tar.gz
sway-5c9a917df9453f0463040b1164ba639b430f7833.tar.zst
sway-5c9a917df9453f0463040b1164ba639b430f7833.zip
Restore workspaces to outputs based on priority
-rw-r--r--include/sway/tree/workspace.h9
-rw-r--r--sway/tree/container.c29
-rw-r--r--sway/tree/layout.c1
-rw-r--r--sway/tree/output.c49
-rw-r--r--sway/tree/workspace.c59
5 files changed, 130 insertions, 17 deletions
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h
index 81321fc8..c72a4ac0 100644
--- a/include/sway/tree/workspace.h
+++ b/include/sway/tree/workspace.h
@@ -9,6 +9,7 @@ struct sway_workspace {
9 struct sway_container *swayc; 9 struct sway_container *swayc;
10 struct sway_view *fullscreen; 10 struct sway_view *fullscreen;
11 struct sway_container *floating; 11 struct sway_container *floating;
12 list_t *output_priority;
12}; 13};
13 14
14extern char *prev_workspace_name; 15extern char *prev_workspace_name;
@@ -33,4 +34,12 @@ bool workspace_is_visible(struct sway_container *ws);
33 34
34bool workspace_is_empty(struct sway_container *ws); 35bool workspace_is_empty(struct sway_container *ws);
35 36
37void workspace_output_raise_priority(struct sway_container *workspace,
38 struct sway_container *old_output, struct sway_container *new_output);
39
40void workspace_output_add_priority(struct sway_container *workspace,
41 struct sway_container *output);
42
43struct sway_container *workspace_output_get_highest_available(
44 struct sway_container *ws, struct sway_container *exclude);
36#endif 45#endif
diff --git a/sway/tree/container.c b/sway/tree/container.c
index ca993c41..f36820b3 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -213,6 +213,9 @@ static struct sway_container *container_workspace_destroy(
213 sway_workspace->floating->parent = NULL; 213 sway_workspace->floating->parent = NULL;
214 _container_destroy(sway_workspace->floating); 214 _container_destroy(sway_workspace->floating);
215 215
216 list_foreach(sway_workspace->output_priority, free);
217 list_free(sway_workspace->output_priority);
218
216 free(sway_workspace); 219 free(sway_workspace);
217 220
218 if (output) { 221 if (output) {
@@ -234,24 +237,33 @@ static struct sway_container *container_output_destroy(
234 // program 237 // program
235 if (root_container.children->length > 1) { 238 if (root_container.children->length > 1) {
236 // Move workspace from this output to another output 239 // Move workspace from this output to another output
237 struct sway_container *other_output = 240 struct sway_container *fallback_output =
238 root_container.children->items[0]; 241 root_container.children->items[0];
239 if (other_output == output) { 242 if (fallback_output == output) {
240 other_output = root_container.children->items[1]; 243 fallback_output = root_container.children->items[1];
241 } 244 }
242 245
243 while (output->children->length) { 246 while (output->children->length) {
244 struct sway_container *workspace = output->children->items[0]; 247 struct sway_container *workspace = output->children->items[0];
248
249 struct sway_container *new_output =
250 workspace_output_get_highest_available(workspace, output);
251 if (!new_output) {
252 new_output = fallback_output;
253 workspace_output_add_priority(workspace, new_output);
254 }
255
245 container_remove_child(workspace); 256 container_remove_child(workspace);
246 if (workspace->children->length > 0) { 257 if (!workspace_is_empty(workspace)) {
247 container_add_child(other_output, workspace); 258 container_add_child(new_output, workspace);
248 ipc_event_workspace(workspace, NULL, "move"); 259 ipc_event_workspace(workspace, NULL, "move");
249 } else { 260 } else {
250 container_workspace_destroy(workspace); 261 container_workspace_destroy(workspace);
251 } 262 }
263
264 container_sort_workspaces(new_output);
265 arrange_output(new_output);
252 } 266 }
253 container_sort_workspaces(other_output);
254 arrange_output(other_output);
255 } 267 }
256 } 268 }
257 269
@@ -433,6 +445,9 @@ void container_descendants(struct sway_container *root,
433 func(item, data); 445 func(item, data);
434 } 446 }
435 container_descendants(item, type, func, data); 447 container_descendants(item, type, func, data);
448 if (i < root->children->length && root->children->items[i] != item) {
449 --i;
450 }
436 } 451 }
437} 452}
438 453
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index b54dc2fe..fc17d8c3 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -183,6 +183,7 @@ void container_move_to(struct sway_container *container,
183 } 183 }
184 container_sort_workspaces(new_parent); 184 container_sort_workspaces(new_parent);
185 seat_set_focus(seat, new_parent); 185 seat_set_focus(seat, new_parent);
186 workspace_output_raise_priority(container, old_parent, new_parent);
186 } 187 }
187 container_notify_subtree_changed(old_parent); 188 container_notify_subtree_changed(old_parent);
188 container_notify_subtree_changed(new_parent); 189 container_notify_subtree_changed(new_parent);
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 8823eba0..1ab8bed2 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -1,11 +1,35 @@
1#define _POSIX_C_SOURCE 200809L 1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 2#include <string.h>
3#include <strings.h> 3#include <strings.h>
4#include "sway/ipc-server.h"
4#include "sway/output.h" 5#include "sway/output.h"
6#include "sway/tree/arrange.h"
5#include "sway/tree/output.h" 7#include "sway/tree/output.h"
6#include "sway/tree/workspace.h" 8#include "sway/tree/workspace.h"
7#include "log.h" 9#include "log.h"
8 10
11static void restore_workspace(struct sway_container *ws, void *output) {
12 if (ws->parent == output) {
13 return;
14 }
15
16 struct sway_container *highest = workspace_output_get_highest_available(
17 ws, NULL);
18 if (!highest) {
19 return;
20 }
21
22 if (highest == output) {
23 struct sway_container *other = container_remove_child(ws);
24 container_add_child(output, ws);
25 ipc_event_workspace(ws, NULL, "move");
26
27 container_sort_workspaces(output);
28 arrange_output(output);
29 arrange_output(other);
30 }
31}
32
9struct sway_container *output_create( 33struct sway_container *output_create(
10 struct sway_output *sway_output) { 34 struct sway_output *sway_output) {
11 const char *name = sway_output->wlr_output->name; 35 const char *name = sway_output->wlr_output->name;
@@ -56,19 +80,24 @@ struct sway_container *output_create(
56 output->width = size.width; 80 output->width = size.width;
57 output->height = size.height; 81 output->height = size.height;
58 82
59 // Create workspace 83 container_descendants(&root_container, C_WORKSPACE, restore_workspace,
60 char *ws_name = workspace_next_name(output->name); 84 output);
61 wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); 85
62 struct sway_container *ws = workspace_create(output, ws_name); 86 if (!output->children->length) {
63 // Set each seat's focus if not already set 87 // Create workspace
64 struct sway_seat *seat = NULL; 88 char *ws_name = workspace_next_name(output->name);
65 wl_list_for_each(seat, &input_manager->seats, link) { 89 wlr_log(L_DEBUG, "Creating default workspace %s", ws_name);
66 if (!seat->has_focus) { 90 struct sway_container *ws = workspace_create(output, ws_name);
67 seat_set_focus(seat, ws); 91 // Set each seat's focus if not already set
92 struct sway_seat *seat = NULL;
93 wl_list_for_each(seat, &input_manager->seats, link) {
94 if (!seat->has_focus) {
95 seat_set_focus(seat, ws);
96 }
68 } 97 }
98 free(ws_name);
69 } 99 }
70 100
71 free(ws_name);
72 container_create_notify(output); 101 container_create_notify(output);
73 return output; 102 return output;
74} 103}
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index 3c42e259..9ba210fd 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -68,7 +68,9 @@ struct sway_container *workspace_create(struct sway_container *output,
68 swayws->floating = container_create(C_CONTAINER); 68 swayws->floating = container_create(C_CONTAINER);
69 swayws->floating->parent = swayws->swayc; 69 swayws->floating->parent = swayws->swayc;
70 swayws->floating->layout = L_FLOATING; 70 swayws->floating->layout = L_FLOATING;
71 swayws->output_priority = create_list();
71 workspace->sway_workspace = swayws; 72 workspace->sway_workspace = swayws;
73 workspace_output_add_priority(workspace, output);
72 74
73 container_add_child(output, workspace); 75 container_add_child(output, workspace);
74 container_sort_workspaces(output); 76 container_sort_workspaces(output);
@@ -454,3 +456,60 @@ bool workspace_is_empty(struct sway_container *ws) {
454 } 456 }
455 return true; 457 return true;
456} 458}
459
460static int find_output(const void *id1, const void *id2) {
461 return strcmp(id1, id2) ? 0 : 1;
462}
463
464void workspace_output_raise_priority(struct sway_container *workspace,
465 struct sway_container *old_output, struct sway_container *output) {
466 struct sway_workspace *ws = workspace->sway_workspace;
467
468 int old_index = list_seq_find(ws->output_priority, find_output,
469 old_output->name);
470 if (old_index < 0) {
471 return;
472 }
473
474 int new_index = list_seq_find(ws->output_priority, find_output,
475 output->name);
476 if (new_index < 0) {
477 list_insert(ws->output_priority, old_index, strdup(output->name));
478 } else if (new_index > old_index) {
479 char *name = ws->output_priority->items[new_index];
480 list_del(ws->output_priority, new_index);
481 list_insert(ws->output_priority, old_index, name);
482 }
483}
484
485void workspace_output_add_priority(struct sway_container *workspace,
486 struct sway_container *output) {
487 int index = list_seq_find(workspace->sway_workspace->output_priority,
488 find_output, output->name);
489 if (index < 0) {
490 list_add(workspace->sway_workspace->output_priority,
491 strdup(output->name));
492 }
493}
494
495static bool _output_by_name(struct sway_container *output, void *data) {
496 return output->type == C_OUTPUT && strcasecmp(output->name, data) == 0;
497}
498
499struct sway_container *workspace_output_get_highest_available(
500 struct sway_container *ws, struct sway_container *exclude) {
501 for (int i = 0; i < ws->sway_workspace->output_priority->length; i++) {
502 char *name = ws->sway_workspace->output_priority->items[i];
503 if (exclude && strcasecmp(name, exclude->name) == 0) {
504 continue;
505 }
506
507 struct sway_container *output = container_find(&root_container,
508 _output_by_name, name);
509 if (output) {
510 return output;
511 }
512 }
513
514 return NULL;
515}