]> git.sur5r.net Git - i3/i3/commitdiff
Render tree before destroying X11 containers upon unmap (Thanks Merovius)
authorMichael Stapelberg <michael@stapelberg.de>
Sun, 23 Dec 2012 14:54:49 +0000 (15:54 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Sun, 23 Dec 2012 14:54:49 +0000 (15:54 +0100)
When an X11 window is closed (say, urxvt), i3 gets an UnmapNotify event
and destroys (DestroyWindow) the window decorations. Before this commit,
the DestroyWindow call was sent immediately.

This lead to a situation where — due to the DestroyNotify — EnterNotify
events were generated that would cause the focus to be set to the
underlying window.

With this commit, i3 first renders the tree and pushes changes to X11
before calling DestroyWindow. Therefore, the surrounding containers will
take up any space that was freed by the window which was closed and no
EnterNotify will be generated.

fixes #660

src/tree.c

index 7a5fb9f010081c7a24f28fbac1673b0471a4583b..c90f58f181724b1d4b7a73678c7da6bdb3e3f77e 100644 (file)
@@ -251,15 +251,29 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool
         free(con->window);
     }
 
-    /* kill the X11 part of this container */
-    x_con_kill(con);
+    Con *ws = con_get_workspace(con);
+
+    /* Figure out which container to focus next before detaching 'con'. */
+    if (con_is_floating(con)) {
+        if (con == focused) {
+            DLOG("This is the focused container, i need to find another one to focus. I start looking at ws = %p\n", ws);
+            /* go down the focus stack as far as possible */
+            next = con_next_focused(con);
+
+            dont_kill_parent = true;
+            DLOG("Alright, focusing %p\n", next);
+        } else {
+            next = NULL;
+        }
+    }
 
+    /* Detach the container so that it will not be rendered anymore. */
     con_detach(con);
 
     /* disable urgency timer, if needed */
     if (con->urgency_timer != NULL) {
         DLOG("Removing urgency timer of con %p\n", con);
-        workspace_update_urgent_flag(con_get_workspace(con));
+        workspace_update_urgent_flag(ws);
         ev_timer_stop(main_loop, con->urgency_timer);
         FREE(con->urgency_timer);
     }
@@ -270,21 +284,24 @@ bool tree_close(Con *con, kill_window_t kill_window, bool dont_kill_parent, bool
         con_fix_percent(parent);
     }
 
+    /* Render the tree so that the surrounding containers take up the space
+     * which 'con' does no longer occupy. If we don’t render here, there will
+     * be a gap in our containers and that could trigger an EnterNotify for an
+     * underlying container, see ticket #660.
+     *
+     * Rendering has to be avoided when dont_kill_parent is set (when
+     * tree_close calls itself recursively) because the tree is in a
+     * non-renderable state during that time. */
+    if (!dont_kill_parent)
+        tree_render();
+
+    /* kill the X11 part of this container */
+    x_con_kill(con);
+
     if (con_is_floating(con)) {
-        Con *ws = con_get_workspace(con);
         DLOG("Container was floating, killing floating container\n");
         tree_close(parent, DONT_KILL_WINDOW, false, (con == focused));
         DLOG("parent container killed\n");
-        if (con == focused) {
-            DLOG("This is the focused container, i need to find another one to focus. I start looking at ws = %p\n", ws);
-            /* go down the focus stack as far as possible */
-            next = con_descend_focused(ws);
-
-            dont_kill_parent = true;
-            DLOG("Alright, focusing %p\n", next);
-        } else {
-            next = NULL;
-        }
     }
 
     free(con->name);