]> git.sur5r.net Git - i3/i3/commitdiff
Implement changing focus via keyboard between floating clients, fix several floating...
authorMichael Stapelberg <michael@stapelberg.de>
Sat, 13 Jun 2009 23:04:59 +0000 (01:04 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Sat, 13 Jun 2009 23:04:59 +0000 (01:04 +0200)
include/data.h
include/floating.h
src/commands.c
src/floating.c
src/handlers.c
src/manage.c
src/table.c

index 5354217bcac24fda2b4cf3483359842c06b1d559..1f4e1d0fd5205d0a788ba96cede1089249eb4c8b 100644 (file)
@@ -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;
 };
 
 /*
index 232e118e7f76034aad47ced4fba53284ffd79c2c..93110bc25beb5380a289bde4c6266c5eddfa2786 100644 (file)
@@ -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
index 80b94ab9d629a40306819c08f4da1db3bcca8c1c..274f0e27b8c9c36cc458598c60b79bcfe10ba71b 100644 (file)
@@ -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);
index 6a2d8218f017b7efbc879cc708817ed5b24c03aa..310b6a395e774fbfc8907af19ce9558fa6503299 100644 (file)
@@ -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;
+                }
+        }
+}
index e472bde5f8d60bfc8dbb17689155d20376aaf020..2d4afc71bda549d4af8b0604f05340406a7d21f4 100644 (file)
@@ -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);
index e84c63453c70c218a2dc04dd40de6a46b86b3f6d..f7769c3bcb03178769f4a8bb00bfa93c42c47c6d 100644 (file)
@@ -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",
index 20b88cec76a828ecc6a53bf5929cf5cea724c194..dab4b9ac1665f75c0be578c81d72a0c8bdc6cac7 100644 (file)
@@ -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]));
         }