/* 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;
/* 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;
};
/*
}
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);
/* 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);
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);
}
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;
}
}
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);
}