diff options
Diffstat (limited to 'src/sxwm.c')
| -rw-r--r-- | src/sxwm.c | 154 |
1 files changed, 132 insertions, 22 deletions
@@ -3193,17 +3193,25 @@ void update_struts(void) { /* reset all reserves */ for (int i = 0; i < n_mons; i++) { - mons[i].reserve_left = mons[i].reserve_right = mons[i].reserve_top = mons[i].reserve_bottom = 0; + mons[i].reserve_left = 0; + mons[i].reserve_right = 0; + mons[i].reserve_top = 0; + mons[i].reserve_bottom = 0; } - Window root_ret, parent_ret, *children; - unsigned int nchildren; + Window root_ret; + Window parent_ret; + Window *children = NULL; + unsigned int n_children = 0; - if (!XQueryTree(dpy, root, &root_ret, &parent_ret, &children, &nchildren)) { + if (!XQueryTree(dpy, root, &root_ret, &parent_ret, &children, &n_children)) { return; } - for (unsigned int i = 0; i < nchildren; i++) { + int screen_w = scr_width; + int screen_h = scr_height; + + for (unsigned int i = 0; i < n_children; i++) { Window w = children[i]; Atom actual_type; @@ -3211,8 +3219,9 @@ void update_struts(void) unsigned long n_items, bytes_after; Atom *types = NULL; - if (XGetWindowProperty(dpy, w, _NET_WM_WINDOW_TYPE, 0, 4, False, XA_ATOM, &actual_type, &actual_format, - &n_items, &bytes_after, (unsigned char **)&types) != Success || !types) { + if (XGetWindowProperty(dpy, w, _NET_WM_WINDOW_TYPE, 0, 4, False, XA_ATOM, + &actual_type, &actual_format, &n_items, &bytes_after, + (unsigned char **)&types) != Success || !types) { continue; } @@ -3231,27 +3240,128 @@ void update_struts(void) long *str = NULL; Atom actual; int sfmt; - unsigned long len, rem; + unsigned long len; + unsigned long rem; + + if (XGetWindowProperty(dpy, w, _NET_WM_STRUT_PARTIAL, 0, 12, False, XA_CARDINAL, + &actual, &sfmt, &len, &rem, + (unsigned char **)&str) == Success && str && len >= 12) { + + /* + ewmh: + [0] left, [1] right, [2] top, [3] bottom + + [4] left_start_y, [5] left_end_y + [6] right_start_y, [7] right_end_y + [8] top_start_x, [9] top_end_x + [10] bottom_start_x,[11] bottom_end_x + + all coords are in root space. + */ + long left = str[0]; + long right = str[1]; + long top = str[2]; + long bottom = str[3]; + long left_start_y = str[4]; + long left_end_y = str[5]; + long right_start_y = str[6]; + long right_end_y = str[7]; + long top_start_x = str[8]; + long top_end_x = str[9]; + long bot_start_x = str[10]; + long bot_end_x = str[11]; - if (XGetWindowProperty(dpy, w, _NET_WM_STRUT_PARTIAL, 0, 12, False, XA_CARDINAL, &actual, &sfmt, &len, &rem, - (unsigned char **)&str) == Success && str && len >= 4) { - XWindowAttributes wa; - if (XGetWindowAttributes(dpy, w, &wa)) { - /* find the monitor this dock belongs to */ - for (int m = 0; m < n_mons; m++) { - if (wa.x >= mons[m].x && wa.x < mons[m].x + mons[m].w && wa.y >= mons[m].y && - wa.y < mons[m].y + mons[m].h) { - mons[m].reserve_left = MAX(mons[m].reserve_left, str[0]); - mons[m].reserve_right = MAX(mons[m].reserve_right, str[1]); - mons[m].reserve_top = MAX(mons[m].reserve_top, str[2]); - mons[m].reserve_bottom = MAX(mons[m].reserve_bottom, str[3]); + XFree(str); + + /* skip empty struts */ + if (!left && !right && !top && !bottom) { + continue; + } + + for (int m = 0; m < n_mons; m++) { + int mx = mons[m].x; + int my = mons[m].y; + int mw = mons[m].w; + int mh = mons[m].h; + + /* strip monitors whose vertical span dostn intersect */ + if (left > 0) { + long span_start = left_start_y; + long span_end = left_end_y; + if (span_end >= my && span_start <= my + mh - 1) { + /* + left is distance from root left edge to reserved area + to map to mon, the portion is: + reserve_left = MAX(0, left - mx) + */ + int reserve = (int)MAX(0, left - mx); + if (reserve > 0) { + mons[m].reserve_left = MAX(mons[m].reserve_left, reserve); + } + } + } + + if (right > 0) { + long span_start = right_start_y; + long span_end = right_end_y; + if (span_end >= my && span_start <= my + mh - 1) { + /* + right is distance from root right edge to reserved area: + right edge = screen_w + mons right edge = mx + mw + amount that cuts into monitor = MAX(0, (screen_w - right) - mx) + */ + int global_reserved_left = screen_w - (int)right; + int overlap = (mx + mw) - global_reserved_left; + int reserve = MAX(0, overlap); + if (reserve > 0) { + mons[m].reserve_right = MAX(mons[m].reserve_right, reserve); + } + } + } + + if (top > 0) { + long span_start = top_start_x; + long span_end = top_end_x; + if (span_end >= mx && span_start <= mx + mw - 1) { + /* + top is distance from root top to reserved area + mons top is at my, amount eaten: + reserve_top = MAX(0, top - my) + */ + int reserve = (int)MAX(0, top - my); + if (reserve > 0) { + mons[m].reserve_top = MAX(mons[m].reserve_top, reserve); + } + } + } + + if (bottom > 0) { + long span_start = bot_start_x; + long span_end = bot_end_x; + if (span_end >= mx && span_start <= mx + mw - 1) { + /* + bottom is distance from root bottom to reserved area + global_reserved_top = screen_h - bottom; + overlap to mon: + overlap = (my + mh) - global_reserved_top; + reserve_bottom = MAX(0, overlap) + */ + int global_reserved_top = screen_h - (int)bottom; + int overlap = (my + mh) - global_reserved_top; + int reserve = MAX(0, overlap); + if (reserve > 0) { + mons[m].reserve_bottom = MAX(mons[m].reserve_bottom, reserve); + } } } } - XFree(str); } } - XFree(children); + + if (children) { + XFree(children); + } update_workarea(); } |
