mirror of
https://github.com/swaywm/sway.git
synced 2024-11-14 06:24:20 +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
@ -183,7 +183,7 @@ struct side_gaps {
|
|||||||
*/
|
*/
|
||||||
struct workspace_config {
|
struct workspace_config {
|
||||||
char *workspace;
|
char *workspace;
|
||||||
char *output;
|
list_t *outputs;
|
||||||
int gaps_inner;
|
int gaps_inner;
|
||||||
struct side_gaps gaps_outer;
|
struct side_gaps gaps_outer;
|
||||||
};
|
};
|
||||||
|
@ -21,6 +21,7 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
wsc->workspace = strdup(ws_name);
|
wsc->workspace = strdup(ws_name);
|
||||||
|
wsc->outputs = create_list();
|
||||||
wsc->gaps_inner = INT_MIN;
|
wsc->gaps_inner = INT_MIN;
|
||||||
wsc->gaps_outer.top = INT_MIN;
|
wsc->gaps_outer.top = INT_MIN;
|
||||||
wsc->gaps_outer.right = 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) {
|
void free_workspace_config(struct workspace_config *wsc) {
|
||||||
free(wsc->workspace);
|
free(wsc->workspace);
|
||||||
free(wsc->output);
|
free_flat_list(wsc->outputs);
|
||||||
free(wsc);
|
free(wsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,18 +142,20 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (output_location >= 0) {
|
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;
|
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);
|
struct workspace_config *wsc = workspace_config_find_or_create(ws_name);
|
||||||
free(ws_name);
|
free(ws_name);
|
||||||
if (!wsc) {
|
if (!wsc) {
|
||||||
return cmd_results_new(CMD_FAILURE, "workspace output",
|
return cmd_results_new(CMD_FAILURE, "workspace output",
|
||||||
"Unable to allocate workspace output");
|
"Unable to allocate workspace output");
|
||||||
}
|
}
|
||||||
free(wsc->output);
|
for (int i = output_location + 1; i < argc; ++i) {
|
||||||
wsc->output = strdup(argv[output_location + 1]);
|
list_add(wsc->outputs, strdup(argv[i]));
|
||||||
|
}
|
||||||
} else if (gaps_location >= 0) {
|
} else if (gaps_location >= 0) {
|
||||||
if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) {
|
if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) {
|
||||||
return error;
|
return error;
|
||||||
|
@ -573,8 +573,12 @@ The default colors are:
|
|||||||
Specifies that workspace _name_ should have the given gaps settings when it
|
Specifies that workspace _name_ should have the given gaps settings when it
|
||||||
is created.
|
is created.
|
||||||
|
|
||||||
*workspace* <name> output <output>
|
*workspace* <name> output <outputs...>
|
||||||
Specifies that workspace _name_ should be shown on the specified _output_.
|
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
|
*workspace\_auto\_back\_and\_forth* yes|no
|
||||||
When _yes_, repeating a workspace switch command will switch back to the
|
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--;
|
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
|
// Saved workspaces
|
||||||
|
@ -33,16 +33,17 @@ struct workspace_config *workspace_find_config(const char *ws_name) {
|
|||||||
struct sway_output *workspace_get_initial_output(const char *name) {
|
struct sway_output *workspace_get_initial_output(const char *name) {
|
||||||
// Check workspace configs for a workspace<->output pair
|
// Check workspace configs for a workspace<->output pair
|
||||||
struct workspace_config *wsc = workspace_find_config(name);
|
struct workspace_config *wsc = workspace_find_config(name);
|
||||||
if (wsc && wsc->output) {
|
if (wsc) {
|
||||||
struct sway_output *output = output_by_name(wsc->output);
|
for (int i = 0; i < wsc->outputs->length; i++) {
|
||||||
|
struct sway_output *output = output_by_name(wsc->outputs->items[i]);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
output = output_by_identifier(wsc->output);
|
output = output_by_identifier(wsc->outputs->items[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output) {
|
if (output) {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Otherwise put it on the focused output
|
// Otherwise put it on the focused output
|
||||||
struct sway_seat *seat = input_manager_current_seat();
|
struct sway_seat *seat = input_manager_current_seat();
|
||||||
struct sway_workspace *focus = seat_get_focused_workspace(seat);
|
struct sway_workspace *focus = seat_get_focused_workspace(seat);
|
||||||
@ -85,7 +86,6 @@ struct sway_workspace *workspace_create(struct sway_output *output,
|
|||||||
ws->floating = create_list();
|
ws->floating = create_list();
|
||||||
ws->tiling = create_list();
|
ws->tiling = create_list();
|
||||||
ws->output_priority = create_list();
|
ws->output_priority = create_list();
|
||||||
workspace_output_add_priority(ws, output);
|
|
||||||
|
|
||||||
ws->gaps_outer = config->gaps_outer;
|
ws->gaps_outer = config->gaps_outer;
|
||||||
ws->gaps_inner = config->gaps_inner;
|
ws->gaps_inner = config->gaps_inner;
|
||||||
@ -110,8 +110,16 @@ struct sway_workspace *workspace_create(struct sway_output *output,
|
|||||||
// Since default outer gaps can be smaller than the negation of
|
// Since default outer gaps can be smaller than the negation of
|
||||||
// workspace specific inner gaps, check outer gaps again
|
// workspace specific inner gaps, check outer gaps again
|
||||||
prevent_invalid_outer_gaps(ws);
|
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_add_workspace(output, ws);
|
||||||
output_sort_workspaces(output);
|
output_sort_workspaces(output);
|
||||||
@ -134,8 +142,7 @@ void workspace_destroy(struct sway_workspace *workspace) {
|
|||||||
|
|
||||||
free(workspace->name);
|
free(workspace->name);
|
||||||
free(workspace->representation);
|
free(workspace->representation);
|
||||||
list_foreach(workspace->output_priority, free);
|
free_flat_list(workspace->output_priority);
|
||||||
list_free(workspace->output_priority);
|
|
||||||
list_free(workspace->floating);
|
list_free(workspace->floating);
|
||||||
list_free(workspace->tiling);
|
list_free(workspace->tiling);
|
||||||
list_free(workspace->current.floating);
|
list_free(workspace->current.floating);
|
||||||
@ -178,7 +185,18 @@ static bool workspace_valid_on_output(const char *output_name,
|
|||||||
struct sway_output *output = output_by_name(output_name);
|
struct sway_output *output = output_by_name(output_name);
|
||||||
output_get_identifier(identifier, sizeof(identifier), output);
|
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,
|
static void workspace_name_from_binding(const struct sway_binding * binding,
|
||||||
@ -281,13 +299,22 @@ char *workspace_next_name(const char *output_name) {
|
|||||||
for (int i = 0; i < config->workspace_configs->length; ++i) {
|
for (int i = 0; i < config->workspace_configs->length; ++i) {
|
||||||
// Unlike with bindings, this does not guarantee order
|
// Unlike with bindings, this does not guarantee order
|
||||||
const struct workspace_config *wsc = config->workspace_configs->items[i];
|
const struct workspace_config *wsc = config->workspace_configs->items[i];
|
||||||
if (wsc->output && strcmp(wsc->output, output_name) == 0
|
if (workspace_by_name(wsc->workspace)) {
|
||||||
&& workspace_by_name(wsc->workspace) == NULL) {
|
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);
|
free(target);
|
||||||
target = strdup(wsc->workspace);
|
target = strdup(wsc->workspace);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (found) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (target != NULL) {
|
if (target != NULL) {
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user