From ec9fbf05df3ac807d60ae6af36236ffc6567bbdc Mon Sep 17 00:00:00 2001 From: Geoffrey Antos Date: Sun, 5 Jul 2009 13:14:24 +0200 Subject: [PATCH] Fix interpretation of struts with multiple screens According to the WM Specification, the left, top, right, and bottom fields are to be declared relative to the overall X screen dimensions, not the monitor dimensions. The example given in the spec (v1.3 or 1.4draft2) is: "Another example is a panel on a screen using the Xinerama extension. Assume that the set up uses two monitors, one running at 1280x1024 and the other to the right running at 1024x768, with the top edge of the two physical displays aligned. If the panel wants to fill the entire bottom edge of the smaller display with a panel 50 pixels tall, it should set a bottom strut of 306, with bottom_start_x of 1280, and bottom_end_x of 2303. Note that the strut is relative to the screen edge, and not the edge of the xinerama monitor." In my case, I have a 1680x1050 monitor to the left of a 1920x1200 monitor aligned at the top. I then have a gnome-panel along the bottom edge of the 1680x1050 monitor with a height of 24 pixels. xprop reports the following partial strut: _NET_WM_STRUT_PARTIAL(CARDINAL) = 0, 0, 0, 175, 0, 0, 0, 0, 0, 0, 0, 1679 which is correct according to the spec. Gnome-panel is reserving the 150 pixels along the bottom that aren't visible on the screen plus the 25 it requests for itself. However, maximizing a window on this monitor leaves a gap of exactly 150 pixels between the bottom edge of the maximized window and the top edge of the panel. Also, when the 1680x1050 monitor is the primary monitor (id=1) then the _NET_WORKAREA property on the root window is also off by 150px for the same reason. This patch fixes the two issues I mentioned for exterior monitor edges. It doesn't attempt to account for "interior" monitor edges (i.e. a 'left' strut on monitor A when monitor B is directly to the left of monitor A) because it's not possible to do so with the current strut specification (see http://mail.gnome.org/archives/wm-spec-list/2004-March/msg00004.html for a discussion on this limitation) This could be avoided by having the partial strut atom contain a xinerama screen ID that the strut applies to, but unfortunately the discussion all those years ago never got anywhere. [ quoted from bug #3792 ] --- openbox/screen.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/openbox/screen.c b/openbox/screen.c index 4913b60..1bcda98 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -1459,6 +1459,15 @@ void screen_update_areas(void) b = MAX(b, s->strut->bottom); } + if (l) l += RECT_LEFT (monitor_area[screen_num_monitors]) + - RECT_LEFT (monitor_area[i]); + if (t) t += RECT_TOP (monitor_area[screen_num_monitors]) + - RECT_TOP (monitor_area[i]); + if (r) r -= RECT_RIGHT (monitor_area[screen_num_monitors]) + - RECT_RIGHT (monitor_area[i]); + if (b) b -= RECT_BOTTOM(monitor_area[screen_num_monitors]) + - RECT_BOTTOM(monitor_area[i]); + /* based on these margins, set the work area for the monitor/desktop */ dims[(i * screen_num_desktops + j) * 4 + 0] += l; @@ -1599,28 +1608,32 @@ Rect* screen_area(guint desktop, guint head, Rect *search) if ((s->desktop == d || s->desktop == DESKTOP_ALL) && STRUT_LEFT_IN_SEARCH(s->strut, search) && !STRUT_LEFT_IGNORE(s->strut, us, search)) - l = MAX(l, al + s->strut->left); + l = MAX(l, RECT_LEFT(monitor_area[screen_num_monitors]) + + s->strut->left); } for (it = struts_top; it; it = g_slist_next(it)) { ObScreenStrut *s = it->data; if ((s->desktop == d || s->desktop == DESKTOP_ALL) && STRUT_TOP_IN_SEARCH(s->strut, search) && !STRUT_TOP_IGNORE(s->strut, us, search)) - t = MAX(t, at + s->strut->top); + t = MAX(t, RECT_TOP(monitor_area[screen_num_monitors]) + + s->strut->top); } for (it = struts_right; it; it = g_slist_next(it)) { ObScreenStrut *s = it->data; if ((s->desktop == d || s->desktop == DESKTOP_ALL) && STRUT_RIGHT_IN_SEARCH(s->strut, search) && !STRUT_RIGHT_IGNORE(s->strut, us, search)) - r = MIN(r, ar - s->strut->right); + r = MIN(r, RECT_RIGHT(monitor_area[screen_num_monitors]) + - s->strut->right); } for (it = struts_bottom; it; it = g_slist_next(it)) { ObScreenStrut *s = it->data; if ((s->desktop == d || s->desktop == DESKTOP_ALL) && STRUT_BOTTOM_IN_SEARCH(s->strut, search) && !STRUT_BOTTOM_IGNORE(s->strut, us, search)) - b = MIN(b, ab - s->strut->bottom); + b = MIN(b, RECT_BOTTOM(monitor_area[screen_num_monitors]) + - s->strut->bottom); } /* limit to this monitor */ -- 1.9.1