/** Switches to the given workspace */
void workspace_show(xcb_connection_t *conn, int workspace);
+/**
+ * Assigns the given workspace to the given screen by correctly updating its
+ * state and reconfiguring all the clients on this workspace.
+ *
+ * This is called when initializing a screen and when re-assigning it to a
+ * different screen which just got available (if you configured it to be on
+ * screen 1 and you just plugged in screen 1).
+ *
+ */
+void workspace_assign_to(Workspace *ws, i3Screen *screen);
+
/**
* Initializes the given workspace if it is not already initialized. The given
* screen is to be understood as a fallback, if the workspace itself either
* the screen is not attached at the moment.
*
*/
-void workspace_initialize(Workspace *ws, i3Screen *screen);
+void workspace_initialize(Workspace *ws, i3Screen *screen, bool recheck);
/**
* Gets the first unused workspace for the given screen, taking into account
LOG("moving floating\n");
- workspace_initialize(t_ws, c_ws->screen);
+ workspace_initialize(t_ws, c_ws->screen, false);
/* Check if there is already a fullscreen client on the destination workspace and
* stop moving if so. */
if (to_focus == NULL)
to_focus = CIRCLEQ_PREV_OR_NULL(&(container->clients), current_client, clients);
- workspace_initialize(t_ws, container->workspace->screen);
+ workspace_initialize(t_ws, container->workspace->screen, false);
/* Check if there is already a fullscreen client on the destination workspace and
* stop moving if so. */
if (current_client->fullscreen && (t_ws->fullscreen_client != NULL)) {
DLOG("Changing container/workspace and unmapping the client\n");
Workspace *t_ws = workspace_get(assign->workspace-1);
- workspace_initialize(t_ws, c_ws->screen);
+ workspace_initialize(t_ws, c_ws->screen, false);
new->container = t_ws->table[t_ws->current_col][t_ws->current_row];
new->workspace = t_ws;
c_ws->current_col = current_col;
/* Check if the workspace has not been used yet */
- workspace_initialize(t_ws, c_ws->screen);
+ workspace_initialize(t_ws, c_ws->screen, false);
if (c_ws->screen != t_ws->screen) {
/* We need to switch to the other screen first */
return NULL;
}
+/*
+ * Assigns the given workspace to the given screen by correctly updating its
+ * state and reconfiguring all the clients on this workspace.
+ *
+ * This is called when initializing a screen and when re-assigning it to a
+ * different screen which just got available (if you configured it to be on
+ * screen 1 and you just plugged in screen 1).
+ *
+ */
+void workspace_assign_to(Workspace *ws, i3Screen *screen) {
+ Client *client;
+ bool empty = true;
+
+ ws->screen = screen;
+
+ /* Copy the dimensions from the virtual screen */
+ memcpy(&(ws->rect), &(ws->screen->rect), sizeof(Rect));
+
+ /* Force reconfiguration for each client on that workspace */
+ FOR_TABLE(ws)
+ CIRCLEQ_FOREACH(client, &(ws->table[cols][rows]->clients), clients) {
+ client->force_reconfigure = true;
+ empty = false;
+ }
+
+ if (empty)
+ return;
+
+ /* Render the workspace to reconfigure the clients. However, they will be visible now, so… */
+ render_workspace(global_conn, screen, ws);
+
+ /* …unless we want to see them at the moment, we should hide that workspace */
+ if (workspace_is_visible(ws))
+ return;
+
+ workspace_unmap_clients(global_conn, ws);
+
+ if (c_ws == ws) {
+ DLOG("Need to adjust c_ws...\n");
+ c_ws = screen->current_workspace;
+ }
+}
+
/*
* Initializes the given workspace if it is not already initialized. The given
* screen is to be understood as a fallback, if the workspace itself either
* the screen is not attached at the moment.
*
*/
-void workspace_initialize(Workspace *ws, i3Screen *screen) {
- if (ws->screen != NULL) {
+void workspace_initialize(Workspace *ws, i3Screen *screen, bool recheck) {
+ i3Screen *old_screen;
+
+ if (ws->screen != NULL && !recheck) {
DLOG("Workspace already initialized\n");
return;
}
+ old_screen = ws->screen;
+
/* If this workspace has no preferred screen or if the screen it wants
* to be on is not available at the moment, we initialize it with
* the screen which was given */
(ws->screen = get_screen_from_preference(virtual_screens, ws->preferred_screen)) == NULL)
ws->screen = screen;
- /* Copy the dimensions from the virtual screen */
- memcpy(&(ws->rect), &(ws->screen->rect), sizeof(Rect));
+ DLOG("old_screen = %p, ws->screen = %p\n", old_screen, ws->screen);
+ /* If the assignment did not change, we do not need to update anything */
+ if (old_screen != NULL && ws->screen == old_screen)
+ return;
+
+ workspace_assign_to(ws, ws->screen);
}
/*
result = workspace_get(last_ws + 1);
}
- workspace_initialize(result, screen);
+ workspace_initialize(result, screen, false);
return result;
}
for (int screen = 0; screen < screens; screen++) {
i3Screen *s = get_screen_at(screen_info[screen].x_org, screen_info[screen].y_org, screenlist);
if (s != NULL) {
+ DLOG("Re-used old Xinerama screen %p\n", s);
/* This screen already exists. We use the littlest screen so that the user
can always see the complete workspace */
s->rect.width = min(s->rect.width, screen_info[screen].width);
s->rect.height = min(s->rect.height, screen_info[screen].height);
} else {
s = calloc(sizeof(i3Screen), 1);
+ DLOG("Created new Xinerama screen %p\n", s);
s->rect.x = screen_info[screen].x_org;
s->rect.y = screen_info[screen].y_org;
s->rect.width = screen_info[screen].width;
Rect bar_rect = {screen->rect.x,
screen->rect.y + screen->rect.height - (font->height + 6),
- screen->rect.x + screen->rect.width,
+ screen->rect.width,
font->height + 6};
DLOG("configuring bar to be at %d x %d with %d x %d\n",
if (ws->reassigned)
continue;
- Client *client;
-
DLOG("Closing bar window (%p)\n", ws->screen->bar);
xcb_destroy_window(conn, ws->screen->bar);
DLOG("Workspace %d's screen out of bounds, assigning to first screen\n", ws->num + 1);
- ws->screen = first;
- memcpy(&(ws->rect), &(first->rect), sizeof(Rect));
-
- /* Force reconfiguration for each client on that workspace */
- FOR_TABLE(ws)
- CIRCLEQ_FOREACH(client, &(ws->table[cols][rows]->clients), clients)
- client->force_reconfigure = true;
-
- /* Render the workspace to reconfigure the clients. However, they will be visible now, so… */
- render_workspace(conn, first, ws);
-
- /* …unless we want to see them at the moment, we should hide that workspace */
- if (workspace_is_visible(ws))
- continue;
-
- workspace_unmap_clients(conn, ws);
-
- if (c_ws == ws) {
- DLOG("Need to adjust c_ws...\n");
- c_ws = first->current_workspace;
- }
+ workspace_assign_to(ws, first);
}
+
xcb_flush(conn);
/* Free the old list */
virtual_screens = new_screens;
+ /* Check for workspaces which need to be assigned to specific screens
+ * which may now be available */
+ TAILQ_FOREACH(ws, workspaces, workspaces) {
+ if (ws->preferred_screen == NULL)
+ continue;
+
+ workspace_initialize(ws, ws->screen, true);
+ }
+
DLOG("Current workspace is now: %d\n", first->current_workspace);
render_layout(conn);