i3bar: suspend the child when bars are fully obscured
Patch status: needinfo
Patch by Alexander Monakov
To apply this patch, use:
curl http://cr.i3wm.org/patch/701/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,37 @@ 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 |
+ cont_child(); |
| 57 |
+ } |
| 58 |
+} |
| 59 |
+ |
| 60 |
+/* |
| 61 |
* Adjusts the size of the tray window and alignment of the tray clients by |
| 62 |
* configuring their respective x coordinates. To be called when mapping or |
| 63 |
* unmapping a tray client window. |
| 64 |
@@ -945,6 +976,10 @@ void xcb_chk_cb(struct ev_loop *loop, ev_check *watcher, int revents) {
|
| 65 |
} |
| 66 |
|
| 67 |
switch (type) {
|
| 68 |
+ case XCB_VISIBILITY_NOTIFY: |
| 69 |
+ /* Visibility change: a bar is [un]obscured by other window */ |
| 70 |
+ handle_visibility_notify((xcb_visibility_notify_event_t *)event); |
| 71 |
+ break; |
| 72 |
case XCB_EXPOSE: |
| 73 |
/* Expose-events happen, when the window needs to be redrawn */ |
| 74 |
redraw_bars(); |
| 75 |
@@ -1461,6 +1496,12 @@ void reconfig_windows(bool redraw_bars) {
|
| 76 |
* */ |
| 77 |
values[2] = XCB_EVENT_MASK_EXPOSURE | |
| 78 |
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; |
| 79 |
+ if (config.hide_on_modifier == M_DOCK) {
|
| 80 |
+ /* If the bar is normally visible, catch visibility change events to suspend |
| 81 |
+ * the status process when the bar is obscured by full-screened windows. */ |
| 82 |
+ values[2] |= XCB_EVENT_MASK_VISIBILITY_CHANGE; |
| 83 |
+ walk->visible = true; |
| 84 |
+ } |
| 85 |
if (!config.disable_ws) {
|
| 86 |
values[2] |= XCB_EVENT_MASK_BUTTON_PRESS; |
| 87 |
} |