re-implement assignments of workspace to specific outputs
This commit is contained in:
parent
0e2d58347c
commit
3f45d3c447
|
@ -117,6 +117,17 @@ struct deco_render_params {
|
||||||
xcb_font_t font;
|
xcb_font_t font;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores which workspace (by name) goes to which output.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct Workspace_Assignment {
|
||||||
|
char *name;
|
||||||
|
char *output;
|
||||||
|
|
||||||
|
TAILQ_ENTRY(Workspace_Assignment) ws_assignments;
|
||||||
|
};
|
||||||
|
|
||||||
struct Ignore_Event {
|
struct Ignore_Event {
|
||||||
int sequence;
|
int sequence;
|
||||||
int response_type;
|
int response_type;
|
||||||
|
|
|
@ -27,6 +27,7 @@ extern int xkb_current_group;
|
||||||
extern TAILQ_HEAD(bindings_head, Binding) *bindings;
|
extern TAILQ_HEAD(bindings_head, Binding) *bindings;
|
||||||
extern TAILQ_HEAD(autostarts_head, Autostart) autostarts;
|
extern TAILQ_HEAD(autostarts_head, Autostart) autostarts;
|
||||||
extern TAILQ_HEAD(assignments_head, Match) assignments;
|
extern TAILQ_HEAD(assignments_head, Match) assignments;
|
||||||
|
extern TAILQ_HEAD(ws_assignments_head, Workspace_Assignment) ws_assignments;
|
||||||
extern SLIST_HEAD(stack_wins_head, Stack_Window) stack_wins;
|
extern SLIST_HEAD(stack_wins_head, Stack_Window) stack_wins;
|
||||||
extern uint8_t root_depth;
|
extern uint8_t root_depth;
|
||||||
extern bool xcursor_supported, xkb_supported;
|
extern bool xcursor_supported, xkb_supported;
|
||||||
|
|
|
@ -517,14 +517,18 @@ workspace:
|
||||||
if (ws_num < 1) {
|
if (ws_num < 1) {
|
||||||
DLOG("Invalid workspace assignment, workspace number %d out of range\n", ws_num);
|
DLOG("Invalid workspace assignment, workspace number %d out of range\n", ws_num);
|
||||||
} else {
|
} else {
|
||||||
#if 0
|
char *ws_name = NULL;
|
||||||
Workspace *ws = workspace_get(ws_num - 1);
|
if ($8 == NULL) {
|
||||||
ws->preferred_output = $<string>7;
|
asprintf(&ws_name, "%d", ws_num);
|
||||||
if ($<string>8 != NULL) {
|
} else {
|
||||||
workspace_set_name(ws, $<string>8);
|
ws_name = $8;
|
||||||
free($<string>8);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
DLOG("Should assign workspace %s to output %s\n", ws_name, $7);
|
||||||
|
struct Workspace_Assignment *assignment = scalloc(sizeof(struct Workspace_Assignment));
|
||||||
|
assignment->name = ws_name;
|
||||||
|
assignment->output = $7;
|
||||||
|
TAILQ_INSERT_TAIL(&ws_assignments, assignment, ws_assignments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| TOKWORKSPACE WHITESPACE NUMBER WHITESPACE workspace_name
|
| TOKWORKSPACE WHITESPACE NUMBER WHITESPACE workspace_name
|
||||||
|
|
|
@ -33,6 +33,10 @@ struct autostarts_head autostarts = TAILQ_HEAD_INITIALIZER(autostarts);
|
||||||
/* The list of assignments */
|
/* The list of assignments */
|
||||||
struct assignments_head assignments = TAILQ_HEAD_INITIALIZER(assignments);
|
struct assignments_head assignments = TAILQ_HEAD_INITIALIZER(assignments);
|
||||||
|
|
||||||
|
/* The list of workspace assignments (which workspace should end up on which
|
||||||
|
* output) */
|
||||||
|
struct ws_assignments_head ws_assignments = TAILQ_HEAD_INITIALIZER(ws_assignments);
|
||||||
|
|
||||||
/* We hope that those are supported and set them to true */
|
/* We hope that those are supported and set them to true */
|
||||||
bool xcursor_supported = true;
|
bool xcursor_supported = true;
|
||||||
bool xkb_supported = true;
|
bool xkb_supported = true;
|
||||||
|
|
90
src/randr.c
90
src/randr.c
|
@ -223,9 +223,6 @@ void disable_randr(xcb_connection_t *conn) {
|
||||||
* Initializes a CT_OUTPUT Con (searches existing ones from inplace restart
|
* Initializes a CT_OUTPUT Con (searches existing ones from inplace restart
|
||||||
* before) to use for the given Output.
|
* before) to use for the given Output.
|
||||||
*
|
*
|
||||||
* XXX: for assignments, we probably need to move workspace creation from here
|
|
||||||
* to after the loop in randr_query_outputs().
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void output_init_con(Output *output) {
|
void output_init_con(Output *output) {
|
||||||
Con *con = NULL, *current;
|
Con *con = NULL, *current;
|
||||||
|
@ -316,7 +313,81 @@ void output_init_con(Output *output) {
|
||||||
FREE(name);
|
FREE(name);
|
||||||
DLOG("attaching\n");
|
DLOG("attaching\n");
|
||||||
con_attach(bottomdock, con, false);
|
con_attach(bottomdock, con, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes at least one workspace for this output, trying the following
|
||||||
|
* steps until there is at least one workspace:
|
||||||
|
*
|
||||||
|
* • Move existing workspaces, which are assigned to be on the given output, to
|
||||||
|
* the output.
|
||||||
|
* • Create the first assigned workspace for this output.
|
||||||
|
* • Create the first unused workspace.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void init_ws_for_output(Output *output, Con *content) {
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
/* 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->name) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* check if this workspace actually exists */
|
||||||
|
Con *workspace = NULL, *out;
|
||||||
|
TAILQ_FOREACH(out, &(croot->nodes_head), nodes)
|
||||||
|
GREP_FIRST(workspace, output_get_content(out),
|
||||||
|
!strcasecmp(child->name, assignment->name));
|
||||||
|
if (workspace == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* check that this workspace is not already attached (that means the
|
||||||
|
* user configured this assignment twice) */
|
||||||
|
Con *workspace_out = con_get_output(workspace);
|
||||||
|
if (workspace_out == output->con) {
|
||||||
|
LOG("Workspace \"%s\" assigned to output \"%s\", but it is already "
|
||||||
|
"there. Do you have two assignment directives for the same "
|
||||||
|
"workspace in your configuration file?\n",
|
||||||
|
workspace->name, output->name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if so, move it over */
|
||||||
|
LOG("Moving workspace \"%s\" from output \"%s\" to \"%s\" due to assignment\n",
|
||||||
|
workspace->name, workspace_out->name, output->name);
|
||||||
|
DLOG("Detaching workspace = %p / %s\n", workspace, workspace->name);
|
||||||
|
con_detach(workspace);
|
||||||
|
DLOG("Re-attaching current = %p / %s\n", workspace, workspace->name);
|
||||||
|
con_attach(workspace, content, false);
|
||||||
|
DLOG("Done, next\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if a workspace exists, we are done now */
|
||||||
|
if (!TAILQ_EMPTY(&(content->nodes_head))) {
|
||||||
|
/* ensure that one of the workspaces is actually visible (in fullscreen
|
||||||
|
* mode), if they were invisible before, this might not be the case. */
|
||||||
|
Con *visible = NULL;
|
||||||
|
GREP_FIRST(visible, content, child->fullscreen_mode == CF_OUTPUT);
|
||||||
|
if (!visible) {
|
||||||
|
visible = TAILQ_FIRST(&(content->nodes_head));
|
||||||
|
workspace_show(visible->name);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* otherwise, we create the first assigned ws for this output */
|
||||||
|
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
||||||
|
if (strcmp(assignment->output, output->name) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
LOG("Initializing first assigned workspace \"%s\" for output \"%s\"\n",
|
||||||
|
assignment->name, assignment->output);
|
||||||
|
workspace_show(assignment->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if there is still no workspace, we create the first free workspace */
|
||||||
DLOG("Now adding a workspace\n");
|
DLOG("Now adding a workspace\n");
|
||||||
|
|
||||||
/* add a workspace to this output */
|
/* add a workspace to this output */
|
||||||
|
@ -731,15 +802,16 @@ void randr_query_outputs() {
|
||||||
|
|
||||||
ewmh_update_workarea();
|
ewmh_update_workarea();
|
||||||
|
|
||||||
#if 0
|
/* Just go through each active output and assign one workspace */
|
||||||
/* Just go through each active output and associate one workspace */
|
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH(output, &outputs, outputs) {
|
||||||
if (!output->active || output->current_workspace != NULL)
|
if (!output->active)
|
||||||
continue;
|
continue;
|
||||||
ws = get_first_workspace_for_output(output);
|
Con *content = output_get_content(output->con);
|
||||||
initialize_output(conn, output, ws);
|
if (!TAILQ_EMPTY(&(content->nodes_head)))
|
||||||
|
continue;
|
||||||
|
DLOG("Should add ws for output %s\n", output->name);
|
||||||
|
init_ws_for_output(output, content);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Focus the primary screen, if possible */
|
/* Focus the primary screen, if possible */
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
TAILQ_FOREACH(output, &outputs, outputs) {
|
||||||
|
|
|
@ -18,24 +18,25 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Con *workspace_get(const char *num, bool *created) {
|
Con *workspace_get(const char *num, bool *created) {
|
||||||
Con *output, *workspace = NULL, *child;
|
Con *output, *workspace = NULL;
|
||||||
|
|
||||||
/* TODO: could that look like this in the future?
|
|
||||||
GET_MATCHING_NODE(workspace, croot, strcasecmp(current->name, num) != 0);
|
|
||||||
*/
|
|
||||||
TAILQ_FOREACH(output, &(croot->nodes_head), nodes)
|
TAILQ_FOREACH(output, &(croot->nodes_head), nodes)
|
||||||
TAILQ_FOREACH(child, &(output_get_content(output)->nodes_head), nodes) {
|
GREP_FIRST(workspace, output_get_content(output), !strcasecmp(child->name, num));
|
||||||
if (strcasecmp(child->name, num) != 0)
|
|
||||||
|
if (workspace == NULL) {
|
||||||
|
LOG("Creating new workspace \"%s\"\n", num);
|
||||||
|
/* unless an assignment is found, we will create this workspace on the current output */
|
||||||
|
output = con_get_output(focused);
|
||||||
|
/* look for assignments */
|
||||||
|
struct Workspace_Assignment *assignment;
|
||||||
|
TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
|
||||||
|
if (strcmp(assignment->name, num) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
workspace = child;
|
LOG("Found workspace assignment to output \"%s\"\n", assignment->output);
|
||||||
|
GREP_FIRST(output, croot, !strcmp(child->name, assignment->output));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG("getting ws %s\n", num);
|
|
||||||
if (workspace == NULL) {
|
|
||||||
LOG("need to create this one\n");
|
|
||||||
output = con_get_output(focused);
|
|
||||||
Con *content = output_get_content(output);
|
Con *content = output_get_content(output);
|
||||||
LOG("got output %p with content %p\n", output, content);
|
LOG("got output %p with content %p\n", output, content);
|
||||||
/* We need to attach this container after setting its type. con_attach
|
/* We need to attach this container after setting its type. con_attach
|
||||||
|
@ -225,7 +226,6 @@ void workspace_show(const char *num) {
|
||||||
old = current;
|
old = current;
|
||||||
current->fullscreen_mode = CF_NONE;
|
current->fullscreen_mode = CF_NONE;
|
||||||
}
|
}
|
||||||
assert(old != NULL);
|
|
||||||
|
|
||||||
/* enable fullscreen for the target workspace. If it happens to be the
|
/* enable fullscreen for the target workspace. If it happens to be the
|
||||||
* same one we are currently on anyways, we can stop here. */
|
* same one we are currently on anyways, we can stop here. */
|
||||||
|
|
Loading…
Reference in New Issue