From 2b70e05ee91d86fc1efa8433c7df05e482893561 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 29 Sep 2009 19:45:41 +0200 Subject: [PATCH] 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. --- include/data.h | 4 +- include/table.h | 4 +- src/cfgparse.y | 16 ++++--- src/click.c | 33 +++++++++----- src/client.c | 5 ++- src/commands.c | 39 +++++++--------- src/config.c | 9 ++-- src/handlers.c | 6 +-- src/layout.c | 13 +++--- src/mainx.c | 6 +-- src/manage.c | 2 +- src/table.c | 14 +++--- src/util.c | 7 +-- src/workspace.c | 115 +++++++++++++++--------------------------------- src/xinerama.c | 45 +++++++++---------- 15 files changed, 144 insertions(+), 174 deletions(-) diff --git a/include/data.h b/include/data.h index 9d5b841e..12c23554 100644 --- a/include/data.h +++ b/include/data.h @@ -232,6 +232,8 @@ struct Workspace { * opened, for example) have the same size as always */ float *width_factor; float *height_factor; + + TAILQ_ENTRY(Workspace) workspaces; }; /** @@ -492,7 +494,7 @@ struct Screen { int num; /** Current workspace selected on this virtual screen */ - int current_workspace; + Workspace *current_workspace; /** x, y, width, height */ Rect rect; diff --git a/include/table.h b/include/table.h index 05f543d6..18561474 100644 --- a/include/table.h +++ b/include/table.h @@ -21,8 +21,8 @@ #define CUR_CELL (CUR_TABLE[current_col][current_row]) extern Workspace *c_ws; -extern Workspace *workspaces; -extern int num_workspaces; +extern TAILQ_HEAD(workspaces_head, Workspace) *workspaces; +//extern int num_workspaces; extern int current_col; extern int current_row; diff --git a/src/cfgparse.y b/src/cfgparse.y index 26e00af9..a1c7aeef 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -112,7 +112,7 @@ void parse_file(const char *f) { /* Then, allocate a new buffer and copy the file over to the new one, * but replace occurences of our variables */ char *walk = buf, *destwalk; - char *new = smalloc((stbuf.st_size + extra_bytes) * sizeof(char)); + char *new = smalloc((stbuf.st_size + extra_bytes + 1) * sizeof(char)); destwalk = new; while (walk < (buf + stbuf.st_size)) { /* Find the next variable */ @@ -335,11 +335,12 @@ new_container: * Thus, the user very likely awaits the default container mode * to trigger in this case, regardless of where it is inside * his configuration file. */ - for (int c = 0; c < num_workspaces; c++) { - if (workspaces[c].table == NULL) + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) { + if (ws->table == NULL) continue; switch_layout_mode(global_conn, - workspaces[c].table[0][0], + ws->table[0][0], config.container_mode); } } @@ -350,10 +351,11 @@ new_container: config.container_stack_limit_value = $7; /* See the comment above */ - for (int c = 0; c < num_workspaces; c++) { - if (workspaces[c].table == NULL) + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) { + if (ws->table == NULL) continue; - Container *con = workspaces[c].table[0][0]; + Container *con = ws->table[0][0]; con->stack_limit = config.container_stack_limit; con->stack_limit_value = config.container_stack_limit_value; } diff --git a/src/click.c b/src/click.c index d9aff341..0aacf450 100644 --- a/src/click.c +++ b/src/click.c @@ -128,29 +128,40 @@ static bool button_press_bar(xcb_connection_t *conn, xcb_button_press_event_t *e /* Check if the button was one of button4 or button5 (scroll up / scroll down) */ if (event->detail == XCB_BUTTON_INDEX_4 || event->detail == XCB_BUTTON_INDEX_5) { - int add = (event->detail == XCB_BUTTON_INDEX_4 ? -1 : 1); - for (int i = c_ws->num + add; (i >= 0) && (i < num_workspaces); i += add) - if (workspaces[i].screen == screen) { - workspace_show(conn, i+1); - return true; + Workspace *ws = c_ws; + if (event->detail == XCB_BUTTON_INDEX_5) { + while ((ws = TAILQ_NEXT(ws, workspaces)) != TAILQ_END(workspaces_head)) { + if (ws->screen == screen) { + workspace_show(conn, ws->num + 1); + return true; + } } + } else { + while ((ws = TAILQ_PREV(ws, workspaces_head, workspaces)) != TAILQ_END(workspaces)) { + if (ws->screen == screen) { + workspace_show(conn, ws->num + 1); + return true; + } + } + } return true; } int drawn = 0; /* Because workspaces can be on different screens, we need to loop through all of them and decide to count it based on its ->screen */ - for (int i = 0; i < num_workspaces; i++) { - if (workspaces[i].screen != screen) + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) { + if (ws->screen != screen) continue; LOG("Checking if click was on workspace %d with drawn = %d, tw = %d\n", - i, drawn, workspaces[i].text_width); + ws->num, drawn, ws->text_width); if (event->event_x > (drawn + 1) && - event->event_x <= (drawn + 1 + workspaces[i].text_width + 5 + 5)) { - workspace_show(conn, i+1); + event->event_x <= (drawn + 1 + ws->text_width + 5 + 5)) { + workspace_show(conn, ws->num + 1); return true; } - drawn += workspaces[i].text_width + 5 + 5 + 2; + drawn += ws->text_width + 5 + 5 + 2; } return true; } diff --git a/src/client.c b/src/client.c index bd5be673..6cd11d9d 100644 --- a/src/client.c +++ b/src/client.c @@ -332,8 +332,9 @@ void client_mark(xcb_connection_t *conn, Client *client, const char *mark) { /* Make sure no other client has this mark set */ Client *current; - for (int c = 0; c < 10; c++) - SLIST_FOREACH(current, &(workspaces[c].focus_stack), focus_clients) { + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) + SLIST_FOREACH(current, &(ws->focus_stack), focus_clients) { if (current == client || current->mark == NULL || strcmp(current->mark, mark) != 0) diff --git a/src/commands.c b/src/commands.c index a43085c6..c566ffe1 100644 --- a/src/commands.c +++ b/src/commands.c @@ -63,8 +63,9 @@ static void jump_to_mark(xcb_connection_t *conn, const char *mark) { Client *current; LOG("Jumping to \"%s\"\n", mark); - for (int c = 0; c < num_workspaces; c++) - SLIST_FOREACH(current, &(workspaces[c].focus_stack), focus_clients) { + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) + SLIST_FOREACH(current, &(ws->focus_stack), focus_clients) { if (current->mark == NULL || strcmp(current->mark, mark) != 0) continue; @@ -130,7 +131,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t } LOG("Switching to ws %d\n", target->current_workspace + 1); - workspace_show(conn, target->current_workspace + 1); + workspace_show(conn, target->current_workspace->num + 1); return; } @@ -165,7 +166,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t /* No screen found? Then wrap */ screen = get_screen_most((direction == D_UP ? D_DOWN : D_UP), container->workspace->screen); } - t_ws = workspace_get(screen->current_workspace); + t_ws = screen->current_workspace; new_row = (direction == D_UP ? (t_ws->rows - 1) : 0); } @@ -207,7 +208,7 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t LOG("Wrapping screen around horizontally\n"); screen = get_screen_most((direction == D_LEFT ? D_RIGHT : D_LEFT), container->workspace->screen); } - t_ws = workspace_get(screen->current_workspace); + t_ws = screen->current_workspace; new_col = (direction == D_LEFT ? (t_ws->cols - 1) : 0); } @@ -784,31 +785,25 @@ static char **append_argument(char **original, char *argument) { * */ static void next_previous_workspace(xcb_connection_t *conn, int direction) { - Workspace *t_ws; - int i; + Workspace *ws = c_ws; if (direction == 'n') { - /* If we are on the last workspace, we cannot go any further */ - if (c_ws->num == (num_workspaces-1)) - return; + while ((ws = TAILQ_NEXT(ws, workspaces)) != TAILQ_END(workspaces_head)) { + if (ws->screen == NULL) + continue; - for (i = c_ws->num + 1; i < num_workspaces; i++) { - t_ws = &(workspaces[i]); - if (t_ws->screen != NULL) - break; + workspace_show(conn, ws->num + 1); + return; } } else if (direction == 'p') { - if (c_ws->num == 0) + while ((ws = TAILQ_PREV(ws, workspaces_head, workspaces)) != TAILQ_END(workspaces)) { + if (ws->screen == NULL) + continue; + + workspace_show(conn, ws->num + 1); return; - for (i = c_ws->num - 1; i >= 0 ; i--) { - t_ws = &(workspaces[i]); - if (t_ws->screen != NULL) - break; } } - - if (t_ws->screen != NULL) - workspace_show(conn, i+1); } static void parse_resize_command(xcb_connection_t *conn, Client *last_focused, const char *command) { diff --git a/src/config.c b/src/config.c index 52cf55b2..0e94afce 100644 --- a/src/config.c +++ b/src/config.c @@ -183,6 +183,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, while (!TAILQ_EMPTY(bindings)) { bind = TAILQ_FIRST(bindings); TAILQ_REMOVE(bindings, bind, bindings); + FREE(bind->translated_to); FREE(bind->command); FREE(bind); } @@ -481,7 +482,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, LOG("setting name to \"%s\"\n", name); if (*name != '\0') - workspace_set_name(&(workspaces[ws_num - 1]), name); + workspace_set_name(workspace_get(ws_num - 1), name); free(ws_str); continue; } @@ -590,8 +591,8 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, REQUIRED_OPTION(font); /* Set an empty name for every workspace which got no name */ - for (int i = 0; i < num_workspaces; i++) { - Workspace *ws = &(workspaces[i]); + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) { if (ws->name != NULL) { /* If the font was not specified when the workspace name * was loaded, we need to predict the text width now */ @@ -601,7 +602,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, continue; } - workspace_set_name(&(workspaces[i]), NULL); + workspace_set_name(ws, NULL); } return; diff --git a/src/handlers.c b/src/handlers.c index cf28b906..863aed48 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -170,7 +170,7 @@ static void check_crossing_screen_boundary(uint32_t x, uint32_t y) { c_ws->current_row = current_row; c_ws->current_col = current_col; - c_ws = &workspaces[screen->current_workspace]; + c_ws = screen->current_workspace; current_row = c_ws->current_row; current_col = c_ws->current_col; LOG("We're now on virtual screen number %d\n", screen->num); @@ -486,7 +486,7 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti /* If this workspace is currently active, we don’t delete it */ i3Screen *screen; TAILQ_FOREACH(screen, virtual_screens, screens) - if (screen->current_workspace == client->workspace->num) { + if (screen->current_workspace == client->workspace) { workspace_active = true; workspace_empty = false; break; @@ -908,7 +908,7 @@ int handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t * the workspace bar */ if (!workspace_is_visible(client->workspace)) { i3Screen *screen = client->workspace->screen; - render_workspace(conn, screen, &(workspaces[screen->current_workspace])); + render_workspace(conn, screen, screen->current_workspace); xcb_flush(conn); } diff --git a/src/layout.c b/src/layout.c index 59309c9d..f04b6de3 100644 --- a/src/layout.c +++ b/src/layout.c @@ -238,7 +238,7 @@ void reposition_client(xcb_connection_t *conn, Client *client) { LOG("Client is on workspace %p with screen %p\n", client->workspace, client->workspace->screen); LOG("but screen at %d, %d is %p\n", client->rect.x, client->rect.y, screen); - floating_assign_to_workspace(client, workspace_get(screen->current_workspace)); + floating_assign_to_workspace(client, screen->current_workspace); } /* @@ -586,14 +586,14 @@ static void render_internal_bar(xcb_connection_t *conn, Workspace *r_ws, int wid xcb_change_gc_single(conn, screen->bargc, XCB_GC_FONT, font->id); int drawn = 0; - for (int c = 0; c < num_workspaces; c++) { - if (workspaces[c].screen != screen) + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) { + if (ws->screen != screen) continue; struct Colortriple *color; - Workspace *ws = &workspaces[c]; - if (screen->current_workspace == c) + if (screen->current_workspace == ws) color = &(config.bar.focused); else if (ws->urgent) color = &(config.bar.urgent); @@ -742,7 +742,8 @@ void render_layout(xcb_connection_t *conn) { return; TAILQ_FOREACH(screen, virtual_screens, screens) - render_workspace(conn, screen, &(workspaces[screen->current_workspace])); + if (screen->current_workspace != NULL) + render_workspace(conn, screen, screen->current_workspace); xcb_flush(conn); } diff --git a/src/mainx.c b/src/mainx.c index 4f235eca..322e51e2 100644 --- a/src/mainx.c +++ b/src/mainx.c @@ -211,8 +211,8 @@ int main(int argc, char *argv[], char *env[]) { * connection and a loaded configuration (default mode for new * containers may be stacking, which requires a new window to be * created), it had to be delayed. */ - expand_table_cols(&(workspaces[0])); - expand_table_rows(&(workspaces[0])); + expand_table_cols(TAILQ_FIRST(workspaces)); + expand_table_rows(TAILQ_FIRST(workspaces)); /* Place requests for the atoms we need as soon as possible */ #define REQUEST_ATOM(name) atom_cookies[name] = xcb_intern_atom(conn, 0, strlen(#name), #name); @@ -456,7 +456,7 @@ int main(int argc, char *argv[], char *env[]) { } LOG("Starting on %d\n", screen->current_workspace); - c_ws = &workspaces[screen->current_workspace]; + c_ws = screen->current_workspace; manage_existing_windows(conn, &prophs, root); diff --git a/src/manage.c b/src/manage.c index 5dcb837c..d4500134 100644 --- a/src/manage.c +++ b/src/manage.c @@ -329,7 +329,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, LOG("Assignment \"%s\" matches, so putting it on workspace %d\n", assign->windowclass_title, assign->workspace); - if (c_ws->screen->current_workspace == (assign->workspace-1)) { + if (c_ws->screen->current_workspace->num == (assign->workspace-1)) { LOG("We are already there, no need to do anything\n"); break; } diff --git a/src/table.c b/src/table.c index 4c5653aa..72cf3d35 100644 --- a/src/table.c +++ b/src/table.c @@ -26,10 +26,11 @@ #include "i3.h" #include "layout.h" #include "config.h" +#include "workspace.h" int current_workspace = 0; int num_workspaces = 1; -Workspace *workspaces; +struct workspaces_head *workspaces; /* Convenience pointer to the current workspace */ Workspace *c_ws; int current_col = 0; @@ -40,12 +41,13 @@ int current_row = 0; * */ void init_table() { - workspaces = scalloc(sizeof(Workspace)); - c_ws = workspaces; + workspaces = scalloc(sizeof(struct workspaces_head)); + TAILQ_INIT(workspaces); - workspaces[0].screen = NULL; - workspaces[0].num = 0; - TAILQ_INIT(&(workspaces[0].floating_clients)); + c_ws = scalloc(sizeof(Workspace)); + workspace_set_name(c_ws, NULL); + TAILQ_INIT(&(c_ws->floating_clients)); + TAILQ_INSERT_TAIL(workspaces, c_ws, workspaces); } static void new_container(Workspace *workspace, Container **container, int col, int row) { diff --git a/src/util.c b/src/util.c index 7990b56e..149af2da 100644 --- a/src/util.c +++ b/src/util.c @@ -458,12 +458,13 @@ Client *get_matching_client(xcb_connection_t *conn, const char *window_classtitl } LOG("Getting clients for class \"%s\" / title \"%s\"\n", to_class, to_title); - for (int workspace = 0; workspace < num_workspaces; workspace++) { - if (workspaces[workspace].screen == NULL) + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) { + if (ws->screen == NULL) continue; Client *client; - SLIST_FOREACH(client, &(workspaces[workspace].focus_stack), focus_clients) { + SLIST_FOREACH(client, &(ws->focus_stack), focus_clients) { LOG("Checking client with class=%s, name=%s\n", client->window_class, client->name); if (!client_matches_class_name(client, to_class, to_title, to_title_ucs, to_title_ucs_len)) continue; diff --git a/src/workspace.c b/src/workspace.c index 36f807d2..8f0b42d7 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -34,80 +34,31 @@ * */ Workspace *workspace_get(int number) { - if (number > (num_workspaces-1)) { - int old_num_workspaces = num_workspaces; - - /* Convert all container->workspace and client->workspace - * pointers to numbers representing their workspace. Necessary - * because the realloc() may make all the pointers invalid, so - * we need to preserve them this way and restore them later. - * - * To distinguish between the first workspace and a NULL - * pointer, we store + 1. */ - for (int c = 0; c < num_workspaces; c++) { - FOR_TABLE(&(workspaces[c])) { - Container *con = workspaces[c].table[cols][rows]; - if (con->workspace != NULL) { - LOG("Handling con %p with pointer %p (num %d)\n", con, con->workspace, con->workspace->num); - con->workspace = (Workspace*)(con->workspace->num + 1); - } - } - Client *current; - SLIST_FOREACH(current, &(workspaces[c].focus_stack), focus_clients) { - if (current->workspace == NULL) - continue; - LOG("Handling client %p with pointer %p (num %d)\n", current, current->workspace, current->workspace->num); - current->workspace = (Workspace*)(current->workspace->num + 1); - } - } + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) + if (ws->num == number) + return ws; - /* preserve c_ws */ - c_ws = (Workspace*)(c_ws->num); - - LOG("We need to initialize that one\n"); - num_workspaces = number+1; - workspaces = realloc(workspaces, num_workspaces * sizeof(Workspace)); - /* Zero out the new workspaces so that we have sane default values */ - for (int c = old_num_workspaces; c < num_workspaces; c++) - memset(&workspaces[c], 0, sizeof(Workspace)); - - /* Immediately after the realloc(), we restore the pointers. - * They may be used when initializing the new workspaces, for - * example when the user configures containers to be stacking - * by default, thus requiring re-rendering the layout. */ - c_ws = workspace_get((int)c_ws); - - for (int c = 0; c < old_num_workspaces; c++) { - FOR_TABLE(&(workspaces[c])) { - Container *con = workspaces[c].table[cols][rows]; - if (con->workspace != NULL) { - LOG("Handling con %p with (num %d)\n", con, con->workspace); - con->workspace = workspace_get((int)con->workspace - 1); - } - } - Client *current; - SLIST_FOREACH(current, &(workspaces[c].focus_stack), focus_clients) { - if (current->workspace == NULL) - continue; - LOG("Handling client %p with (num %d)\n", current, current->workspace); - current->workspace = workspace_get((int)current->workspace - 1); - } - } + /* If we are still there, we could not find the requested workspace. */ + int last_ws = TAILQ_LAST(workspaces, workspaces_head)->num; - /* Initialize the new workspaces */ - for (int c = old_num_workspaces; c < num_workspaces; c++) { - memset(&workspaces[c], 0, sizeof(Workspace)); - workspaces[c].num = c; - TAILQ_INIT(&(workspaces[c].floating_clients)); - expand_table_cols(&(workspaces[c])); - expand_table_rows(&(workspaces[c])); - workspace_set_name(&(workspaces[c]), NULL); - } + LOG("We need to initialize that one, last ws = %d\n", last_ws); + + for (int c = last_ws; c < number; c++) { + LOG("Creating new ws\n"); + + ws = scalloc(sizeof(Workspace)); + ws->num = number; + TAILQ_INIT(&(ws->floating_clients)); + expand_table_cols(ws); + expand_table_rows(ws); + workspace_set_name(ws, NULL); - LOG("done\n"); + TAILQ_INSERT_TAIL(workspaces, ws, workspaces); } + LOG("done\n"); - return &(workspaces[number]); + return ws; } /* @@ -145,7 +96,7 @@ void workspace_set_name(Workspace *ws, const char *name) { * */ bool workspace_is_visible(Workspace *ws) { - return (ws->screen->current_workspace == ws->num); + return (ws->screen->current_workspace == ws); } /* @@ -174,7 +125,7 @@ void workspace_show(xcb_connection_t *conn, int workspace) { /* Store the old client */ Client *old_client = CUR_CELL->currently_focused; - c_ws = workspace_get(t_ws->screen->current_workspace); + c_ws = t_ws->screen->current_workspace; current_col = c_ws->current_col; current_row = c_ws->current_row; if (CUR_CELL->currently_focused != NULL) @@ -192,7 +143,7 @@ void workspace_show(xcb_connection_t *conn, int workspace) { } /* Check if we need to change something or if we’re already there */ - if (c_ws->screen->current_workspace == (workspace-1)) { + if (c_ws->screen->current_workspace->num == (workspace-1)) { Client *last_focused = SLIST_FIRST(&(c_ws->focus_stack)); if (last_focused != SLIST_END(&(c_ws->focus_stack))) set_focus(conn, last_focused, true); @@ -204,9 +155,8 @@ void workspace_show(xcb_connection_t *conn, int workspace) { return; } - t_ws->screen->current_workspace = workspace-1; Workspace *old_workspace = c_ws; - c_ws = workspace_get(workspace-1); + c_ws = t_ws->screen->current_workspace = workspace_get(workspace-1); /* Unmap all clients of the old workspace */ workspace_unmap_clients(conn, old_workspace); @@ -325,8 +275,8 @@ void workspace_initialize(Workspace *ws, i3Screen *screen) { Workspace *get_first_workspace_for_screen(struct screens_head *slist, i3Screen *screen) { Workspace *result = NULL; - for (int c = 0; c < num_workspaces; c++) { - Workspace *ws = workspace_get(c); + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) { if (ws->preferred_screen == NULL || !screens_are_equal(get_screen_from_preference(slist, ws->preferred_screen), screen)) continue; @@ -337,11 +287,12 @@ Workspace *get_first_workspace_for_screen(struct screens_head *slist, i3Screen * if (result == NULL) { /* No assignment found, returning first unused workspace */ - for (int c = 0; c < num_workspaces; c++) { - if (workspaces[c].screen != NULL) + Workspace *ws; + TAILQ_FOREACH(ws, workspaces, workspaces) { + if (ws->screen != NULL) continue; - result = workspace_get(c); + result = ws; break; } } @@ -349,7 +300,11 @@ Workspace *get_first_workspace_for_screen(struct screens_head *slist, i3Screen * if (result == NULL) { LOG("No existing free workspace found to assign, creating a new one\n"); - result = workspace_get(num_workspaces); + Workspace *ws; + int last_ws = 0; + TAILQ_FOREACH(ws, workspaces, workspaces) + last_ws = ws->num; + result = workspace_get(last_ws + 1); } workspace_initialize(result, screen); diff --git a/src/xinerama.c b/src/xinerama.c index 77da7bbf..df7f9408 100644 --- a/src/xinerama.c +++ b/src/xinerama.c @@ -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); -- 2.39.5