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 */
|
/* 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
51
src/table.c
51
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) {
|
static void move_columns_from(xcb_connection_t *conn, Workspace *workspace, int cols) {
|
||||||
|
printf("firstly freeing \n");
|
||||||
|
|
||||||
|
/* 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 (; cols < workspace->cols; cols++)
|
||||||
for (int rows = 0; rows < workspace->rows; rows++) {
|
for (int rows = 0; rows < workspace->rows; rows++) {
|
||||||
Container *old_container = workspace->table[cols-1][rows],
|
printf("at col = %d, row = %d\n", cols, rows);
|
||||||
*new_container = workspace->table[cols][rows];
|
Container *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)
|
|
||||||
leave_stack_mode(conn, old_container);
|
|
||||||
|
|
||||||
free(old_container);
|
|
||||||
|
|
||||||
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 (int cols = 0; cols < workspace->cols; cols++) {
|
||||||
|
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 (; 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 *new_container = workspace->table[cols][rows];
|
||||||
*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)
|
|
||||||
leave_stack_mode(conn, old_container);
|
|
||||||
|
|
||||||
free(old_container);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 don’t need to */
|
/* redecorate_window flushes, so we don’t need to */
|
||||||
redecorate_window(conn, client);
|
redecorate_window(conn, client);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue