Implement a focus stack, correctly free table columns/rows

This commit is contained in:
Michael Stapelberg 2009-03-05 01:20:13 +01:00
parent bde67a179e
commit 17bca23a8c
5 changed files with 44 additions and 42 deletions

View File

@ -140,6 +140,10 @@ struct Workspace {
/* Contains all clients with _NET_WM_WINDOW_TYPE == _NET_WM_WINDOW_TYPE_DOCK */ /* Contains all clients with _NET_WM_WINDOW_TYPE == _NET_WM_WINDOW_TYPE_DOCK */
SLIST_HEAD(dock_clients_head, Client) dock_clients; 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 */ /* Backpointer to the screen this workspace is on */
i3Screen *screen; i3Screen *screen;
@ -240,6 +244,7 @@ struct Client {
/* The following entry provides the necessary list pointers to use Client with LIST_* macros */ /* The following entry provides the necessary list pointers to use Client with LIST_* macros */
CIRCLEQ_ENTRY(Client) clients; CIRCLEQ_ENTRY(Client) clients;
SLIST_ENTRY(Client) dock_clients; SLIST_ENTRY(Client) dock_clients;
SLIST_ENTRY(Client) focus_clients;
}; };
/* /*

View File

@ -419,27 +419,15 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti
} }
if (client->container != NULL) { if (client->container != NULL) {
Client *to_focus = NULL;
Container *con = client->container; 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 this was the fullscreen client, we need to unset it */
if (client->fullscreen) if (client->fullscreen)
con->workspace->fullscreen_client = NULL; con->workspace->fullscreen_client = NULL;
/* If the container will be empty now and is in stacking mode, we need to /* If the container will be empty now and is in stacking mode, we need to
correctly resize the stack_win */ 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); struct Stack_Window *stack_win = &(con->stack_win);
stack_win->rect.height = 0; stack_win->rect.height = 0;
xcb_unmap_window(conn, stack_win->window); 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 */ /* Remove the client from the list of clients */
CIRCLEQ_REMOVE(&(con->clients), client, 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 */ /* Actually set focus, if there is a window which should get it */
if (to_focus != NULL) if (!SLIST_EMPTY(&(con->workspace->focus_stack)))
set_focus(conn, to_focus); set_focus(conn, SLIST_FIRST(&(con->workspace->focus_stack)));
} }
printf("child of 0x%08x.\n", client->frame); printf("child of 0x%08x.\n", client->frame);

View File

@ -244,6 +244,8 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
if (old_focused != NULL) if (old_focused != NULL)
CIRCLEQ_INSERT_AFTER(&(CUR_CELL->clients), old_focused, new, clients); CIRCLEQ_INSERT_AFTER(&(CUR_CELL->clients), old_focused, new, clients);
else CIRCLEQ_INSERT_TAIL(&(CUR_CELL->clients), 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); render_layout(conn);

View 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) { static void move_columns_from(xcb_connection_t *conn, Workspace *workspace, int cols) {
for (; cols < workspace->cols; cols++) printf("firstly freeing \n");
for (int rows = 0; rows < workspace->rows; rows++) {
Container *old_container = workspace->table[cols-1][rows],
*new_container = workspace->table[cols][rows];
/* Fix the container backpointer for all clients */ /* Clean up the column to be freed */
Client *client; for (int rows = 0; rows < workspace->rows; rows++) {
CIRCLEQ_FOREACH(client, &(old_container->clients), clients) Container *old_container = workspace->table[cols-1][rows];
client->container = new_container;
if (old_container->mode == MODE_STACK) if (old_container->mode == MODE_STACK)
leave_stack_mode(conn, old_container); 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); printf("moving cols = %d to cols -1 = %d\n", cols, cols-1);
workspace->table[cols-1][rows] = new_container; workspace->table[cols-1][rows] = new_container;
new_container->row = rows; new_container->row = rows;
new_container->col = cols-1; new_container->col = cols-1;
workspace->table[cols][rows] = NULL;
} }
} }
static void move_rows_from(xcb_connection_t *conn, Workspace *workspace, int rows) { 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++) { for (int cols = 0; cols < workspace->cols; cols++) {
Container *old_container = workspace->table[cols][rows-1], Container *old_container = workspace->table[cols][rows-1];
*new_container = workspace->table[cols][rows];
/* 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) if (old_container->mode == MODE_STACK)
leave_stack_mode(conn, old_container); 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); printf("moving rows = %d to rows -1 = %d\n", rows, rows - 1);
workspace->table[cols][rows-1] = new_container; workspace->table[cols][rows-1] = new_container;
new_container->row = rows-1; new_container->row = rows-1;
new_container->col = cols; new_container->col = cols;
workspace->table[cols][rows] = NULL;
} }
} }

View File

@ -152,6 +152,9 @@ void set_focus(xcb_connection_t *conn, Client *client) {
if ((old_client != NULL) && (old_client != client)) if ((old_client != NULL) && (old_client != client))
redecorate_window(conn, old_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 dont need to */ /* redecorate_window flushes, so we dont need to */
redecorate_window(conn, client); redecorate_window(conn, client);
} }