*
* i3 - an improved dynamic tiling window manager
*
- * (c) 2009 Michael Stapelberg and contributors
+ * © 2009 Michael Stapelberg and contributors
*
* See file LICENSE for license information.
*
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;
CIRCLEQ_ENTRY(Client) clients;
SLIST_ENTRY(Client) dock_clients;
SLIST_ENTRY(Client) focus_clients;
+ TAILQ_ENTRY(Client) floating_clients;
};
/*
*/
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
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;
}
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);
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 */
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 */
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;
+ }
+ }
+}
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);
} 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);
}
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",
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]));
}