Refactor workspaces to be stored in a TAILQ instead of an array

This fixes many problems we were having with a dynamically growing
array because of the realloc (pointers inside the area which was
allocated were no longer valid as soon as the realloc moved the
memory to another address).

Again, this is a rather big change, so expect problems and enable
core-dumps.
This commit is contained in:
Michael Stapelberg
2009-09-29 19:45:41 +02:00
parent 5a77081c55
commit 2b70e05ee9
15 changed files with 142 additions and 172 deletions

View File

@ -133,7 +133,7 @@ static void initialize_screen(xcb_connection_t *conn, i3Screen *screen, Workspac
i3Font *font = load_font(conn, config.font);
workspace->screen = screen;
screen->current_workspace = workspace->num;
screen->current_workspace = workspace;
/* Create a bar for each screen */
Rect bar_rect = {screen->rect.x,
@ -298,12 +298,13 @@ void xinerama_requery_screens(xcb_connection_t *conn) {
int screen_count = 0;
/* Mark each workspace which currently is assigned to a screen, so we
* can garbage-collect afterwards */
for (int c = 0; c < num_workspaces; c++)
workspaces[c].reassigned = (workspaces[c].screen == NULL);
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces)
ws->reassigned = (ws->screen == NULL);
TAILQ_FOREACH(screen, new_screens, screens) {
screen->num = screen_count;
screen->current_workspace = -1;
screen->current_workspace = NULL;
TAILQ_FOREACH(old_screen, virtual_screens, screens) {
if (old_screen->num != screen_count)
@ -334,8 +335,8 @@ void xinerama_requery_screens(xcb_connection_t *conn) {
screen->dock_clients = old_screen->dock_clients;
/* Update the dimensions */
for (int c = 0; c < num_workspaces; c++) {
Workspace *ws = &(workspaces[c]);
Workspace *ws;
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->screen != old_screen)
continue;
@ -347,7 +348,7 @@ void xinerama_requery_screens(xcb_connection_t *conn) {
break;
}
if (screen->current_workspace == -1) {
if (screen->current_workspace == NULL) {
/* Find the first unused workspace, preferring the ones
* which are assigned to this screen and initialize
* the screen with it. */
@ -364,38 +365,36 @@ void xinerama_requery_screens(xcb_connection_t *conn) {
}
/* Check for workspaces which are out of bounds */
for (int c = 0; c < num_workspaces; c++) {
if (workspaces[c].reassigned)
TAILQ_FOREACH(ws, workspaces, workspaces) {
if (ws->reassigned)
continue;
/* f_ws is a shortcut to the workspace to fix */
Workspace *f_ws = &(workspaces[c]);
Client *client;
LOG("Closing bar window (%p)\n", f_ws->screen->bar);
xcb_destroy_window(conn, f_ws->screen->bar);
LOG("Closing bar window (%p)\n", ws->screen->bar);
xcb_destroy_window(conn, ws->screen->bar);
LOG("Workspace %d's screen out of bounds, assigning to first screen\n", c+1);
f_ws->screen = first;
memcpy(&(f_ws->rect), &(first->rect), sizeof(Rect));
LOG("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(f_ws)
CIRCLEQ_FOREACH(client, &(f_ws->table[cols][rows]->clients), clients)
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, f_ws);
render_workspace(conn, first, ws);
/* …unless we want to see them at the moment, we should hide that workspace */
if (workspace_is_visible(f_ws))
if (workspace_is_visible(ws))
continue;
workspace_unmap_clients(conn, f_ws);
workspace_unmap_clients(conn, ws);
if (c_ws == f_ws) {
if (c_ws == ws) {
LOG("Need to adjust c_ws...\n");
c_ws = &(workspaces[first->current_workspace]);
c_ws = first->current_workspace;
}
}
xcb_flush(conn);