Skip to content

Commit 0b798ed

Browse files
authored
Merge pull request #2115 from RedSoxFan/restore-workspaces
Restore workspaces to output when re-enabled
2 parents c65c844 + e2b2fb0 commit 0b798ed

File tree

5 files changed

+131
-17
lines changed

5 files changed

+131
-17
lines changed

include/sway/tree/workspace.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ struct sway_workspace {
99
struct sway_container *swayc;
1010
struct sway_view *fullscreen;
1111
struct sway_container *floating;
12+
list_t *output_priority;
1213
};
1314

1415
extern char *prev_workspace_name;
@@ -33,4 +34,12 @@ bool workspace_is_visible(struct sway_container *ws);
3334

3435
bool workspace_is_empty(struct sway_container *ws);
3536

37+
void workspace_output_raise_priority(struct sway_container *workspace,
38+
struct sway_container *old_output, struct sway_container *new_output);
39+
40+
void workspace_output_add_priority(struct sway_container *workspace,
41+
struct sway_container *output);
42+
43+
struct sway_container *workspace_output_get_highest_available(
44+
struct sway_container *ws, struct sway_container *exclude);
3645
#endif

sway/tree/container.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ static struct sway_container *container_workspace_destroy(
213213
sway_workspace->floating->parent = NULL;
214214
_container_destroy(sway_workspace->floating);
215215

216+
list_foreach(sway_workspace->output_priority, free);
217+
list_free(sway_workspace->output_priority);
218+
216219
free(sway_workspace);
217220

218221
if (output) {
@@ -234,24 +237,33 @@ static struct sway_container *container_output_destroy(
234237
// program
235238
if (root_container.children->length > 1) {
236239
// Move workspace from this output to another output
237-
struct sway_container *other_output =
240+
struct sway_container *fallback_output =
238241
root_container.children->items[0];
239-
if (other_output == output) {
240-
other_output = root_container.children->items[1];
242+
if (fallback_output == output) {
243+
fallback_output = root_container.children->items[1];
241244
}
242245

243246
while (output->children->length) {
244247
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+
245256
container_remove_child(workspace);
246-
if (workspace->children->length > 0) {
247-
container_add_child(other_output, workspace);
257+
if (!workspace_is_empty(workspace)) {
258+
container_add_child(new_output, workspace);
248259
ipc_event_workspace(workspace, NULL, "move");
249260
} else {
250261
container_workspace_destroy(workspace);
251262
}
263+
264+
container_sort_workspaces(new_output);
265+
arrange_output(new_output);
252266
}
253-
container_sort_workspaces(other_output);
254-
arrange_output(other_output);
255267
}
256268
}
257269

sway/tree/layout.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ void container_move_to(struct sway_container *container,
183183
}
184184
container_sort_workspaces(new_parent);
185185
seat_set_focus(seat, new_parent);
186+
workspace_output_raise_priority(container, old_parent, new_parent);
187+
ipc_event_workspace(container, NULL, "move");
186188
}
187189
container_notify_subtree_changed(old_parent);
188190
container_notify_subtree_changed(new_parent);

sway/tree/output.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,39 @@
11
#define _POSIX_C_SOURCE 200809L
22
#include <string.h>
33
#include <strings.h>
4+
#include "sway/ipc-server.h"
45
#include "sway/output.h"
6+
#include "sway/tree/arrange.h"
57
#include "sway/tree/output.h"
68
#include "sway/tree/workspace.h"
79
#include "log.h"
810

11+
static void restore_workspaces(struct sway_container *output) {
12+
for (int i = 0; i < root_container.children->length; i++) {
13+
struct sway_container *other = root_container.children->items[i];
14+
if (other == output) {
15+
continue;
16+
}
17+
18+
for (int j = 0; j < other->children->length; j++) {
19+
struct sway_container *ws = other->children->items[j];
20+
struct sway_container *highest =
21+
workspace_output_get_highest_available(ws, NULL);
22+
if (highest == output) {
23+
container_remove_child(ws);
24+
container_add_child(output, ws);
25+
ipc_event_workspace(ws, NULL, "move");
26+
j--;
27+
}
28+
}
29+
30+
arrange_output(other);
31+
}
32+
33+
container_sort_workspaces(output);
34+
arrange_output(output);
35+
}
36+
937
struct sway_container *output_create(
1038
struct sway_output *sway_output) {
1139
const char *name = sway_output->wlr_output->name;
@@ -56,19 +84,23 @@ struct sway_container *output_create(
5684
output->width = size.width;
5785
output->height = size.height;
5886

59-
// Create workspace
60-
char *ws_name = workspace_next_name(output->name);
61-
wlr_log(L_DEBUG, "Creating default workspace %s", ws_name);
62-
struct sway_container *ws = workspace_create(output, ws_name);
63-
// Set each seat's focus if not already set
64-
struct sway_seat *seat = NULL;
65-
wl_list_for_each(seat, &input_manager->seats, link) {
66-
if (!seat->has_focus) {
67-
seat_set_focus(seat, ws);
87+
restore_workspaces(output);
88+
89+
if (!output->children->length) {
90+
// Create workspace
91+
char *ws_name = workspace_next_name(output->name);
92+
wlr_log(L_DEBUG, "Creating default workspace %s", ws_name);
93+
struct sway_container *ws = workspace_create(output, ws_name);
94+
// Set each seat's focus if not already set
95+
struct sway_seat *seat = NULL;
96+
wl_list_for_each(seat, &input_manager->seats, link) {
97+
if (!seat->has_focus) {
98+
seat_set_focus(seat, ws);
99+
}
68100
}
101+
free(ws_name);
69102
}
70103

71-
free(ws_name);
72104
container_create_notify(output);
73105
return output;
74106
}

sway/tree/workspace.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ struct sway_container *workspace_create(struct sway_container *output,
6868
swayws->floating = container_create(C_CONTAINER);
6969
swayws->floating->parent = swayws->swayc;
7070
swayws->floating->layout = L_FLOATING;
71+
swayws->output_priority = create_list();
7172
workspace->sway_workspace = swayws;
73+
workspace_output_add_priority(workspace, output);
7274

7375
container_add_child(output, workspace);
7476
container_sort_workspaces(output);
@@ -454,3 +456,60 @@ bool workspace_is_empty(struct sway_container *ws) {
454456
}
455457
return true;
456458
}
459+
460+
static int find_output(const void *id1, const void *id2) {
461+
return strcmp(id1, id2) ? 0 : 1;
462+
}
463+
464+
void 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+
485+
void 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+
495+
static bool _output_by_name(struct sway_container *output, void *data) {
496+
return output->type == C_OUTPUT && strcasecmp(output->name, data) == 0;
497+
}
498+
499+
struct 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+
}

0 commit comments

Comments
 (0)