Awesome seems to handle all window gravity values correctly when the window is mapped the first time. However, if a program which uses StaticGravity (or any other gravity except NorthWestGravity) unmaps its window and then maps it again, the window moves from the position where it was placed initially.
Tested with:
awesome v4.2-345-g94d3918d (Human after all)
• Compiled against Lua 5.3.5 (running with Lua 5.3)
• D-Bus support: ✔
• execinfo support: ✔
• xcb-randr version: 1.6
• LGI version: 0.9.2
How to reproduce the issue:
placement from window rules, so that Awesome would always honor the client-specified window geometry.gcc -o map_unmap_test -g -O2 -Wall -W map_unmap_test.c -lX11) and run the following test program:#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
int main(void)
{
Display *dpy;
Window win;
XSetWindowAttributes win_attrs;
XSizeHints *size_hints;
int i;
dpy = XOpenDisplay(getenv("DISPLAY"));
win = XCreateWindow(dpy, DefaultRootWindow(dpy), 100, 100, 100, 100,
0, CopyFromParent, InputOutput, CopyFromParent,
0, &win_attrs);
size_hints = XAllocSizeHints();
size_hints->flags = USPosition | USSize | PWinGravity;
size_hints->win_gravity = StaticGravity;
XSetWMNormalHints(dpy, win, size_hints);
XFree(size_hints);
for (i = 0; i < 5; ++i) {
XMapWindow(dpy, win);
XSync(dpy, True);
sleep(1);
XUnmapWindow(dpy, win);
XSync(dpy, True);
sleep(1);
}
return 0;
}
Expected result:
A 100Ă—100 window should appear, the top left corner of the client area should be placed at (100, 100); the window should flash 5 times, but remain at the same position.
Actual result:
The window initially appears at (100, 100), but after every unmap and map the window position shifts up (by border_width+titlebar.height) and to the left (by border_width).
The real world case when this problem appears is https://github.com/telegramdesktop/tdesktop/issues/4837 (that report is for a different window manager, but the problem is apparenty the same — telegram-desktop sets StaticGravity for its window, and the “minimize to tray” action unmaps the window, then restoring just maps that window again).
I have found a Lua-level workaround for this problem — remove titlebars and border in the "unmanage" callback:
client.connect_signal("unmanage", function (c)
awful.titlebar.hide(c, "top")
awful.titlebar.hide(c, "left")
awful.titlebar.hide(c, "right")
awful.titlebar.hide(c, "bottom")
c.border_width = 0
end)
Thanks for this great bug report!
I guess (no time to test currently, sorry), that something similar would happen when restarting awesome. In both awesome_atexit and client_unmanage, we reparent the window back to the root window at position (c->geometry.x, c->geometry.y). Another guess: This position has to be corrected for the (inverse) gravity.
Untested tentative patch (that only handles the unmanage case, not the exit):
diff --git a/objects/client.c b/objects/client.c
index c7a0c8e8..5771e3a9 100644
--- a/objects/client.c
+++ b/objects/client.c
@@ -2208,9 +2214,26 @@ client_unmanage(client_t *c, bool window_valid)
if(window_valid)
{
+ int16_t x = c->geometry.x;
+ int16_t y = c->geometry.y;
+
+ /* Move the window inversely for its gravity */
+ if(c->size_hints.flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY)
+ {
+ int16_t diff_x = 0, diff_y = 0;
+ uint16_t bw = c->border_width;
+ xwindow_translate_for_gravity(c->size_hints.win_gravity,
+ bw + c->titlebar[CLIENT_TITLEBAR_LEFT].size,
+ bw + c->titlebar[CLIENT_TITLEBAR_TOP].size,
+ bw + c->titlebar[CLIENT_TITLEBAR_RIGHT].size,
+ bw + c->titlebar[CLIENT_TITLEBAR_BOTTOM].size,
+ &diff_x, &diff_y);
+ x -= diff_x;
+ y -= diff_y;
+ }
+
xcb_unmap_window(globalconf.connection, c->window);
- xcb_reparent_window(globalconf.connection, c->window, globalconf.screen->root,
- c->geometry.x, c->geometry.y);
+ xcb_reparent_window(globalconf.connection, c->window, globalconf.screen->root, x, y);
}
if (c->nofocus_window != XCB_NONE)
(I guess this reparent-back-to-root-window should be moved into a common helper function used by both client_unmanage and awesome_atexit...)
Untested tentative patch (that only handles the unmanage case, not the exit):
Tested this patch — it works exactly as expected: the problem with unmap/map is fixed both for my test program and for telegram-desktop. So the only remaining part is to fix the exit case (I did not notice that in my testing, but now I see that restarting Awesome causes the telegram-desktop window to shift up and to the left).
Thanks for testing. I'll move this code for reparenting based on the "inverse gravity"'d position into a helper function and call it from both necessary places. Also, I think I should include your test program into the test suite (but that will require replacing the sleep with something more complicated so that the test does not run 10 seconds).
I might have some time for that on the coming weekend, but I also might not. We will see.
Thanks again for this great bug report and for testing my quickly hacked together patch.
Any timeline on when this will come into awesomewm, as I also have the same issue.
Current state is "this breaks some tests on Travis, but I cannot reproduce locally and have no idea what is going on". Sorry.
WRT reproducing, I have two different monitors - one at home and one at work and when I autolaunch applications in rc.lua then I see this happening.. not sure if it will help in your case of reproducing.
Most helpful comment
Thanks for testing. I'll move this code for reparenting based on the "inverse gravity"'d position into a helper function and call it from both necessary places. Also, I think I should include your test program into the test suite (but that will require replacing the sleep with something more complicated so that the test does not run 10 seconds).
I might have some time for that on the coming weekend, but I also might not. We will see.
Thanks again for this great bug report and for testing my quickly hacked together patch.