* • Create the first unused workspace.
*
*/
-void init_ws_for_output(Output *output, Con *content) {
+void init_ws_for_output(Output *output) {
+ Con *content = output_get_content(output->con);
+ Con *previous_focus = con_get_workspace(focused);
+
/* 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;
-
- /* 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));
+ }
+ Con *workspace = get_existing_workspace_by_name(assignment->name);
if (workspace == NULL)
continue;
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_primary_name(output));
-
- /* if the workspace is currently visible on that output, we need to
- * switch to a different workspace - otherwise the output would end up
- * with no active workspace */
- bool visible = workspace_is_visible(workspace);
- Con *previous = NULL;
- if (visible && (previous = TAILQ_NEXT(workspace, focused))) {
- LOG("Switching to previously used workspace \"%s\" on output \"%s\"\n",
- previous->name, workspace_out->name);
- workspace_show(previous);
- }
-
- /* Render the output on which the workspace was to get correct Rects.
- * Then, we need to work with the "content" container, since we cannot
- * be sure that the workspace itself was rendered at all (in case it’s
- * invisible, it won’t be rendered). */
- render_con(workspace_out, false);
- Con *ws_out_content = output_get_content(workspace_out);
-
- Con *floating_con;
- TAILQ_FOREACH(floating_con, &(workspace->floating_head), floating_windows)
- /* NB: We use output->con here because content is not yet rendered,
- * so it has a rect of {0, 0, 0, 0}. */
- floating_fix_coordinates(floating_con, &(ws_out_content->rect), &(output->con->rect));
-
- con_detach(workspace);
- con_attach(workspace, content, false);
-
- /* In case the workspace we just moved was visible but there was no
- * other workspace to switch to, we need to initialize the source
- * output as well */
- if (visible && previous == NULL) {
- LOG("There is no workspace left on \"%s\", re-initializing\n",
- workspace_out->name);
- init_ws_for_output(get_output_by_name(workspace_out->name, true),
- output_get_content(workspace_out));
- DLOG("Done re-initializing, continuing with \"%s\"\n", output_primary_name(output));
- }
+ DLOG("Moving workspace \"%s\" from output \"%s\" to \"%s\" due to assignment\n",
+ workspace->name, workspace_out->name, output_primary_name(output));
+ /* Need to copy output's rect since content is not yet rendered. We
+ * can't call render_con here because render_output only proceeds if a
+ * workspace exists. */
+ content->rect = output->con->rect;
+ workspace_move_to_output(workspace, output);
}
+ /* Temporarily set the focused container, might not be initialized yet. */
+ focused = content;
+
/* 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
GREP_FIRST(visible, content, child->fullscreen_mode == CF_OUTPUT);
if (!visible) {
visible = TAILQ_FIRST(&(content->nodes_head));
- focused = content;
workspace_show(visible);
}
- return;
+ goto restore_focus;
}
/* 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);
- focused = content;
workspace_show_by_name(assignment->name);
- return;
+ goto restore_focus;
}
/* if there is still no workspace, we create the first free workspace */
DLOG("Now adding a workspace\n");
- Con *ws = create_workspace_on_output(output, content);
+ workspace_show(create_workspace_on_output(output, content));
- /* TODO: Set focus in main.c */
- con_activate(ws);
+restore_focus:
+ if (previous_focus) {
+ workspace_show(previous_focus);
+ }
}
/*
}
/* If default_orientation is NO_ORIENTATION, we change the orientation of
- * the workspaces and their childs depending on output resolution. This is
+ * the workspaces and their children depending on output resolution. This is
* only done for workspaces with maximum one child. */
if (config.default_orientation == NO_ORIENTATION) {
TAILQ_FOREACH(workspace, &(content->nodes_head), nodes) {
/* If there's no randr output, enable the output covering the root window. */
if (any_randr_output_active()) {
DLOG("Active RandR output found. Disabling root output.\n");
- if (root_output->active)
+ if (root_output && root_output->active) {
root_output->to_be_disabled = true;
+ }
} else {
DLOG("No active RandR output found. Enabling root output.\n");
root_output->active = true;
if (!TAILQ_EMPTY(&(content->nodes_head)))
continue;
DLOG("Should add ws for output %s\n", output_primary_name(output));
- init_ws_for_output(output, content);
+ init_ws_for_output(output);
}
/* Focus the primary screen, if possible */
continue;
DLOG("Focusing primary output %s\n", output_primary_name(output));
- con_activate(con_descend_focused(output->con));
+ Con *content = output_get_content(output->con);
+ Con *ws = TAILQ_FIRST(&(content)->focus_head);
+ workspace_show(ws);
}
/* render_layout flushes */
if (output->con != NULL) {
/* We need to move the workspaces from the disappearing output to the first output */
- /* 1: Get the con to focus next, if the disappearing ws is focused */
- Con *next = NULL;
- if (TAILQ_FIRST(&(croot->focus_head)) == output->con) {
- DLOG("This output (%p) was focused! Getting next\n", output->con);
- next = focused;
- DLOG("next = %p\n", next);
- }
+ /* 1: Get the con to focus next */
+ Con *next = focused;
/* 2: iterate through workspaces and re-assign them, fixing the coordinates
* of floating containers as we go */
if (current != next && TAILQ_EMPTY(&(current->focus_head))) {
/* the workspace is empty and not focused, get rid of it */
DLOG("Getting rid of current = %p / %s (empty, unfocused)\n", current, current->name);
- tree_close_internal(current, DONT_KILL_WINDOW, false, false);
+ tree_close_internal(current, DONT_KILL_WINDOW, false);
continue;
}
DLOG("Detaching current = %p / %s\n", current, current->name);
TAILQ_FOREACH(floating_con, &(current->floating_head), floating_windows) {
floating_fix_coordinates(floating_con, &(output->con->rect), &(first->con->rect));
}
- DLOG("Done, next\n");
}
- DLOG("re-attached all workspaces\n");
+ /* Restore focus after con_detach / con_attach. next can be NULL, see #3523. */
if (next) {
DLOG("now focusing next = %p\n", next);
- con_activate(next);
+ con_focus(next);
workspace_show(con_get_workspace(next));
}
Con *con = output->con;
/* clear the pointer before calling tree_close_internal in which the memory is freed */
output->con = NULL;
- tree_close_internal(con, DONT_KILL_WINDOW, true, false);
+ tree_close_internal(con, DONT_KILL_WINDOW, true);
DLOG("Done. Should be fine now\n");
}
static void fallback_to_root_output(void) {
root_output->active = true;
output_init_con(root_output);
- init_ws_for_output(root_output, output_get_content(root_output->con));
+ init_ws_for_output(root_output);
}
/*