Implement a focus stack, correctly free table columns/rows
This commit is contained in:
parent
bde67a179e
commit
17bca23a8c
|
@ -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;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
35
src/table.c
35
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);
|
||||
|
||||
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];
|
||||
|
||||
/* Fix the container backpointer for all clients */
|
||||
Client *client;
|
||||
CIRCLEQ_FOREACH(client, &(old_container->clients), clients)
|
||||
client->container = new_container;
|
||||
Container *old_container = workspace->table[cols][rows-1];
|
||||
|
||||
if (old_container->mode == MODE_STACK)
|
||||
leave_stack_mode(conn, 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue