Implement changing focus via keyboard between floating clients, fix several floating bugs
This commit is contained in:
parent
33b331d444
commit
00c6bdeb0b
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* i3 - an improved dynamic tiling window manager
|
* i3 - an improved dynamic tiling window manager
|
||||||
*
|
*
|
||||||
* (c) 2009 Michael Stapelberg and contributors
|
* © 2009 Michael Stapelberg and contributors
|
||||||
*
|
*
|
||||||
* See file LICENSE for license information.
|
* See file LICENSE for license information.
|
||||||
*
|
*
|
||||||
|
@ -167,6 +167,10 @@ struct Workspace {
|
||||||
the focus can be reverted correctly when a client is closed */
|
the focus can be reverted correctly when a client is closed */
|
||||||
SLIST_HEAD(focus_stack_head, Client) focus_stack;
|
SLIST_HEAD(focus_stack_head, Client) focus_stack;
|
||||||
|
|
||||||
|
/* This tail queue contains the floating clients in order of when they were first
|
||||||
|
* set to floating (new floating clients are just appended) */
|
||||||
|
TAILQ_HEAD(floating_clients_head, Client) floating_clients;
|
||||||
|
|
||||||
/* Backpointer to the screen this workspace is on */
|
/* Backpointer to the screen this workspace is on */
|
||||||
i3Screen *screen;
|
i3Screen *screen;
|
||||||
|
|
||||||
|
@ -319,6 +323,7 @@ struct Client {
|
||||||
CIRCLEQ_ENTRY(Client) clients;
|
CIRCLEQ_ENTRY(Client) clients;
|
||||||
SLIST_ENTRY(Client) dock_clients;
|
SLIST_ENTRY(Client) dock_clients;
|
||||||
SLIST_ENTRY(Client) focus_clients;
|
SLIST_ENTRY(Client) focus_clients;
|
||||||
|
TAILQ_ENTRY(Client) floating_clients;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -37,4 +37,13 @@ int floating_border_click(xcb_connection_t *conn, Client *client, xcb_button_pre
|
||||||
*/
|
*/
|
||||||
void floating_drag_window(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event);
|
void floating_drag_window(xcb_connection_t *conn, Client *client, xcb_button_press_event_t *event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes focus in the given direction for floating clients.
|
||||||
|
*
|
||||||
|
* Changing to the left/right means going to the previous/next floating client,
|
||||||
|
* changing to top/bottom means cycling through the Z-index.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void floating_focus_direction(xcb_connection_t *conn, Client *currently_focused, direction_t direction);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -923,8 +923,13 @@ void parse_command(xcb_connection_t *conn, const char *command) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_focused == NULL || last_focused->floating >= FLOATING_AUTO_ON) {
|
if (last_focused == NULL) {
|
||||||
LOG("Not performing (null or floating) \n");
|
LOG("Not performing (null) \n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_focused->floating >= FLOATING_AUTO_ON && action != ACTION_FOCUS) {
|
||||||
|
LOG("Not performing (floating)\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -943,9 +948,11 @@ void parse_command(xcb_connection_t *conn, const char *command) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == ACTION_FOCUS)
|
if (action == ACTION_FOCUS) {
|
||||||
focus_thing(conn, direction, (with == WITH_WINDOW ? THING_WINDOW : THING_CONTAINER));
|
if (last_focused->floating >= FLOATING_AUTO_ON)
|
||||||
else if (action == ACTION_MOVE) {
|
floating_focus_direction(conn, last_focused, direction);
|
||||||
|
else focus_thing(conn, direction, (with == WITH_WINDOW ? THING_WINDOW : THING_CONTAINER));
|
||||||
|
} else if (action == ACTION_MOVE) {
|
||||||
if (with == WITH_WINDOW)
|
if (with == WITH_WINDOW)
|
||||||
move_current_window(conn, direction);
|
move_current_window(conn, direction);
|
||||||
else move_current_container(conn, direction);
|
else move_current_container(conn, direction);
|
||||||
|
|
|
@ -56,10 +56,13 @@ void toggle_floating_mode(xcb_connection_t *conn, Client *client, bool automatic
|
||||||
break;
|
break;
|
||||||
/* If there are no tiling clients on this workspace, there can only be one
|
/* If there are no tiling clients on this workspace, there can only be one
|
||||||
* container: the first one */
|
* container: the first one */
|
||||||
if (next_tiling == SLIST_END(&(client->workspace->focus_stack)))
|
if (next_tiling == TAILQ_END(&(client->workspace->focus_stack)))
|
||||||
con = client->workspace->table[0][0];
|
con = client->workspace->table[0][0];
|
||||||
else con = next_tiling->container;
|
else con = next_tiling->container;
|
||||||
|
|
||||||
|
/* Remove the client from the list of floating clients */
|
||||||
|
TAILQ_REMOVE(&(client->workspace->floating_clients), client, floating_clients);
|
||||||
|
|
||||||
LOG("destination container = %p\n", con);
|
LOG("destination container = %p\n", con);
|
||||||
Client *old_focused = con->currently_focused;
|
Client *old_focused = con->currently_focused;
|
||||||
/* Preserve position/size */
|
/* Preserve position/size */
|
||||||
|
@ -87,6 +90,9 @@ void toggle_floating_mode(xcb_connection_t *conn, Client *client, bool automatic
|
||||||
client_remove_from_container(conn, client, con, false);
|
client_remove_from_container(conn, client, con, false);
|
||||||
client->container = NULL;
|
client->container = NULL;
|
||||||
|
|
||||||
|
/* Add the client to the list of floating clients for its workspace */
|
||||||
|
TAILQ_INSERT_TAIL(&(client->workspace->floating_clients), client, floating_clients);
|
||||||
|
|
||||||
if (con->currently_focused == client) {
|
if (con->currently_focused == client) {
|
||||||
LOG("Need to re-adjust currently_focused\n");
|
LOG("Need to re-adjust currently_focused\n");
|
||||||
/* Get the next client in the focus stack for this particular container */
|
/* Get the next client in the focus stack for this particular container */
|
||||||
|
@ -288,3 +294,27 @@ static void drag_pointer(xcb_connection_t *conn, Client *client, xcb_button_pres
|
||||||
xcb_flush(conn);
|
xcb_flush(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Changes focus in the given direction for floating clients.
|
||||||
|
*
|
||||||
|
* Changing to the left/right means going to the previous/next floating client,
|
||||||
|
* changing to top/bottom means cycling through the Z-index.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void floating_focus_direction(xcb_connection_t *conn, Client *currently_focused, direction_t direction) {
|
||||||
|
LOG("floating focus\n");
|
||||||
|
|
||||||
|
if (direction == D_LEFT || direction == D_RIGHT) {
|
||||||
|
/* Go to the next/previous floating client */
|
||||||
|
Client *client;
|
||||||
|
|
||||||
|
while ((client = (direction == D_LEFT ? TAILQ_PREV(currently_focused, floating_clients_head, floating_clients) :
|
||||||
|
TAILQ_NEXT(currently_focused, floating_clients))) !=
|
||||||
|
TAILQ_END(&(currently_focused->workspace->floating_clients))) {
|
||||||
|
if (!client->floating)
|
||||||
|
continue;
|
||||||
|
set_focus(conn, client, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -584,6 +584,11 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti
|
||||||
SLIST_REMOVE(&(client->workspace->screen->dock_clients), client, Client, dock_clients);
|
SLIST_REMOVE(&(client->workspace->screen->dock_clients), client, Client, dock_clients);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (client->floating) {
|
||||||
|
LOG("Removing from floating clients\n");
|
||||||
|
TAILQ_REMOVE(&(client->workspace->floating_clients), client, floating_clients);
|
||||||
|
}
|
||||||
|
|
||||||
LOG("child of 0x%08x.\n", client->frame);
|
LOG("child of 0x%08x.\n", client->frame);
|
||||||
xcb_reparent_window(conn, client->child, root, 0, 0);
|
xcb_reparent_window(conn, client->child, root, 0, 0);
|
||||||
xcb_destroy_window(conn, client->frame);
|
xcb_destroy_window(conn, client->frame);
|
||||||
|
|
|
@ -340,7 +340,8 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
|
||||||
} else if (!new->dock) {
|
} else if (!new->dock) {
|
||||||
/* Focus the new window if we’re not in fullscreen mode and if it is not a dock window */
|
/* Focus the new window if we’re not in fullscreen mode and if it is not a dock window */
|
||||||
if (new->container->workspace->fullscreen_client == NULL) {
|
if (new->container->workspace->fullscreen_client == NULL) {
|
||||||
new->container->currently_focused = new;
|
if (new->floating <= FLOATING_USER_OFF)
|
||||||
|
new->container->currently_focused = new;
|
||||||
if (new->container == CUR_CELL)
|
if (new->container == CUR_CELL)
|
||||||
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, new->child, XCB_CURRENT_TIME);
|
xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, new->child, XCB_CURRENT_TIME);
|
||||||
}
|
}
|
||||||
|
@ -372,6 +373,11 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
|
||||||
if (new->floating >= FLOATING_AUTO_ON) {
|
if (new->floating >= FLOATING_AUTO_ON) {
|
||||||
SLIST_INSERT_HEAD(&(new->workspace->focus_stack), new, focus_clients);
|
SLIST_INSERT_HEAD(&(new->workspace->focus_stack), new, focus_clients);
|
||||||
|
|
||||||
|
/* Add the client to the list of floating clients for its workspace */
|
||||||
|
TAILQ_INSERT_TAIL(&(new->workspace->floating_clients), new, floating_clients);
|
||||||
|
|
||||||
|
new->container = NULL;
|
||||||
|
|
||||||
new->floating_rect.x = new->rect.x;
|
new->floating_rect.x = new->rect.x;
|
||||||
new->floating_rect.y = new->rect.y;
|
new->floating_rect.y = new->rect.y;
|
||||||
LOG("copying size from tiling (%d, %d) size (%d, %d)\n",
|
LOG("copying size from tiling (%d, %d) size (%d, %d)\n",
|
||||||
|
|
|
@ -43,6 +43,7 @@ void init_table() {
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
workspaces[i].screen = NULL;
|
workspaces[i].screen = NULL;
|
||||||
workspaces[i].num = i;
|
workspaces[i].num = i;
|
||||||
|
TAILQ_INIT(&(workspaces[i].floating_clients));
|
||||||
expand_table_cols(&(workspaces[i]));
|
expand_table_cols(&(workspaces[i]));
|
||||||
expand_table_rows(&(workspaces[i]));
|
expand_table_rows(&(workspaces[i]));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue