]> git.sur5r.net Git - i3/i3/commitdiff
Implement clients going automatically into floating
authorMichael Stapelberg <michael@stapelberg.de>
Sat, 30 May 2009 22:31:18 +0000 (00:31 +0200)
committerMichael Stapelberg <michael@stapelberg.de>
Sat, 30 May 2009 22:31:18 +0000 (00:31 +0200)
include/data.h
include/floating.h
src/client.c
src/commands.c
src/floating.c
src/handlers.c
src/layout.c
src/manage.c
src/util.c

index 7308f5c1201d93758fbc3be9209f2a914c2e5a47..5354217bcac24fda2b4cf3483359842c06b1d559 100644 (file)
@@ -242,6 +242,10 @@ struct Font {
  *
  */
 struct Client {
+        /* initialized will be set to true if the client was fully initialized by
+         * manage_window() and all functions can be used normally */
+        bool initialized;
+
         /* if you set a client to floating and set it back to managed, it does remember its old
            position and *tries* to get back there */
         Cell old_position;
@@ -284,8 +288,11 @@ struct Client {
         /* fullscreen is pretty obvious */
         bool fullscreen;
 
-        /* floating? (= not in tiling layout) */
-        bool floating;
+        /* floating? (= not in tiling layout) This cannot be simply a bool because we want to keep track
+         * of whether the status was set by the application (by setting WM_CLASS to tools for example) or
+         * by the user. The user’s choice overwrites automatic mode, of course. The order of the values
+         * is important because we check with >= FLOATING_AUTO_ON if a client is floating. */
+        enum { FLOATING_AUTO_OFF = 0, FLOATING_USER_OFF = 1, FLOATING_AUTO_ON = 2, FLOATING_USER_ON = 3 } floating;
 
         /* Ensure TITLEBAR_TOP maps to 0 because we use calloc for initialization later */
         enum { TITLEBAR_TOP = 0, TITLEBAR_LEFT, TITLEBAR_RIGHT, TITLEBAR_BOTTOM, TITLEBAR_OFF } titlebar_position;
index aa3c55b7917d37fef616ec6aa3c6abc16db52a81..232e118e7f76034aad47ced4fba53284ffd79c2c 100644 (file)
  * Correctly takes care of the position/size (separately stored for tiling/floating mode)
  * and repositions/resizes/redecorates the client.
  *
+ * If the automatic flag is set to true, this was an automatic update by a change of the
+ * window class from the application which can be overwritten by the user.
+ *
  */
-void toggle_floating_mode(xcb_connection_t *conn, Client *client);
+void toggle_floating_mode(xcb_connection_t *conn, Client *client, bool automatic);
 
 /**
  * Called whenever the user clicks on a border (not the titlebar!) of a floating window.
index 9eb345654431b15c7b853e0887801b6dcefd6306..53cacbf4d69f713cb939c01540c054d28a80eacf 100644 (file)
@@ -186,7 +186,7 @@ void client_toggle_fullscreen(xcb_connection_t *conn, Client *client) {
                 LOG("leaving fullscreen mode\n");
                 client->fullscreen = false;
                 workspace->fullscreen_client = NULL;
-                if (client->floating) {
+                if (client->floating >= FLOATING_AUTO_ON) {
                         /* For floating clients it’s enough if we just reconfigure that window (in fact,
                          * re-rendering the layout will not update the client.) */
                         reposition_client(conn, client);
index 8a66f4801f995b27437c209aad167133fa983190..d84adf45d16d4804be3581d37dbe1c50607b908e 100644 (file)
@@ -617,7 +617,7 @@ void show_workspace(xcb_connection_t *conn, int workspace) {
 
         /* Map all floating clients */
         SLIST_FOREACH(client, &(c_ws->focus_stack), focus_clients) {
-                if (!client->floating)
+                if (client->floating <= FLOATING_USER_OFF)
                         continue;
 
                 xcb_map_window(conn, client->frame);
@@ -836,7 +836,7 @@ void parse_command(xcb_connection_t *conn, const char *command) {
 
         /* Is it just 's' for stacking or 'd' for default? */
         if ((command[0] == 's' || command[0] == 'd') && (command[1] == '\0')) {
-                if (last_focused == NULL || last_focused->floating) {
+                if (last_focused == NULL || last_focused->floating >= FLOATING_AUTO_ON) {
                         LOG("not switching, this is a floating client\n");
                         return;
                 }
@@ -852,7 +852,7 @@ void parse_command(xcb_connection_t *conn, const char *command) {
                         return;
                 }
 
-                toggle_floating_mode(conn, last_focused);
+                toggle_floating_mode(conn, last_focused, false);
                 /* delete all empty columns/rows */
                 cleanup_table(conn, last_focused->workspace);
 
@@ -908,13 +908,13 @@ void parse_command(xcb_connection_t *conn, const char *command) {
         }
 
         if (*rest == '\0') {
-                if (last_focused != NULL && last_focused->floating)
+                if (last_focused != NULL && last_focused->floating >= FLOATING_AUTO_ON)
                         move_floating_window_to_workspace(conn, last_focused, workspace);
                 else move_current_window_to_workspace(conn, workspace);
                 return;
         }
 
-        if (last_focused == NULL || last_focused->floating) {
+        if (last_focused == NULL || last_focused->floating >= FLOATING_AUTO_ON) {
                 LOG("Not performing (null or floating) \n");
                 return;
         }
index 90064c29b8052b8ea9014cebbf352b46873af50e..9c71cf36fb174b8b1de7be36fd6eb1175accbb01 100644 (file)
@@ -39,15 +39,18 @@ static void drag_pointer(xcb_connection_t *conn, Client *client, xcb_button_pres
  * Correctly takes care of the position/size (separately stored for tiling/floating mode)
  * and repositions/resizes/redecorates the client.
  *
+ * If the automatic flag is set to true, this was an automatic update by a change of the
+ * window class from the application which can be overwritten by the user.
+ *
  */
-void toggle_floating_mode(xcb_connection_t *conn, Client *client) {
+void toggle_floating_mode(xcb_connection_t *conn, Client *client, bool automatic) {
         Container *con = client->container;
 
         if (con == NULL) {
                 LOG("This client is already in floating (container == NULL), re-inserting\n");
                 Client *next_tiling;
                 SLIST_FOREACH(next_tiling, &(client->workspace->focus_stack), focus_clients)
-                        if (!next_tiling->floating)
+                        if (next_tiling->floating <= FLOATING_USER_OFF)
                                 break;
                 /* If there are no tiling clients on this workspace, there can only be one
                  * container: the first one */
@@ -60,7 +63,7 @@ void toggle_floating_mode(xcb_connection_t *conn, Client *client) {
                 /* Preserve position/size */
                 memcpy(&(client->floating_rect), &(client->rect), sizeof(Rect));
 
-                client->floating = false;
+                client->floating = FLOATING_USER_OFF;
                 client->container = con;
 
                 if (old_focused != NULL && !old_focused->dock)
@@ -88,7 +91,9 @@ void toggle_floating_mode(xcb_connection_t *conn, Client *client) {
                 con->currently_focused = get_last_focused_client(conn, con, NULL);
         }
 
-        client->floating = true;
+        if (automatic)
+                client->floating = FLOATING_AUTO_ON;
+        else client->floating = FLOATING_USER_ON;
 
         /* Initialize the floating position from the position in tiling mode, if this
          * client never was floating (width == 0) */
index 7682aaf0ecf5e2e81a60427e6329de9c10c07cba..0d828d2004a522bbfb88119945bdcc01ad198cbe 100644 (file)
@@ -336,7 +336,7 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
                 LOG("client. done.\n");
                 xcb_allow_events(conn, XCB_ALLOW_REPLAY_POINTER, event->time);
                 /* Floating clients should be raised on click */
-                if (client->floating)
+                if (client->floating >= FLOATING_AUTO_ON)
                         xcb_raise_window(conn, client->frame);
                 xcb_flush(conn);
                 return 1;
@@ -348,7 +348,7 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
                 LOG("click on titlebar\n");
 
                 /* Floating clients can be dragged by grabbing their titlebar */
-                if (client->floating) {
+                if (client->floating >= FLOATING_AUTO_ON) {
                         /* Firstly, we raise it. Maybe the user just wanted to raise it without grabbing */
                         uint32_t values[] = { XCB_STACK_MODE_ABOVE };
                         xcb_configure_window(conn, client->frame, XCB_CONFIG_WINDOW_STACK_MODE, values);
@@ -359,7 +359,7 @@ int handle_button_press(void *ignored, xcb_connection_t *conn, xcb_button_press_
                 return 1;
         }
 
-        if (client->floating)
+        if (client->floating >= FLOATING_AUTO_ON)
                 return floating_border_click(conn, client, event);
 
         if (event->event_y < 2) {
@@ -542,7 +542,7 @@ int handle_unmap_notify_event(void *data, xcb_connection_t *conn, xcb_unmap_noti
                 /* Only if this is the active container, we need to really change focus */
                 if ((con->currently_focused != NULL) && ((con == CUR_CELL) || client->fullscreen))
                         set_focus(conn, con->currently_focused, true);
-        } else if (client->floating) {
+        } else if (client->floating >= FLOATING_AUTO_ON) {
                 SLIST_REMOVE(&(client->workspace->focus_stack), client, Client, focus_clients);
         }
 
@@ -737,6 +737,17 @@ int handle_windowclass_change(void *data, xcb_connection_t *conn, uint8_t state,
         client->window_class = new_class;
         FREE(old_class);
 
+        if (!client->initialized) {
+                LOG("Client is not yet initialized, not putting it to floating\n");
+                return 1;
+        }
+
+        if (strcmp(new_class, "tools") == 0) {
+                LOG("tool window, should we put it floating?\n");
+                if (client->floating == FLOATING_AUTO_OFF)
+                        toggle_floating_mode(conn, client, true);
+        }
+
         return 1;
 }
 
index 060625d95d666a1dba2087254e4b6ddfe271c812..0085cdc4e8cb7344baa20b73618e5cc78b7931e1 100644 (file)
@@ -109,9 +109,9 @@ void decorate_window(xcb_connection_t *conn, Client *client, xcb_drawable_t draw
                 return;
 
         LOG("redecorating child %08x\n", client->child);
-        if (client->floating || client->container->currently_focused == client) {
+        if (client->floating >= FLOATING_AUTO_ON || client->container->currently_focused == client) {
                 /* Distinguish if the window is currently focused… */
-                if (client->floating || CUR_CELL->currently_focused == client)
+                if (client->floating >= FLOATING_AUTO_ON || CUR_CELL->currently_focused == client)
                         background_color = get_colorpixel(conn, config.client.focused.background);
                 /* …or if it is the focused window in a not focused container */
                 else background_color = get_colorpixel(conn, config.client.focused_inactive.background);
index 5e6e6eed58506bfe60bdfe8d927f9bced9070dbe..c87de57557abfe45cb51c469a4bbe1bec37085cb 100644 (file)
@@ -339,7 +339,7 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
                 /* Ensure that it is below all floating clients */
                 Client *first_floating;
                 SLIST_FOREACH(first_floating, &(new->container->workspace->focus_stack), focus_clients)
-                        if (first_floating->floating)
+                        if (first_floating->floating >= FLOATING_AUTO_ON)
                                 break;
 
                 if (first_floating != SLIST_END(&(new->container->workspace->focus_stack))) {
@@ -349,6 +349,8 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
                 }
         }
 
+        new->initialized = true;
+
         /* Check if the window already got the fullscreen hint set */
         xcb_atom_t *state;
         if ((preply = xcb_get_property_reply(conn, state_cookie, NULL)) != NULL &&
index 3cbb93d976e525cbc234608a95abb1ab2b46131f..40e39e84d61e19636b3eaebfa3448492e7fc4901 100644 (file)
@@ -264,7 +264,7 @@ void unmap_workspace(xcb_connection_t *conn, Workspace *u_ws) {
 
         /* To find floating clients, we traverse the focus stack */
         SLIST_FOREACH(client, &(u_ws->focus_stack), focus_clients) {
-                if (!client->floating)
+                if (client->floating <= FLOATING_USER_OFF)
                         continue;
 
                 xcb_unmap_window(conn, client->frame);