From: Michael Stapelberg Date: Sat, 13 Jun 2009 23:04:59 +0000 (+0200) Subject: Implement changing focus via keyboard between floating clients, fix several floating... X-Git-Tag: 3.b~54 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=00c6bdeb0b1c575a02c5d28fbd8549875e98c1f1;p=i3%2Fi3 Implement changing focus via keyboard between floating clients, fix several floating bugs --- diff --git a/include/data.h b/include/data.h index 5354217b..1f4e1d0f 100644 --- a/include/data.h +++ b/include/data.h @@ -3,7 +3,7 @@ * * i3 - an improved dynamic tiling window manager * - * (c) 2009 Michael Stapelberg and contributors + * © 2009 Michael Stapelberg and contributors * * See file LICENSE for license information. * @@ -167,6 +167,10 @@ struct Workspace { the focus can be reverted correctly when a client is closed */ 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 */ i3Screen *screen; @@ -319,6 +323,7 @@ struct Client { CIRCLEQ_ENTRY(Client) clients; SLIST_ENTRY(Client) dock_clients; SLIST_ENTRY(Client) focus_clients; + TAILQ_ENTRY(Client) floating_clients; }; /* diff --git a/include/floating.h b/include/floating.h index 232e118e..93110bc2 100644 --- a/include/floating.h +++ b/include/floating.h @@ -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); +/** + * 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 diff --git a/src/commands.c b/src/commands.c index 80b94ab9..274f0e27 100644 --- a/src/commands.c +++ b/src/commands.c @@ -923,8 +923,13 @@ void parse_command(xcb_connection_t *conn, const char *command) { return; } - if (last_focused == NULL || last_focused->floating >= FLOATING_AUTO_ON) { - LOG("Not performing (null or floating) \n"); + if (last_focused == NULL) { + LOG("Not performing (null) \n"); + return; + } + + if (last_focused->floating >= FLOATING_AUTO_ON && action != ACTION_FOCUS) { + LOG("Not performing (floating)\n"); return; } @@ -943,9 +948,11 @@ void parse_command(xcb_connection_t *conn, const char *command) { return; } - if (action == ACTION_FOCUS) - focus_thing(conn, direction, (with == WITH_WINDOW ? THING_WINDOW : THING_CONTAINER)); - else if (action == ACTION_MOVE) { + if (action == ACTION_FOCUS) { + if (last_focused->floating >= FLOATING_AUTO_ON) + 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) move_current_window(conn, direction); else move_current_container(conn, direction); diff --git a/src/floating.c b/src/floating.c index 6a2d8218..310b6a39 100644 --- a/src/floating.c +++ b/src/floating.c @@ -56,10 +56,13 @@ void toggle_floating_mode(xcb_connection_t *conn, Client *client, bool automatic break; /* If there are no tiling clients on this workspace, there can only be 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]; 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); Client *old_focused = con->currently_focused; /* 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->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) { LOG("Need to re-adjust currently_focused\n"); /* 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); } +/* + * 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; + } + } +} diff --git a/src/handlers.c b/src/handlers.c index e472bde5..2d4afc71 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -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); } + 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); xcb_reparent_window(conn, client->child, root, 0, 0); xcb_destroy_window(conn, client->frame); diff --git a/src/manage.c b/src/manage.c index e84c6345..f7769c3b 100644 --- a/src/manage.c +++ b/src/manage.c @@ -340,7 +340,8 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child, } else if (!new->dock) { /* 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) { - new->container->currently_focused = new; + if (new->floating <= FLOATING_USER_OFF) + new->container->currently_focused = new; if (new->container == CUR_CELL) 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) { 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.y = new->rect.y; LOG("copying size from tiling (%d, %d) size (%d, %d)\n", diff --git a/src/table.c b/src/table.c index 20b88cec..dab4b9ac 100644 --- a/src/table.c +++ b/src/table.c @@ -43,6 +43,7 @@ void init_table() { for (int i = 0; i < 10; i++) { workspaces[i].screen = NULL; workspaces[i].num = i; + TAILQ_INIT(&(workspaces[i].floating_clients)); expand_table_cols(&(workspaces[i])); expand_table_rows(&(workspaces[i])); }