i3 - improved tiling WM


Bugfix: Handle nested transient popups properly

Patch status: needinfo

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/12/raw.patch | git am

b/src/manage.c

20
@@ -353,10 +353,19 @@ 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
+                    transient_win = next_transient->window;
40
+            }
41
         }
42
     }
43
 

b/src/render.c

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