From 17bca23a8c03ab643b65bb5ce71783d413b9864c Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 5 Mar 2009 01:20:13 +0100 Subject: [PATCH] Implement a focus stack, correctly free table columns/rows --- include/data.h | 5 +++++ src/handlers.c | 25 ++++++++++--------------- src/mainx.c | 2 ++ src/table.c | 49 +++++++++++++++++++++++-------------------------- src/util.c | 3 +++ 5 files changed, 43 insertions(+), 41 deletions(-) diff --git a/include/data.h b/include/data.h index 1665139b..75764044 100644 --- a/include/data.h +++ b/include/data.h @@ -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; }; /* diff --git a/src/handlers.c b/src/handlers.c index 4c9a6584..47c1884f 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -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); diff --git a/src/mainx.c b/src/mainx.c index 9927af6f..83233aeb 100644 --- a/src/mainx.c +++ b/src/mainx.c @@ -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); diff --git a/src/table.c b/src/table.c index eeb93a0c..733acb6c 100644 --- a/src/table.c +++ b/src/table.c @@ -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; } } diff --git a/src/util.c b/src/util.c index 9d9ef693..d1542324 100644 --- a/src/util.c +++ b/src/util.c @@ -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); } -- 2.39.5