i3 - improved tiling WM


i3bar: suspend the child when bars are fully obscured

Patch status: merged

Patch by Alexander Monakov

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

b/i3bar/include/outputs.h

14
@@ -40,6 +40,7 @@ struct i3_output {
15
     char* name;   /* Name of the output */
16
     bool active;  /* If the output is active */
17
     bool primary; /* If it is the primary output */
18
+    bool visible; /* If the bar is visible on this output */
19
     int ws;       /* The number of the currently visible ws */
20
     rect rect;    /* The rect (relative to the root-win) */
21
 

b/i3bar/src/xcb.c

26
@@ -482,6 +482,39 @@ void handle_button(xcb_button_press_event_t *event) {
27
 }
28
 
29
 /*
30
+ * Handle visibility notifications: when none of the bars are visible, e.g.
31
+ * if windows are in full-screen on each output, suspend the child process.
32
+ *
33
+ */
34
+static void handle_visibility_notify(xcb_visibility_notify_event_t *event) {
35
+    bool visible = (event->state != XCB_VISIBILITY_FULLY_OBSCURED);
36
+    int num_visible = 0;
37
+    i3_output *output;
38
+
39
+    SLIST_FOREACH (output, outputs, slist) {
40
+        if (!output->active) {
41
+            continue;
42
+        }
43
+        if (output->bar == event->window) {
44
+            if (output->visible == visible) {
45
+                return;
46
+            }
47
+            output->visible = visible;
48
+        }
49
+        num_visible += output->visible;
50
+    }
51
+
52
+    if (num_visible == 0) {
53
+        stop_child();
54
+    } else if (num_visible == visible) {
55
+        /* Wake the child only when transitioning from 0 to 1 visible bar.
56
+         * We cannot transition from 0 to 2 or more visible bars at once since
57
+         * visibility events are delivered to each window separately */
58
+        cont_child();
59
+    }
60
+}
61
+
62
+/*
63
  * Adjusts the size of the tray window and alignment of the tray clients by
64
  * configuring their respective x coordinates. To be called when mapping or
65
  * unmapping a tray client window.
66
@@ -945,6 +978,10 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) {
67
         }
68
 
69
         switch (type) {
70
+            case XCB_VISIBILITY_NOTIFY:
71
+                /* Visibility change: a bar is [un]obscured by other window */
72
+                handle_visibility_notify((xcb_visibility_notify_event_t *)event);
73
+                break;
74
             case XCB_EXPOSE:
75
                 /* Expose-events happen, when the window needs to be redrawn */
76
                 redraw_bars();
77
@@ -1461,6 +1498,12 @@ void reconfig_windows(bool redraw_bars) {
78
              * */
79
             values[2] = XCB_EVENT_MASK_EXPOSURE |
80
                         XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
81
+            if (config.hide_on_modifier == M_DOCK) {
82
+                /* If the bar is normally visible, catch visibility change events to suspend
83
+                 * the status process when the bar is obscured by full-screened windows.  */
84
+                values[2] |= XCB_EVENT_MASK_VISIBILITY_CHANGE;
85
+                walk->visible = true;
86
+            }
87
             if (!config.disable_ws) {
88
                 values[2] |= XCB_EVENT_MASK_BUTTON_PRESS;
89
             }