]> git.sur5r.net Git - i3/i3/commitdiff
Refactor workspaces to be stored in a TAILQ instead of an array
authorMichael Stapelberg <michael@stapelberg.de>
Tue, 29 Sep 2009 17:45:41 +0000 (19:45 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Tue, 29 Sep 2009 17:45:41 +0000 (19:45 +0200)
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.

15 files changed:
include/data.h
include/table.h
src/cfgparse.y
src/click.c
src/client.c
src/commands.c
src/config.c
src/handlers.c
src/layout.c
src/mainx.c
src/manage.c
src/table.c
src/util.c
src/workspace.c
src/xinerama.c

index 9d5b841e2000709e461ad7206cc96d95980382e1..12c235544bb957a8be4cf9c1ec86e74d2a312704 100644 (file)
@@ -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;
index 05f543d6f593551b1c4e6c2b13990e132feb3be5..18561474bb14d394e65ddaa0fdb57df57f271749 100644 (file)
@@ -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;
 
index 26e00af9ebc26291f24f7f248077d52f87ba6bb8..a1c7aeef819d6966a46fc0e332252815f09578e0 100644 (file)
@@ -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 = $<number>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;
                 }
index d9aff341ef0462b987ab445c2e3b9b0a521abd4b..0aacf4507ab00dfaea012e7b5590bc08dc3cd214 100644 (file)
@@ -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;
         }
index bd5be673219c851716b877d083b1f9a8e9a8ce9d..6cd11d9d636231d7d9cdcc9aba77698e327bc576 100644 (file)
@@ -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)
index a43085c6955d6f2840a2e555f3a31e828a6a3034..c566ffe16d7b93205fcc3c185e129a534ebd5ec3 100644 (file)
@@ -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) {
index 52cf55b26ca1c84e857b18725503ebdfa60cd792..0e94afce2df73d351d6ff28cf9565151a2baf389 100644 (file)
@@ -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;
index cf28b9064573ead8252baf4951e32d3d747300cb..863aed4809230ce19c0645ea4c7f24320df473e9 100644 (file)
@@ -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);
         }
 
index 59309c9d78a7a7e530b2c5f906ede02cb8de8c18..f04b6de33392d62a233cc9c385aa61e21a128b3a 100644 (file)
@@ -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);
 }
index 4f235eca8cef4e40a9f304bf570f9725aa116f70..322e51e28a0f9eb185f2cac1cf62465ecdc49e70 100644 (file)
@@ -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);
 
index 5dcb837c1144538f2abf3ad64bc45c85256b9ff0..d45001341511f9987069d9b30211460421528fa2 100644 (file)
@@ -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;
                         }
index 4c5653aa5b9caef257a0c4459d42c77fe89a2cb0..72cf3d352aa662ff606780598b7b09340b211272 100644 (file)
 #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) {
index 7990b56e3f460420969fb8570e787815b600d31d..149af2dae32d43f0ac25f7f0ffe05387c1a0c846 100644 (file)
@@ -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;
index 36f807d241d54081e5f9b35717725b06d3c37e5b..8f0b42d7576a72d71a31bb6e2eec7889217c1e39 100644 (file)
  *
  */
 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 <workspace number> + 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);
index 77da7bbf96a91ffc8820cb541f81515c3a50e1e3..df7f94083d426186fe3521373aefe53708c4fc36 100644 (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);