With these two extra patches there should be no more drifting.
Exit Window Maker? No drifting.
Restart Window Maker? No drifting.
Start Window Maker on an unmanaged display? No drifting.
Toggle a window's border on or off in the inspector? No drifting.
Managing and unmanaging windows which already had borders? No
drifting.
Managing a previously maximised window? No drifting.
Also no overlapping titlebars on new windows.
From 0010a2395a68f7632c26f9ca46df7f48af33ba90 Mon Sep 17 00:00:00 2001
From: Iain Patterson <[email protected]>
Date: Fri, 16 Nov 2012 14:43:52 -0800
Subject: [PATCH 2/3] Fixed regression when placing windows.
The initial fix for the bug reported by Paul Seelig whereby windows
would drift on restart introduced two regressions.
New windows would place higher on the screen than intended, possibly
obscuring the bottoms of other windows with their titlebars, and all
windows would jump vertically at shutdown because we weren't restoring
them to where they were before they had a titlebar and border.
---
src/client.c | 7 +++++++
src/placement.c | 10 ++++++----
src/window.c | 5 +++--
3 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/client.c b/src/client.c
index 3287306..10f2571 100644
--- a/src/client.c
+++ b/src/client.c
@@ -81,6 +81,13 @@ void wClientRestore(WWindow * wwin)
if (gy > 0)
wwin->frame_y += (wwin->frame->top_width +
wwin->frame->bottom_width);
#endif
+ /* account for titlebar and border */
+ wwin->frame_y += wwin->frame->top_width;
+ if (HAS_BORDER(wwin)) {
+ wwin->frame_x += FRAME_BORDER_WIDTH;
+ wwin->frame_y += FRAME_BORDER_WIDTH;
+ }
+
XSetWindowBorderWidth(dpy, wwin->client_win, wwin->old_border_width);
XReparentWindow(dpy, wwin->client_win, wwin->screen_ptr->root_win,
wwin->frame_x, wwin->frame_y);
diff --git a/src/placement.c b/src/placement.c
index b30e0af..3d219d6 100644
--- a/src/placement.c
+++ b/src/placement.c
@@ -523,6 +523,7 @@ void PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
unsigned width, unsigned
WScreen *scr = wwin->screen_ptr;
int h = WMFontHeight(scr->title_font)
+ (wPreferences.window_title_clearance + TITLEBAR_EXTEND_SPACE)
* 2;
+ int border_width;
if (h > wPreferences.window_title_max_height)
h = wPreferences.window_title_max_height;
@@ -577,13 +578,14 @@ void PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
unsigned width, unsigned
* this will also take dock/clip etc.. into account
* aswell as being xinerama friendly
*/
- if (*x_ret + width > usableArea.x2)
- *x_ret = usableArea.x2 - width;
+ border_width = (HAS_BORDER(wwin)) ? 2 * FRAME_BORDER_WIDTH : 0;
+ if (*x_ret + border_width + width > usableArea.x2)
+ *x_ret = usableArea.x2 - border_width - width;
if (*x_ret < usableArea.x1)
*x_ret = usableArea.x1;
- if (*y_ret + height > usableArea.y2)
- *y_ret = usableArea.y2 - height;
+ if (*y_ret + border_width + height > usableArea.y2)
+ *y_ret = usableArea.y2 - border_width - height;
if (*y_ret < usableArea.y1)
*y_ret = usableArea.y1;
}
diff --git a/src/window.c b/src/window.c
index b07d9d4..7f0a1fe 100644
--- a/src/window.c
+++ b/src/window.c
@@ -591,6 +591,7 @@ WWindow *wManageWindow(WScreen *scr, Window window)
char *title;
Bool withdraw = False;
Bool raise = False;
+ Bool frame_adjustment = True;
/* mutex. */
XGrabServer(dpy);
@@ -994,6 +995,7 @@ WWindow *wManageWindow(WScreen *scr, Window window)
} else {
PlaceWindow(wwin, &x, &y, width, height);
+ frame_adjustment = False;
}
if (wPreferences.window_placement == WPM_MANUAL) {
dontBring = True;
@@ -1144,7 +1146,7 @@ WWindow *wManageWindow(WScreen *scr, Window window)
y -= wwin->frame->top_width + wwin->frame->bottom_width;
}
- {
+ if (frame_adjustment) {
WMRect rect;
WArea usableArea;
int head;
@@ -1161,7 +1163,6 @@ WWindow *wManageWindow(WScreen *scr, Window window)
* when placing so the window would be shifted without
* the adjustment below
*/
-
if (y >= usableArea.y1 + wwin->frame->top_width)
y -= wwin->frame->top_width;
--
1.7.11.4
From ec5dc11759b505893b98651fe9384bcae83e71d3 Mon Sep 17 00:00:00 2001
From: Iain Patterson <[email protected]>
Date: Fri, 16 Nov 2012 16:00:07 -0800
Subject: [PATCH 3/3] Prevent border drifting.
Windows were drifting by FRAME_BORDER_WIDTH pixels when their
borders were toggled on or off.
Windows which had a border before we managed them were drifting
on shutdown and again at startup. It happened because the absolute
upper-left co-ordinates of a bordered window would in fact be the
upper-left co-ordinates of the border itself, whereas we consider
the client window to have no border and co-ordinates offset by the
titlebar and frame border.
---
src/client.c | 2 ++
src/window.c | 27 ++++++++++++++++++++++-----
2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/src/client.c b/src/client.c
index 10f2571..89f6277 100644
--- a/src/client.c
+++ b/src/client.c
@@ -83,6 +83,8 @@ void wClientRestore(WWindow * wwin)
#endif
/* account for titlebar and border */
wwin->frame_y += wwin->frame->top_width;
+ wwin->frame_x -= wwin->old_border_width;
+ wwin->frame_y -= wwin->old_border_width;
if (HAS_BORDER(wwin)) {
wwin->frame_x += FRAME_BORDER_WIDTH;
wwin->frame_y += FRAME_BORDER_WIDTH;
diff --git a/src/window.c b/src/window.c
index 7f0a1fe..551cc21 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1178,6 +1178,17 @@ WWindow *wManageWindow(WScreen *scr, Window window)
}
}
+ /* If this is a newly-mapped window which had a border,
+ * the absolute co-ordinates reported to us are actually
+ * the co-ordinates of the border. We, however, track
+ * the absolute co-ordinates of the client window, offset
+ * by the title bar and frame border. As a result
+ * we need to offset placement of the client by the border
+ * size so its position matches what we expect.
+ */
+ x += wwin->old_border_width;
+ y += wwin->old_border_width;
+
/*
* wWindowConfigure() will init the client window's size
* (wwin->client.{width,height}) and all other geometry
@@ -2226,7 +2237,9 @@ void wWindowConfigureBorders(WWindow *wwin)
{
if (wwin->frame) {
int flags;
- int newy, oldh;
+ int newx, newy, oldh;
+ int border_width;
+ XWindowAttributes attr;
flags = WFF_LEFT_BUTTON | WFF_RIGHT_BUTTON;
@@ -2244,13 +2257,17 @@ void wWindowConfigureBorders(WWindow *wwin)
if (wwin->flags.shaded)
flags |= WFF_IS_SHADED;
- oldh = wwin->frame->top_width;
+ if (!XGetWindowAttributes(dpy, wwin->frame->core->window,
&attr))
+ attr.border_width = 0;
+ border_width = (flags & WFF_BORDER) ? FRAME_BORDER_WIDTH : 0;
+ oldh = wwin->frame->top_width + attr.border_width;
wFrameWindowUpdateBorders(wwin->frame, flags);
- if (oldh != wwin->frame->top_width) {
- newy = wwin->frame_y + oldh - wwin->frame->top_width;
+ if (oldh != wwin->frame->top_width + border_width) {
+ newx = wwin->frame_x + attr.border_width - border_width;
+ newy = wwin->frame_y + oldh - border_width -
wwin->frame->top_width;
XMoveWindow(dpy, wwin->client_win, 0,
wwin->frame->top_width);
- wWindowConfigure(wwin, wwin->frame_x, newy,
wwin->client.width, wwin->client.height);
+ wWindowConfigure(wwin, newx, newy, wwin->client.width,
wwin->client.height);
}
flags = 0;
--
1.7.11.4