aboutsummaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-11-11 11:22:38 -0500
committerLibravatar Brian Ashworth <bosrsf04@gmail.com>2018-11-11 11:22:38 -0500
commit12876932a948d7265745efaccafea509bdbaffe8 (patch)
tree458a3acb6db39a78d26b4ce38ea637aa21812e29 /sway
parentMerge pull request #3098 from c-edw/feature/RefactorArgParse (diff)
downloadsway-12876932a948d7265745efaccafea509bdbaffe8.tar.gz
sway-12876932a948d7265745efaccafea509bdbaffe8.tar.zst
sway-12876932a948d7265745efaccafea509bdbaffe8.zip
Allow multiple outputs for workspace output
`i3 4.16` allows users to list multiple outputs for a workspace and the first available will be used. The syntax is as follows: `workspace <workspace> output <outputs...>` Additionally when the workspace is created, the outputs get added to the output priority list in the order specified. This ensures that if a higher output gets connected, the workspace will move to the higher output. This works the same way as if the user had a workspace on an output, disconnected the output, and then later reconnected the output.
Diffstat (limited to 'sway')
-rw-r--r--sway/commands/workspace.c13
-rw-r--r--sway/sway.5.scd8
-rw-r--r--sway/tree/output.c7
-rw-r--r--sway/tree/workspace.c61
4 files changed, 65 insertions, 24 deletions
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c
index 168494d2..92118ecf 100644
--- a/sway/commands/workspace.c
+++ b/sway/commands/workspace.c
@@ -21,6 +21,7 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) {
21 return NULL; 21 return NULL;
22 } 22 }
23 wsc->workspace = strdup(ws_name); 23 wsc->workspace = strdup(ws_name);
24 wsc->outputs = create_list();
24 wsc->gaps_inner = INT_MIN; 25 wsc->gaps_inner = INT_MIN;
25 wsc->gaps_outer.top = INT_MIN; 26 wsc->gaps_outer.top = INT_MIN;
26 wsc->gaps_outer.right = INT_MIN; 27 wsc->gaps_outer.right = INT_MIN;
@@ -32,7 +33,7 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) {
32 33
33void free_workspace_config(struct workspace_config *wsc) { 34void free_workspace_config(struct workspace_config *wsc) {
34 free(wsc->workspace); 35 free(wsc->workspace);
35 free(wsc->output); 36 free_flat_list(wsc->outputs);
36 free(wsc); 37 free(wsc);
37} 38}
38 39
@@ -141,18 +142,20 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
141 } 142 }
142 } 143 }
143 if (output_location >= 0) { 144 if (output_location >= 0) {
144 if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) { 145 if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST,
146 output_location + 2))) {
145 return error; 147 return error;
146 } 148 }
147 char *ws_name = join_args(argv, argc - 2); 149 char *ws_name = join_args(argv, output_location);
148 struct workspace_config *wsc = workspace_config_find_or_create(ws_name); 150 struct workspace_config *wsc = workspace_config_find_or_create(ws_name);
149 free(ws_name); 151 free(ws_name);
150 if (!wsc) { 152 if (!wsc) {
151 return cmd_results_new(CMD_FAILURE, "workspace output", 153 return cmd_results_new(CMD_FAILURE, "workspace output",
152 "Unable to allocate workspace output"); 154 "Unable to allocate workspace output");
153 } 155 }
154 free(wsc->output); 156 for (int i = output_location + 1; i < argc; ++i) {
155 wsc->output = strdup(argv[output_location + 1]); 157 list_add(wsc->outputs, strdup(argv[i]));
158 }
156 } else if (gaps_location >= 0) { 159 } else if (gaps_location >= 0) {
157 if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) { 160 if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) {
158 return error; 161 return error;
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 8f6b35f1..1a11015f 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -573,8 +573,12 @@ The default colors are:
573 Specifies that workspace _name_ should have the given gaps settings when it 573 Specifies that workspace _name_ should have the given gaps settings when it
574 is created. 574 is created.
575 575
576*workspace* <name> output <output> 576*workspace* <name> output <outputs...>
577 Specifies that workspace _name_ should be shown on the specified _output_. 577 Specifies that workspace _name_ should be shown on the specified _outputs_.
578 Multiple outputs can be listed and the first available will be used. If the
579 workspace gets placed on an output further down the list and an output that
580 is higher on the list becomes available, the workspace will be move to the
581 higher priority output.
578 582
579*workspace\_auto\_back\_and\_forth* yes|no 583*workspace\_auto\_back\_and\_forth* yes|no
580 When _yes_, repeating a workspace switch command will switch back to the 584 When _yes_, repeating a workspace switch command will switch back to the
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 2704920d..3c4614a8 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -31,6 +31,13 @@ static void restore_workspaces(struct sway_output *output) {
31 j--; 31 j--;
32 } 32 }
33 } 33 }
34
35 if (other->workspaces->length == 0) {
36 char *next = workspace_next_name(other->wlr_output->name);
37 struct sway_workspace *ws = workspace_create(other, next);
38 free(next);
39 ipc_event_workspace(NULL, ws, "init");
40 }
34 } 41 }
35 42
36 // Saved workspaces 43 // Saved workspaces
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index 93ce50de..4be63311 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -33,14 +33,15 @@ struct workspace_config *workspace_find_config(const char *ws_name) {
33struct sway_output *workspace_get_initial_output(const char *name) { 33struct sway_output *workspace_get_initial_output(const char *name) {
34 // Check workspace configs for a workspace<->output pair 34 // Check workspace configs for a workspace<->output pair
35 struct workspace_config *wsc = workspace_find_config(name); 35 struct workspace_config *wsc = workspace_find_config(name);
36 if (wsc && wsc->output) { 36 if (wsc) {
37 struct sway_output *output = output_by_name(wsc->output); 37 for (int i = 0; i < wsc->outputs->length; i++) {
38 if (!output) { 38 struct sway_output *output = output_by_name(wsc->outputs->items[i]);
39 output = output_by_identifier(wsc->output); 39 if (!output) {
40 } 40 output = output_by_identifier(wsc->outputs->items[i]);
41 41 }
42 if (output) { 42 if (output) {
43 return output; 43 return output;
44 }
44 } 45 }
45 } 46 }
46 // Otherwise put it on the focused output 47 // Otherwise put it on the focused output
@@ -85,7 +86,6 @@ struct sway_workspace *workspace_create(struct sway_output *output,
85 ws->floating = create_list(); 86 ws->floating = create_list();
86 ws->tiling = create_list(); 87 ws->tiling = create_list();
87 ws->output_priority = create_list(); 88 ws->output_priority = create_list();
88 workspace_output_add_priority(ws, output);
89 89
90 ws->gaps_outer = config->gaps_outer; 90 ws->gaps_outer = config->gaps_outer;
91 ws->gaps_inner = config->gaps_inner; 91 ws->gaps_inner = config->gaps_inner;
@@ -110,9 +110,17 @@ struct sway_workspace *workspace_create(struct sway_output *output,
110 // Since default outer gaps can be smaller than the negation of 110 // Since default outer gaps can be smaller than the negation of
111 // workspace specific inner gaps, check outer gaps again 111 // workspace specific inner gaps, check outer gaps again
112 prevent_invalid_outer_gaps(ws); 112 prevent_invalid_outer_gaps(ws);
113
114 // Add output priorities
115 for (int i = 0; i < wsc->outputs->length; ++i) {
116 list_add(ws->output_priority, strdup(wsc->outputs->items[i]));
117 }
113 } 118 }
114 } 119 }
115 120
121 // If not already added, add the output to the lowest priority
122 workspace_output_add_priority(ws, output);
123
116 output_add_workspace(output, ws); 124 output_add_workspace(output, ws);
117 output_sort_workspaces(output); 125 output_sort_workspaces(output);
118 126
@@ -134,8 +142,7 @@ void workspace_destroy(struct sway_workspace *workspace) {
134 142
135 free(workspace->name); 143 free(workspace->name);
136 free(workspace->representation); 144 free(workspace->representation);
137 list_foreach(workspace->output_priority, free); 145 free_flat_list(workspace->output_priority);
138 list_free(workspace->output_priority);
139 list_free(workspace->floating); 146 list_free(workspace->floating);
140 list_free(workspace->tiling); 147 list_free(workspace->tiling);
141 list_free(workspace->current.floating); 148 list_free(workspace->current.floating);
@@ -177,8 +184,19 @@ static bool workspace_valid_on_output(const char *output_name,
177 char identifier[128]; 184 char identifier[128];
178 struct sway_output *output = output_by_name(output_name); 185 struct sway_output *output = output_by_name(output_name);
179 output_get_identifier(identifier, sizeof(identifier), output); 186 output_get_identifier(identifier, sizeof(identifier), output);
180 187
181 return !wsc || !wsc->output || strcmp(wsc->output, output_name) == 0 || strcasecmp(identifier, output_name) == 0; 188 if (!wsc) {
189 return true;
190 }
191
192 for (int i = 0; i < wsc->outputs->length; i++) {
193 if (strcmp(wsc->outputs->items[i], output_name) == 0 ||
194 strcmp(wsc->outputs->items[i], identifier) == 0) {
195 return true;
196 }
197 }
198
199 return false;
182} 200}
183 201
184static void workspace_name_from_binding(const struct sway_binding * binding, 202static void workspace_name_from_binding(const struct sway_binding * binding,
@@ -281,10 +299,19 @@ char *workspace_next_name(const char *output_name) {
281 for (int i = 0; i < config->workspace_configs->length; ++i) { 299 for (int i = 0; i < config->workspace_configs->length; ++i) {
282 // Unlike with bindings, this does not guarantee order 300 // Unlike with bindings, this does not guarantee order
283 const struct workspace_config *wsc = config->workspace_configs->items[i]; 301 const struct workspace_config *wsc = config->workspace_configs->items[i];
284 if (wsc->output && strcmp(wsc->output, output_name) == 0 302 if (workspace_by_name(wsc->workspace)) {
285 && workspace_by_name(wsc->workspace) == NULL) { 303 continue;
286 free(target); 304 }
287 target = strdup(wsc->workspace); 305 bool found = false;
306 for (int j = 0; j < wsc->outputs->length; ++j) {
307 if (strcmp(wsc->outputs->items[j], output_name) == 0) {
308 found = true;
309 free(target);
310 target = strdup(wsc->workspace);
311 break;
312 }
313 }
314 if (found) {
288 break; 315 break;
289 } 316 }
290 } 317 }