Merge pull request #3108 from RedSoxFan/workspace-output-improved

Allow multiple outputs for workspace output
This commit is contained in:
Drew DeVault 2018-11-11 11:30:27 -05:00 committed by GitHub
commit 101515eb0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 66 additions and 25 deletions

View file

@ -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;
};

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -33,16 +33,17 @@ 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 (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->output);
output = output_by_identifier(wsc->outputs->items[i]);
}
if (output) {
return output;
}
}
}
// Otherwise put it on the focused output
struct sway_seat *seat = input_manager_current_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->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,8 +110,16 @@ 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);
@ -178,7 +185,18 @@ static bool workspace_valid_on_output(const char *output_name,
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,13 +299,22 @@ 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) {
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;
}
}
if (target != NULL) {
return target;
}