Relocate a client window as if it is undecorated when reparenting it back. It eliminates the position offset due to re-decorating when a client trys to restore its previous position. (#3253)
Add tests for geometry changes when managing/unmanaging clients. Also verified that it fixed issue #2308.
This commit is contained in:
parent
cd4008c249
commit
ab6f7e03ca
|
@ -111,8 +111,9 @@ awesome_atexit(bool restart)
|
||||||
/* Move clients where we want them to be and keep the stacking order intact */
|
/* Move clients where we want them to be and keep the stacking order intact */
|
||||||
foreach(c, globalconf.stack)
|
foreach(c, globalconf.stack)
|
||||||
{
|
{
|
||||||
|
area_t geometry = client_get_undecorated_geometry(*c);
|
||||||
xcb_reparent_window(globalconf.connection, (*c)->window, globalconf.screen->root,
|
xcb_reparent_window(globalconf.connection, (*c)->window, globalconf.screen->root,
|
||||||
(*c)->geometry.x, (*c)->geometry.y);
|
geometry.x, geometry.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the client order. This is useful also for "hard" restarts. */
|
/* Save the client order. This is useful also for "hard" restarts. */
|
||||||
|
|
|
@ -2267,6 +2267,27 @@ client_add_titlebar_geometry(client_t *c, area_t *geometry)
|
||||||
geometry->height += c->titlebar[CLIENT_TITLEBAR_BOTTOM].size;
|
geometry->height += c->titlebar[CLIENT_TITLEBAR_BOTTOM].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
area_t
|
||||||
|
client_get_undecorated_geometry(client_t *c)
|
||||||
|
{
|
||||||
|
area_t geometry = c->geometry;
|
||||||
|
if (!c->fullscreen) {
|
||||||
|
int diff_left = c->titlebar[CLIENT_TITLEBAR_LEFT].size;
|
||||||
|
int diff_right = c->titlebar[CLIENT_TITLEBAR_RIGHT].size;
|
||||||
|
int diff_top = c->titlebar[CLIENT_TITLEBAR_TOP].size;
|
||||||
|
int diff_bottom = c->titlebar[CLIENT_TITLEBAR_BOTTOM].size;
|
||||||
|
geometry.width -= diff_left + diff_right;
|
||||||
|
geometry.height -= diff_top + diff_bottom;
|
||||||
|
if (c->size_hints.flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY) {
|
||||||
|
xwindow_translate_for_gravity(c->size_hints.win_gravity,
|
||||||
|
-diff_left - c->border_width, -diff_top - c->border_width,
|
||||||
|
-diff_right - c->border_width, -diff_bottom - c->border_width,
|
||||||
|
&geometry.x, &geometry.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return geometry;
|
||||||
|
}
|
||||||
|
|
||||||
/** Send a synthetic configure event to a window.
|
/** Send a synthetic configure event to a window.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
@ -2941,9 +2962,10 @@ client_unmanage(client_t *c, client_unmanage_t reason)
|
||||||
|
|
||||||
if(reason != CLIENT_UNMANAGE_DESTROYED)
|
if(reason != CLIENT_UNMANAGE_DESTROYED)
|
||||||
{
|
{
|
||||||
|
area_t geometry = client_get_undecorated_geometry(c);
|
||||||
xcb_unmap_window(globalconf.connection, c->window);
|
xcb_unmap_window(globalconf.connection, c->window);
|
||||||
xcb_reparent_window(globalconf.connection, c->window, globalconf.screen->root,
|
xcb_reparent_window(globalconf.connection, c->window, globalconf.screen->root,
|
||||||
c->geometry.x, c->geometry.y);
|
geometry.x, geometry.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->nofocus_window != XCB_NONE)
|
if (c->nofocus_window != XCB_NONE)
|
||||||
|
|
|
@ -256,6 +256,7 @@ void client_emit_scanned(void);
|
||||||
void client_emit_scanning(void);
|
void client_emit_scanning(void);
|
||||||
drawable_t *client_get_drawable(client_t *, int, int);
|
drawable_t *client_get_drawable(client_t *, int, int);
|
||||||
drawable_t *client_get_drawable_offset(client_t *, int *, int *);
|
drawable_t *client_get_drawable_offset(client_t *, int *, int *);
|
||||||
|
area_t client_get_undecorated_geometry(client_t *);
|
||||||
|
|
||||||
/** Put client on top of the stack.
|
/** Put client on top of the stack.
|
||||||
* \param c The client to raise.
|
* \param c The client to raise.
|
||||||
|
|
|
@ -6,9 +6,13 @@ local wibox = require( "wibox" )
|
||||||
local beautiful = require( "beautiful" )
|
local beautiful = require( "beautiful" )
|
||||||
local cruled = require("ruled.client")
|
local cruled = require("ruled.client")
|
||||||
local gdebug = require("gears.debug")
|
local gdebug = require("gears.debug")
|
||||||
|
local test_client = require("_client")
|
||||||
|
local lgi = require("lgi")
|
||||||
|
local gears = require("gears")
|
||||||
|
|
||||||
local w = nil
|
local w = nil
|
||||||
local w1_draw, w2_draw
|
local w1_draw, w2_draw
|
||||||
|
local windowid
|
||||||
|
|
||||||
-- Replacing the rules is not supported anymore.
|
-- Replacing the rules is not supported anymore.
|
||||||
local dep = gdebug.deprecate
|
local dep = gdebug.deprecate
|
||||||
|
@ -257,6 +261,113 @@ local steps = {
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
runner.run_steps(steps)
|
-- Tests for unmanaged client geometries with different gravity settings.
|
||||||
|
local test_data = {
|
||||||
|
-- gravity => expectation of unmanaged x, y, w, h.
|
||||||
|
["NORTH_WEST"] = {0, 0, 100, 80},
|
||||||
|
["NORTH"] = {10, 0, 100, 80},
|
||||||
|
["NORTH_EAST"] = {20, 0, 100, 80},
|
||||||
|
["WEST"] = {0, 20, 100, 80},
|
||||||
|
["CENTER"] = {10, 20, 100, 80},
|
||||||
|
["EAST"] = {20, 20, 100, 80},
|
||||||
|
["SOUTH_WEST"] = {0, 40, 100, 80},
|
||||||
|
["SOUTH"] = {10, 40, 100, 80},
|
||||||
|
["SOUTH_EAST"] = {20, 40, 100, 80},
|
||||||
|
["STATIC"] = {10, 30, 100, 80}
|
||||||
|
}
|
||||||
|
for gravity, expectation in pairs(test_data) do
|
||||||
|
gears.table.merge(steps, {
|
||||||
|
function()
|
||||||
|
set_rules { }
|
||||||
|
-- Wait for the previous cleanup to be done
|
||||||
|
if #client.get() == 0 then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
function(count)
|
||||||
|
if count == 1 then
|
||||||
|
print("testing gravity " .. gravity)
|
||||||
|
test_client(nil,nil,nil,nil,nil,{gravity=lgi.Gdk.Gravity[gravity]})
|
||||||
|
else
|
||||||
|
local c = client.get()[1]
|
||||||
|
if c then
|
||||||
|
assert(c.size_hints.win_gravity == gravity:lower())
|
||||||
|
c.border_width = 10
|
||||||
|
c:titlebar_top(20)
|
||||||
|
c:geometry({
|
||||||
|
x = 0,
|
||||||
|
y = 0,
|
||||||
|
width = 100,
|
||||||
|
height = 100
|
||||||
|
})
|
||||||
|
windowid = c.window
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
-- For some reason unmanage needs to happen in a separate step to pass the tests..
|
||||||
|
function()
|
||||||
|
local c = client.get()[1]
|
||||||
|
c:unmanage()
|
||||||
|
awesome.sync()
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
local display = lgi.Gdk.Display.open(os.getenv("DISPLAY"))
|
||||||
|
local window = lgi.GdkX11.X11Window.foreign_new_for_display(display, windowid)
|
||||||
|
local x, y, width, height = window:get_geometry()
|
||||||
|
print(gravity, x, y, width, height)
|
||||||
|
assert(x == expectation[1])
|
||||||
|
assert(y == expectation[2])
|
||||||
|
assert(width == expectation[3])
|
||||||
|
assert(height == expectation[4])
|
||||||
|
window:destroy()
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
local display = lgi.Gdk.Display.open(os.getenv("DISPLAY"))
|
||||||
|
local window = lgi.GdkX11.X11Window.foreign_new_for_display(display, windowid)
|
||||||
|
if window then return end
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
-- Additionally, checks our expectations are correct by adding decoration back.
|
||||||
|
function(count)
|
||||||
|
if count == 1 then
|
||||||
|
test_client(nil,nil,nil,nil,nil,{gravity=lgi.Gdk.Gravity[gravity]})
|
||||||
|
else
|
||||||
|
local c = client.get()[1]
|
||||||
|
if c then
|
||||||
|
assert(c.size_hints.win_gravity == gravity:lower())
|
||||||
|
c.border_width = 0
|
||||||
|
c:titlebar_top(0)
|
||||||
|
c:geometry({
|
||||||
|
x = expectation[1],
|
||||||
|
y = expectation[2],
|
||||||
|
width = expectation[3],
|
||||||
|
height = expectation[4]
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
local c = client.get()[1]
|
||||||
|
c:titlebar_top(20)
|
||||||
|
c.border_width = 10
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
function()
|
||||||
|
local c = client.get()[1]
|
||||||
|
assert(c.border_width == 10 )
|
||||||
|
assert(c:geometry().x == 0 )
|
||||||
|
assert(c:geometry().y == 0 )
|
||||||
|
assert(c:geometry().height == 100 )
|
||||||
|
assert(c:geometry().width == 100 )
|
||||||
|
c:kill()
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
runner.run_steps(steps)
|
||||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
Loading…
Reference in New Issue