i3 - improved tiling WM


Bugfix: Handle nested transient popups properly

Patch status: merged

Patch by Mats

Long description:

During smart popup fullscreen handling, display all transient popups
that belong to the respective fullscreen application. A popup window
belongs to another window if the latter is reachable via the path
induced by the WM_TRANSIENT_FOR hints.

fixes #881

To apply this patch, use:
curl http://cr.i3wm.org/patch/53/raw.patch | git am

b/src/manage.c

20
@@ -385,10 +385,20 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
21
             con_toggle_fullscreen(fs, CF_OUTPUT);
22
         } else if (config.popup_during_fullscreen == PDF_SMART &&
23
                    fs != NULL &&
24
-                   fs->window != NULL &&
25
-                   fs->window->id == cwindow->transient_for) {
26
-            LOG("This floating window belongs to the fullscreen window (popup_during_fullscreen == smart)\n");
27
-            con_focus(nc);
28
+                   fs->window != NULL) {
29
+            i3Window *transient_win = cwindow;
30
+            while (transient_win != NULL &&
31
+                   transient_win->transient_for != XCB_NONE) {
32
+                if (transient_win->transient_for == fs->window->id) {
33
+                    LOG("This floating window belongs to the fullscreen window (popup_during_fullscreen == smart)\n");
34
+                    con_focus(nc);
35
+                    break;
36
+                }
37
+                Con *next_transient = con_by_window_id(transient_win->transient_for);
38
+                if (next_transient == NULL)
39
+                    break;
40
+                transient_win = next_transient->window;
41
+            }
42
         }
43
     }
44
 

b/src/render.c

49
@@ -271,18 +271,28 @@ void render_con(Con *con, bool render_fullscreen) {
50
                 /* Don’t render floating windows when there is a fullscreen window
51
                  * on that workspace. Necessary to make floating fullscreen work
52
                  * correctly (ticket #564). */
53
-                if (fullscreen != NULL) {
54
+                if (fullscreen != NULL && fullscreen->window != NULL) {
55
                     Con *floating_child = con_descend_focused(child);
56
+                    Con *transient_con = floating_child;
57
+                    bool is_transient_for = false;
58
                     /* Exception to the above rule: smart
59
                      * popup_during_fullscreen handling (popups belonging to
60
                      * the fullscreen app will be rendered). */
61
-                    if (floating_child->window == NULL ||
62
-                        fullscreen->window == NULL ||
63
-                        floating_child->window->transient_for != fullscreen->window->id)
64
+                    while (transient_con != NULL &&
65
+                           transient_con->window != NULL &&
66
+                           transient_con->window->transient_for != XCB_NONE) {
67
+                        if (transient_con->window->transient_for == fullscreen->window->id) {
68
+                            is_transient_for = true;
69
+                            break;
70
+                        }
71
+                        transient_con = con_by_window_id(transient_con->window->transient_for);
72
+                    }
73
+
74
+                    if (!is_transient_for)
75
                         continue;
76
                     else {
77
                         DLOG("Rendering floating child even though in fullscreen mode: "
78
-                             "floating->transient_for (0x%08x) == fullscreen->id (0x%08x)\n",
79
+                             "floating->transient_for (0x%08x) --> fullscreen->id (0x%08x)\n",
80
                              floating_child->window->transient_for, fullscreen->window->id);
81
                     }
82
                 }