Merge pull request #3254 from orestisf1993/issue-555
Multiple assignments of workspaces to outputs (#555)
This commit is contained in:
@ -2019,6 +2019,9 @@ void cmd_rename_workspace(I3_CMD, const char *old_name, const char *new_name) {
|
||||
LOG("Could not get output named \"%s\"\n", assignment->output);
|
||||
continue;
|
||||
}
|
||||
if (!output_triggers_assignment(target_output, assignment)) {
|
||||
continue;
|
||||
}
|
||||
workspace_move_to_output(workspace, target_output);
|
||||
|
||||
break;
|
||||
|
@ -322,8 +322,8 @@ CFGFUN(show_marks, const char *value) {
|
||||
config.show_marks = eval_boolstr(value);
|
||||
}
|
||||
|
||||
CFGFUN(workspace, const char *workspace, const char *output) {
|
||||
DLOG("Assigning workspace \"%s\" to output \"%s\"\n", workspace, output);
|
||||
CFGFUN(workspace, const char *workspace, const char *outputs) {
|
||||
DLOG("Assigning workspace \"%s\" to outputs \"%s\"\n", workspace, outputs);
|
||||
/* Check for earlier assignments of the same workspace so that we
|
||||
* don’t have assignments of a single workspace to different
|
||||
* outputs */
|
||||
@ -336,10 +336,16 @@ CFGFUN(workspace, const char *workspace, const char *output) {
|
||||
}
|
||||
}
|
||||
|
||||
assignment = scalloc(1, sizeof(struct Workspace_Assignment));
|
||||
assignment->name = sstrdup(workspace);
|
||||
assignment->output = sstrdup(output);
|
||||
TAILQ_INSERT_TAIL(&ws_assignments, assignment, ws_assignments);
|
||||
char *buf = sstrdup(outputs);
|
||||
char *output = strtok(buf, " ");
|
||||
while (output != NULL) {
|
||||
assignment = scalloc(1, sizeof(struct Workspace_Assignment));
|
||||
assignment->name = sstrdup(workspace);
|
||||
assignment->output = sstrdup(output);
|
||||
TAILQ_INSERT_TAIL(&ws_assignments, assignment, ws_assignments);
|
||||
output = strtok(NULL, " ");
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
|
||||
CFGFUN(ipc_socket, const char *path) {
|
||||
|
@ -424,9 +424,9 @@ void init_ws_for_output(Output *output, Con *content) {
|
||||
/* go through all assignments and move the existing workspaces to this output */
|
||||
struct Workspace_Assignment *assignment;
|
||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
||||
if (strcmp(assignment->output, output_primary_name(output)) != 0)
|
||||
if (!output_triggers_assignment(output, assignment)) {
|
||||
continue;
|
||||
|
||||
}
|
||||
Con *workspace = get_existing_workspace_by_name(assignment->name);
|
||||
if (workspace == NULL)
|
||||
continue;
|
||||
@ -501,8 +501,9 @@ void init_ws_for_output(Output *output, Con *content) {
|
||||
|
||||
/* otherwise, we create the first assigned ws for this output */
|
||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
||||
if (strcmp(assignment->output, output_primary_name(output)) != 0)
|
||||
if (!output_triggers_assignment(output, assignment)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG("Initializing first assigned workspace \"%s\" for output \"%s\"\n",
|
||||
assignment->name, assignment->output);
|
||||
|
@ -67,6 +67,52 @@ static void _workspace_apply_default_orientation(Con *ws) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the first output that is assigned to a workspace specified by the
|
||||
* given name or number or NULL if no such output exists. If there is a
|
||||
* workspace with a matching name and another workspace with a matching number,
|
||||
* the output assigned to the first one is returned.
|
||||
* The order of the 'ws_assignments' queue is respected: if multiple assignments
|
||||
* match the specified workspace, the first one is returned.
|
||||
* If 'name' is NULL it will be ignored.
|
||||
* If 'parsed_num' is -1 it will be ignored.
|
||||
*
|
||||
*/
|
||||
static Con *get_assigned_output(const char *name, long parsed_num) {
|
||||
Con *output = NULL;
|
||||
struct Workspace_Assignment *assignment;
|
||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
||||
if (name && strcmp(assignment->name, name) == 0) {
|
||||
DLOG("Found workspace name assignment to output \"%s\"\n", assignment->output);
|
||||
Output *assigned_by_name = get_output_by_name(assignment->output, true);
|
||||
if (assigned_by_name) {
|
||||
/* When the name matches exactly, skip numbered assignments. */
|
||||
return assigned_by_name->con;
|
||||
}
|
||||
} else if (!output && /* Only keep the first numbered assignment. */
|
||||
parsed_num != -1 &&
|
||||
name_is_digits(assignment->name) &&
|
||||
ws_name_to_number(assignment->name) == parsed_num) {
|
||||
DLOG("Found workspace number assignment to output \"%s\"\n", assignment->output);
|
||||
Output *assigned_by_num = get_output_by_name(assignment->output, true);
|
||||
if (assigned_by_num) {
|
||||
output = assigned_by_num->con;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the first output assigned to a workspace with the given
|
||||
* workspace assignment is the same as the given output.
|
||||
*/
|
||||
bool output_triggers_assignment(Output *output, struct Workspace_Assignment *assignment) {
|
||||
Con *assigned = get_assigned_output(assignment->name, -1);
|
||||
return assigned && assigned == output->con;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a pointer to the workspace with the given number (starting at 0),
|
||||
* creating the workspace if necessary (by allocating the necessary amount of
|
||||
@ -78,25 +124,16 @@ Con *workspace_get(const char *num, bool *created) {
|
||||
|
||||
if (workspace == NULL) {
|
||||
LOG("Creating new workspace \"%s\"\n", num);
|
||||
/* unless an assignment is found, we will create this workspace on the current output */
|
||||
Con *output = con_get_output(focused);
|
||||
/* look for assignments */
|
||||
struct Workspace_Assignment *assignment;
|
||||
|
||||
/* We set workspace->num to the number if this workspace’s name begins
|
||||
* with a positive number. Otherwise it’s a named ws and num will be
|
||||
* -1. */
|
||||
long parsed_num = ws_name_to_number(num);
|
||||
|
||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
||||
if (strcmp(assignment->name, num) == 0) {
|
||||
DLOG("Found workspace name assignment to output \"%s\"\n", assignment->output);
|
||||
GREP_FIRST(output, croot, !strcmp(child->name, assignment->output));
|
||||
break;
|
||||
} else if (parsed_num != -1 && name_is_digits(assignment->name) && ws_name_to_number(assignment->name) == parsed_num) {
|
||||
DLOG("Found workspace number assignment to output \"%s\"\n", assignment->output);
|
||||
GREP_FIRST(output, croot, !strcmp(child->name, assignment->output));
|
||||
}
|
||||
Con *output = get_assigned_output(num, parsed_num);
|
||||
/* if an assignment is not found, we create this workspace on the current output */
|
||||
if (!output) {
|
||||
output = con_get_output(focused);
|
||||
}
|
||||
|
||||
Con *content = output_get_content(output);
|
||||
@ -208,19 +245,10 @@ Con *create_workspace_on_output(Output *output, Con *content) {
|
||||
/* Ensure that this workspace is not assigned to a different output —
|
||||
* otherwise we would create it, then move it over to its output, then
|
||||
* find a new workspace, etc… */
|
||||
bool assigned = false;
|
||||
struct Workspace_Assignment *assignment;
|
||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
||||
if (strcmp(assignment->name, target_name) != 0 ||
|
||||
strcmp(assignment->output, output_primary_name(output)) == 0)
|
||||
continue;
|
||||
|
||||
assigned = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (assigned)
|
||||
Con *assigned = get_assigned_output(target_name, -1);
|
||||
if (assigned && assigned != output->con) {
|
||||
continue;
|
||||
}
|
||||
|
||||
exists = (get_existing_workspace_by_name(target_name) != NULL);
|
||||
if (!exists) {
|
||||
@ -239,7 +267,9 @@ Con *create_workspace_on_output(Output *output, Con *content) {
|
||||
DLOG("Getting next unused workspace by number\n");
|
||||
int c = 0;
|
||||
while (exists) {
|
||||
exists = (get_existing_workspace_by_num(++c) != NULL);
|
||||
c++;
|
||||
Con *assigned = get_assigned_output(NULL, c);
|
||||
exists = (get_existing_workspace_by_num(c) || (assigned && assigned != output->con));
|
||||
DLOG("result for ws %d: exists = %d\n", c, exists);
|
||||
}
|
||||
ws->num = c;
|
||||
@ -946,8 +976,9 @@ bool workspace_move_to_output(Con *ws, Output *output) {
|
||||
bool used_assignment = false;
|
||||
struct Workspace_Assignment *assignment;
|
||||
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
||||
if (assignment->output == NULL || strcmp(assignment->output, output_primary_name(current_output)) != 0)
|
||||
if (!output_triggers_assignment(current_output, assignment)) {
|
||||
continue;
|
||||
}
|
||||
/* check if this workspace is already attached to the tree */
|
||||
if (get_existing_workspace_by_name(assignment->name) != NULL) {
|
||||
continue;
|
||||
|
Reference in New Issue
Block a user