]> git.sur5r.net Git - i3/i3/commitdiff
Implement a focus stack, correctly free table columns/rows
authorMichael Stapelberg <michael+x200@stapelberg.de>
Thu, 5 Mar 2009 00:20:13 +0000 (01:20 +0100)
committerMichael Stapelberg <michael+x200@stapelberg.de>
Thu, 5 Mar 2009 00:20:13 +0000 (01:20 +0100)
include/data.h
src/handlers.c
src/mainx.c
src/table.c
src/util.c

index 1665139b0071710285b2f684318ab271a052eb1d..757640440e435bfb88c68e9f4a5dd0b175cb7d86 100644 (file)
@@ -140,6 +140,10 @@ struct Workspace {
         /* Contains all clients with _NET_WM_WINDOW_TYPE == _NET_WM_WINDOW_TYPE_DOCK */
         SLIST_HEAD(dock_clients_head, Client) dock_clients;
 
+        /* The focus stack contains the clients in the correct order of focus so that
+           the focus can be reverted correctly when a client is closed */
+        SLIST_HEAD(focus_stack_head, Client) focus_stack;
+
         /* Backpointer to the screen this workspace is on */
         i3Screen *screen;
 
@@ -240,6 +244,7 @@ struct Client {
         /* The following entry provides the necessary list pointers to use Client with LIST_* macros */
         CIRCLEQ_ENTRY(Client) clients;
         SLIST_ENTRY(Client) dock_clients;
+        SLIST_ENTRY(Client) focus_clients;
 };
 
 /*
index 4c9a6584d37a5e34ddca3a809cebe849fffa1cdc..47c1884fee6123ed7e6ca0021335ec8599051191 100644 (file)
@@ -419,27 +419,15 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti
         }
 
         if (client->container != NULL) {
-                Client *to_focus = NULL;
                 Container *con = client->container;
 
-                /* If the client which is being unmapped was the currently active, we need to find
-                   the next possible window to focus in this container */
-                if (con->currently_focused == client) {
-                        to_focus = CIRCLEQ_NEXT_OR_NULL(&(con->clients), client, clients);
-                        if (to_focus == NULL)
-                                to_focus = CIRCLEQ_PREV_OR_NULL(&(con->clients), client, clients);
-
-                        /* Set focus in data structure to the next/previous window, if any (else NULL) */
-                        con->currently_focused = to_focus;
-                }
-
                 /* If this was the fullscreen client, we need to unset it */
                 if (client->fullscreen)
                         con->workspace->fullscreen_client = NULL;
 
                 /* If the container will be empty now and is in stacking mode, we need to
                    correctly resize the stack_win */
-                if (con->currently_focused == NULL && con->mode == MODE_STACK) {
+                if (CIRCLEQ_EMPTY(&(con->clients)) && con->mode == MODE_STACK) {
                         struct Stack_Window *stack_win = &(con->stack_win);
                         stack_win->rect.height = 0;
                         xcb_unmap_window(conn, stack_win->window);
@@ -448,9 +436,16 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti
                 /* Remove the client from the list of clients */
                 CIRCLEQ_REMOVE(&(con->clients), client, clients);
 
+                /* Remove from the focus stack */
+                printf("Removing from focus stack\n");
+                SLIST_REMOVE(&(con->workspace->focus_stack), client, Client, focus_clients);
+
+                /* Remove from currently_focused */
+                con->currently_focused = NULL;
+
                 /* Actually set focus, if there is a window which should get it */
-                if (to_focus != NULL)
-                        set_focus(conn, to_focus);
+                if (!SLIST_EMPTY(&(con->workspace->focus_stack)))
+                        set_focus(conn, SLIST_FIRST(&(con->workspace->focus_stack)));
         }
 
         printf("child of 0x%08x.\n", client->frame);
index 9927af6febd608b2963848209dd9a0dea2a2d7f2..83233aeb584b65845c3b422a26e670dfe3ee8a76 100644 (file)
@@ -244,6 +244,8 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
                 if (old_focused != NULL)
                         CIRCLEQ_INSERT_AFTER(&(CUR_CELL->clients), old_focused, new, clients);
                 else CIRCLEQ_INSERT_TAIL(&(CUR_CELL->clients), new, clients);
+
+                SLIST_INSERT_HEAD(&(new->container->workspace->focus_stack), new, focus_clients);
         }
 
         render_layout(conn);
index eeb93a0ce026c186c2db45eea111cd89b51cba24..733acb6c32914664d25f4ffead4d9551df45c6ab 100644 (file)
@@ -108,52 +108,49 @@ bool cell_exists(int col, int row) {
 }
 
 static void move_columns_from(xcb_connection_t *conn, Workspace *workspace, int cols) {
-        for (; cols < workspace->cols; cols++)
-                for (int rows = 0; rows < workspace->rows; rows++) {
-                        Container *old_container = workspace->table[cols-1][rows],
-                                  *new_container = workspace->table[cols][rows];
+        printf("firstly freeing \n");
 
-                        /* Fix the container backpointer for all clients */
-                        Client *client;
-                        CIRCLEQ_FOREACH(client, &(old_container->clients), clients)
-                                client->container = new_container;
+        /* Clean up the column to be freed */
+        for (int rows = 0; rows < workspace->rows; rows++) {
+                Container *old_container = workspace->table[cols-1][rows];
 
-                        if (old_container->mode == MODE_STACK)
-                                leave_stack_mode(conn, old_container);
+                if (old_container->mode == MODE_STACK)
+                        leave_stack_mode(conn, old_container);
 
-                        free(old_container);
+                free(old_container);
+        }
+
+        for (; cols < workspace->cols; cols++)
+                for (int rows = 0; rows < workspace->rows; rows++) {
+                        printf("at col = %d, row = %d\n", cols, rows);
+                        Container *new_container = workspace->table[cols][rows];
 
                         printf("moving cols = %d to cols -1 = %d\n", cols, cols-1);
                         workspace->table[cols-1][rows] = new_container;
 
                         new_container->row = rows;
                         new_container->col = cols-1;
-
-                        workspace->table[cols][rows] = NULL;
                 }
 }
 
 static void move_rows_from(xcb_connection_t *conn, Workspace *workspace, int rows) {
-        for (; rows < workspace->rows; rows++)
-                for (int cols = 0; cols < workspace->cols; cols++) {
-                        Container *old_container = workspace->table[cols][rows-1],
-                                  *new_container = workspace->table[cols][rows];
+        for (int cols = 0; cols < workspace->cols; cols++) {
+                Container *old_container = workspace->table[cols][rows-1];
 
-                        /* Fix the container backpointer for all clients */
-                        Client *client;
-                        CIRCLEQ_FOREACH(client, &(old_container->clients), clients)
-                                client->container = new_container;
+                if (old_container->mode == MODE_STACK)
+                        leave_stack_mode(conn, old_container);
 
-                        if (old_container->mode == MODE_STACK)
-                                leave_stack_mode(conn, old_container);
-
-                        free(old_container);
+                free(old_container);
+        }
+        for (; rows < workspace->rows; rows++)
+                for (int cols = 0; cols < workspace->cols; cols++) {
+                        Container *new_container = workspace->table[cols][rows];
 
                         printf("moving rows = %d to rows -1 = %d\n", rows, rows - 1);
                         workspace->table[cols][rows-1] = new_container;
+
                         new_container->row = rows-1;
                         new_container->col = cols;
-                        workspace->table[cols][rows] = NULL;
                 }
 }
 
index 9d9ef693648a2f1a9d2f10cf59135b88783a819a..d154232482b3cfdb6ebfe3e55d737de0551c51d4 100644 (file)
@@ -152,6 +152,9 @@ void set_focus(xcb_connection_t *conn, Client *client) {
         if ((old_client != NULL) && (old_client != client))
                 redecorate_window(conn, old_client);
 
+        SLIST_REMOVE(&(client->container->workspace->focus_stack), client, Client, focus_clients);
+        SLIST_INSERT_HEAD(&(client->container->workspace->focus_stack), client, focus_clients);
+
         /* redecorate_window flushes, so we don’t need to */
         redecorate_window(conn, client);
 }