mirror of
https://github.com/NickHu/sway
synced 2024-12-26 21:58:30 +01:00
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.
This commit is contained in:
parent
80a1c340a9
commit
12876932a9
5 changed files with 66 additions and 25 deletions
|
@ -183,7 +183,7 @@ struct side_gaps {
|
|||
*/
|
||||
struct workspace_config {
|
||||
char *workspace;
|
||||
char *output;
|
||||
list_t *outputs;
|
||||
int gaps_inner;
|
||||
struct side_gaps gaps_outer;
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) {
|
|||
return NULL;
|
||||
}
|
||||
wsc->workspace = strdup(ws_name);
|
||||
wsc->outputs = create_list();
|
||||
wsc->gaps_inner = INT_MIN;
|
||||
wsc->gaps_outer.top = INT_MIN;
|
||||
wsc->gaps_outer.right = INT_MIN;
|
||||
|
@ -32,7 +33,7 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) {
|
|||
|
||||
void free_workspace_config(struct workspace_config *wsc) {
|
||||
free(wsc->workspace);
|
||||
free(wsc->output);
|
||||
free_flat_list(wsc->outputs);
|
||||
free(wsc);
|
||||
}
|
||||
|
||||
|
@ -141,18 +142,20 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
if (output_location >= 0) {
|
||||
if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) {
|
||||
if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST,
|
||||
output_location + 2))) {
|
||||
return error;
|
||||
}
|
||||
char *ws_name = join_args(argv, argc - 2);
|
||||
char *ws_name = join_args(argv, output_location);
|
||||
struct workspace_config *wsc = workspace_config_find_or_create(ws_name);
|
||||
free(ws_name);
|
||||
if (!wsc) {
|
||||
return cmd_results_new(CMD_FAILURE, "workspace output",
|
||||
"Unable to allocate workspace output");
|
||||
}
|
||||
free(wsc->output);
|
||||
wsc->output = strdup(argv[output_location + 1]);
|
||||
for (int i = output_location + 1; i < argc; ++i) {
|
||||
list_add(wsc->outputs, strdup(argv[i]));
|
||||
}
|
||||
} else if (gaps_location >= 0) {
|
||||
if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) {
|
||||
return error;
|
||||
|
|
|
@ -573,8 +573,12 @@ The default colors are:
|
|||
Specifies that workspace _name_ should have the given gaps settings when it
|
||||
is created.
|
||||
|
||||
*workspace* <name> output <output>
|
||||
Specifies that workspace _name_ should be shown on the specified _output_.
|
||||
*workspace* <name> output <outputs...>
|
||||
Specifies that workspace _name_ should be shown on the specified _outputs_.
|
||||
Multiple outputs can be listed and the first available will be used. If the
|
||||
workspace gets placed on an output further down the list and an output that
|
||||
is higher on the list becomes available, the workspace will be move to the
|
||||
higher priority output.
|
||||
|
||||
*workspace\_auto\_back\_and\_forth* yes|no
|
||||
When _yes_, repeating a workspace switch command will switch back to the
|
||||
|
|
|
@ -31,6 +31,13 @@ static void restore_workspaces(struct sway_output *output) {
|
|||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
if (other->workspaces->length == 0) {
|
||||
char *next = workspace_next_name(other->wlr_output->name);
|
||||
struct sway_workspace *ws = workspace_create(other, next);
|
||||
free(next);
|
||||
ipc_event_workspace(NULL, ws, "init");
|
||||
}
|
||||
}
|
||||
|
||||
// Saved workspaces
|
||||
|
|
|
@ -33,14 +33,15 @@ struct workspace_config *workspace_find_config(const char *ws_name) {
|
|||
struct sway_output *workspace_get_initial_output(const char *name) {
|
||||
// Check workspace configs for a workspace<->output pair
|
||||
struct workspace_config *wsc = workspace_find_config(name);
|
||||
if (wsc && wsc->output) {
|
||||
struct sway_output *output = output_by_name(wsc->output);
|
||||
if (!output) {
|
||||
output = output_by_identifier(wsc->output);
|
||||
}
|
||||
|
||||
if (output) {
|
||||
return output;
|
||||
if (wsc) {
|
||||
for (int i = 0; i < wsc->outputs->length; i++) {
|
||||
struct sway_output *output = output_by_name(wsc->outputs->items[i]);
|
||||
if (!output) {
|
||||
output = output_by_identifier(wsc->outputs->items[i]);
|
||||
}
|
||||
if (output) {
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Otherwise put it on the focused output
|
||||
|
@ -85,7 +86,6 @@ struct sway_workspace *workspace_create(struct sway_output *output,
|
|||
ws->floating = create_list();
|
||||
ws->tiling = create_list();
|
||||
ws->output_priority = create_list();
|
||||
workspace_output_add_priority(ws, output);
|
||||
|
||||
ws->gaps_outer = config->gaps_outer;
|
||||
ws->gaps_inner = config->gaps_inner;
|
||||
|
@ -110,9 +110,17 @@ struct sway_workspace *workspace_create(struct sway_output *output,
|
|||
// Since default outer gaps can be smaller than the negation of
|
||||
// workspace specific inner gaps, check outer gaps again
|
||||
prevent_invalid_outer_gaps(ws);
|
||||
|
||||
// Add output priorities
|
||||
for (int i = 0; i < wsc->outputs->length; ++i) {
|
||||
list_add(ws->output_priority, strdup(wsc->outputs->items[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If not already added, add the output to the lowest priority
|
||||
workspace_output_add_priority(ws, output);
|
||||
|
||||
output_add_workspace(output, ws);
|
||||
output_sort_workspaces(output);
|
||||
|
||||
|
@ -134,8 +142,7 @@ void workspace_destroy(struct sway_workspace *workspace) {
|
|||
|
||||
free(workspace->name);
|
||||
free(workspace->representation);
|
||||
list_foreach(workspace->output_priority, free);
|
||||
list_free(workspace->output_priority);
|
||||
free_flat_list(workspace->output_priority);
|
||||
list_free(workspace->floating);
|
||||
list_free(workspace->tiling);
|
||||
list_free(workspace->current.floating);
|
||||
|
@ -177,8 +184,19 @@ static bool workspace_valid_on_output(const char *output_name,
|
|||
char identifier[128];
|
||||
struct sway_output *output = output_by_name(output_name);
|
||||
output_get_identifier(identifier, sizeof(identifier), output);
|
||||
|
||||
return !wsc || !wsc->output || strcmp(wsc->output, output_name) == 0 || strcasecmp(identifier, output_name) == 0;
|
||||
|
||||
if (!wsc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < wsc->outputs->length; i++) {
|
||||
if (strcmp(wsc->outputs->items[i], output_name) == 0 ||
|
||||
strcmp(wsc->outputs->items[i], identifier) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void workspace_name_from_binding(const struct sway_binding * binding,
|
||||
|
@ -281,10 +299,19 @@ char *workspace_next_name(const char *output_name) {
|
|||
for (int i = 0; i < config->workspace_configs->length; ++i) {
|
||||
// Unlike with bindings, this does not guarantee order
|
||||
const struct workspace_config *wsc = config->workspace_configs->items[i];
|
||||
if (wsc->output && strcmp(wsc->output, output_name) == 0
|
||||
&& workspace_by_name(wsc->workspace) == NULL) {
|
||||
free(target);
|
||||
target = strdup(wsc->workspace);
|
||||
if (workspace_by_name(wsc->workspace)) {
|
||||
continue;
|
||||
}
|
||||
bool found = false;
|
||||
for (int j = 0; j < wsc->outputs->length; ++j) {
|
||||
if (strcmp(wsc->outputs->items[j], output_name) == 0) {
|
||||
found = true;
|
||||
free(target);
|
||||
target = strdup(wsc->workspace);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue