]> git.sur5r.net Git - i3/i3/commitdiff
i3bar: suspend the child when bars are fully obscured
authorAlexander Monakov <amonakov@ispras.ru>
Thu, 8 Jan 2015 22:18:23 +0000 (01:18 +0300)
committerMichael Stapelberg <michael@stapelberg.de>
Sun, 25 Jan 2015 19:31:38 +0000 (20:31 +0100)
i3bar/include/outputs.h
i3bar/src/xcb.c

index e0beae89d6e2ef59bd6eff9bdbcae210881510aa..bd41e7767d247d3b75f1f014788f195008fdb4cd 100644 (file)
@@ -40,6 +40,7 @@ struct i3_output {
     char* name;   /* Name of the output */
     bool active;  /* If the output is active */
     bool primary; /* If it is the primary output */
+    bool visible; /* If the bar is visible on this output */
     int ws;       /* The number of the currently visible ws */
     rect rect;    /* The rect (relative to the root-win) */
 
index 179f8274b9f00871e66904ce8df52e0d7b0bbfb2..6f5f0ca2096c07c095ea769519c450b5649eaca3 100644 (file)
@@ -481,6 +481,39 @@ void handle_button(xcb_button_press_event_t *event) {
     free(buffer);
 }
 
+/*
+ * Handle visibility notifications: when none of the bars are visible, e.g.
+ * if windows are in full-screen on each output, suspend the child process.
+ *
+ */
+static void handle_visibility_notify(xcb_visibility_notify_event_t *event) {
+    bool visible = (event->state != XCB_VISIBILITY_FULLY_OBSCURED);
+    int num_visible = 0;
+    i3_output *output;
+
+    SLIST_FOREACH (output, outputs, slist) {
+        if (!output->active) {
+            continue;
+        }
+        if (output->bar == event->window) {
+            if (output->visible == visible) {
+                return;
+            }
+            output->visible = visible;
+        }
+        num_visible += output->visible;
+    }
+
+    if (num_visible == 0) {
+        stop_child();
+    } else if (num_visible == visible) {
+        /* Wake the child only when transitioning from 0 to 1 visible bar.
+         * We cannot transition from 0 to 2 or more visible bars at once since
+         * visibility events are delivered to each window separately */
+        cont_child();
+    }
+}
+
 /*
  * Adjusts the size of the tray window and alignment of the tray clients by
  * configuring their respective x coordinates. To be called when mapping or
@@ -945,6 +978,10 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) {
         }
 
         switch (type) {
+            case XCB_VISIBILITY_NOTIFY:
+                /* Visibility change: a bar is [un]obscured by other window */
+                handle_visibility_notify((xcb_visibility_notify_event_t *)event);
+                break;
             case XCB_EXPOSE:
                 /* Expose-events happen, when the window needs to be redrawn */
                 redraw_bars();
@@ -1461,6 +1498,12 @@ void reconfig_windows(bool redraw_bars) {
              * */
             values[2] = XCB_EVENT_MASK_EXPOSURE |
                         XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT;
+            if (config.hide_on_modifier == M_DOCK) {
+                /* If the bar is normally visible, catch visibility change events to suspend
+                 * the status process when the bar is obscured by full-screened windows.  */
+                values[2] |= XCB_EVENT_MASK_VISIBILITY_CHANGE;
+                walk->visible = true;
+            }
             if (!config.disable_ws) {
                 values[2] |= XCB_EVENT_MASK_BUTTON_PRESS;
             }