awful.placement: Add the border to the client's geometry (#540)

Thanks to the way that X11 works, geometries consider the size of the client
without the border width, but the position of the top-left corner of the border.
This commit adds a new function get_area() which returns the area that is
actually covered by a client. Then, all the code is changed to use this new
function (even the part of the code which did get this border thing correct).

Closes https://github.com/awesomeWM/awesome/pull/541.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2015-10-24 08:44:50 +02:00 committed by Daniel Hahler
parent 3d3570a998
commit 0be33a0707
1 changed files with 28 additions and 18 deletions

View File

@ -103,26 +103,36 @@ local function area_remove(areas, elem)
return areas return areas
end end
--- Get the area covered by a client.
-- @client c The client.
-- @treturn The client's area.
local function get_area(c)
local geometry = c:geometry()
local border = c.border_width or 0
geometry.width = geometry.width + 2 * border
geometry.height = geometry.height + 2 * border
return geometry
end
--- Place the client so no part of it will be outside the screen (workarea). --- Place the client so no part of it will be outside the screen (workarea).
-- @client c The client. -- @client c The client.
-- @tparam[opt=client's screen] integer screen The screen. -- @tparam[opt=client's screen] integer screen The screen.
-- @treturn table The new client geometry. -- @treturn table The new client geometry.
function placement.no_offscreen(c, screen) function placement.no_offscreen(c, screen)
local c = c or capi.client.focus local c = c or capi.client.focus
local geometry = c:geometry() local geometry = get_area(c)
local screen = screen or c.screen or a_screen.getbycoord(geometry.x, geometry.y) local screen = screen or c.screen or a_screen.getbycoord(geometry.x, geometry.y)
local border = c.border_width
local screen_geometry = capi.screen[screen].workarea local screen_geometry = capi.screen[screen].workarea
if geometry.x + geometry.width + 2*border > screen_geometry.x + screen_geometry.width then if geometry.x + geometry.width > screen_geometry.x + screen_geometry.width then
geometry.x = screen_geometry.x + screen_geometry.width - geometry.width - 2*border geometry.x = screen_geometry.x + screen_geometry.width - geometry.width
end end
if geometry.x < screen_geometry.x then if geometry.x < screen_geometry.x then
geometry.x = screen_geometry.x geometry.x = screen_geometry.x
end end
if geometry.y + geometry.height + border > screen_geometry.y + screen_geometry.height then if geometry.y + geometry.height > screen_geometry.y + screen_geometry.height then
geometry.y = screen_geometry.y + screen_geometry.height - geometry.height - 2*border geometry.y = screen_geometry.y + screen_geometry.height - geometry.height
end end
if geometry.y < screen_geometry.y then if geometry.y < screen_geometry.y then
geometry.y = screen_geometry.y geometry.y = screen_geometry.y
@ -134,14 +144,14 @@ end
--- Place the client where there's place available with minimum overlap. --- Place the client where there's place available with minimum overlap.
-- @param c The client. -- @param c The client.
function placement.no_overlap(c) function placement.no_overlap(c)
local geometry = c:geometry() local geometry = get_area(c)
local screen = c.screen or a_screen.getbycoord(geometry.x, geometry.y) local screen = c.screen or a_screen.getbycoord(geometry.x, geometry.y)
local cls = client.visible(screen) local cls = client.visible(screen)
local curlay = layout.get() local curlay = layout.get()
local areas = { capi.screen[screen].workarea } local areas = { capi.screen[screen].workarea }
for i, cl in pairs(cls) do for i, cl in pairs(cls) do
if cl ~= c and cl.type ~= "desktop" and (client.floating.get(cl) or curlay == layout.suit.floating) then if cl ~= c and cl.type ~= "desktop" and (client.floating.get(cl) or curlay == layout.suit.floating) then
areas = area_remove(areas, cl:geometry()) areas = area_remove(areas, get_area(cl))
end end
end end
@ -188,7 +198,7 @@ end
-- @return The new client geometry. -- @return The new client geometry.
function placement.under_mouse(c) function placement.under_mouse(c)
local c = c or capi.client.focus local c = c or capi.client.focus
local c_geometry = c:geometry() local c_geometry = get_area(c)
local m_coords = capi.mouse.coords() local m_coords = capi.mouse.coords()
return c:geometry({ x = m_coords.x - c_geometry.width / 2, return c:geometry({ x = m_coords.x - c_geometry.width / 2,
y = m_coords.y - c_geometry.height / 2 }) y = m_coords.y - c_geometry.height / 2 })
@ -204,9 +214,9 @@ end
function placement.next_to_mouse(c, offset) function placement.next_to_mouse(c, offset)
c = c or capi.client.focus c = c or capi.client.focus
offset = offset or dpi(5) offset = offset or dpi(5)
local c_geometry = c:geometry() local c_geometry = get_area(c)
local c_width = c_geometry.width + (c.border_width * 2) local c_width = c_geometry.width
local c_height = c_geometry.height + (c.border_width * 2) local c_height = c_geometry.height
local m_coords = capi.mouse.coords() local m_coords = capi.mouse.coords()
local screen_geometry = capi.screen[capi.mouse.screen].workarea local screen_geometry = capi.screen[capi.mouse.screen].workarea
@ -236,11 +246,11 @@ end
-- @return The new client geometry. -- @return The new client geometry.
function placement.centered(c, p) function placement.centered(c, p)
local c = c or capi.client.focus local c = c or capi.client.focus
local c_geometry = c:geometry() local c_geometry = get_area(c)
local screen = c.screen or a_screen.getbycoord(c_geometry.x, c_geometry.y) local screen = c.screen or a_screen.getbycoord(c_geometry.x, c_geometry.y)
local s_geometry local s_geometry
if p then if p then
s_geometry = p:geometry() s_geometry = get_area(p)
else else
s_geometry = capi.screen[screen].geometry s_geometry = capi.screen[screen].geometry
end end
@ -254,11 +264,11 @@ end
-- @return The new client geometry. -- @return The new client geometry.
function placement.center_horizontal(c, p) function placement.center_horizontal(c, p)
local c = c or capi.client.focus local c = c or capi.client.focus
local c_geometry = c:geometry() local c_geometry = get_area(c)
local screen = c.screen or a_screen.getbycoord(c_geometry.x, c_geometry.y) local screen = c.screen or a_screen.getbycoord(c_geometry.x, c_geometry.y)
local s_geometry local s_geometry
if p then if p then
s_geometry = p:geometry() s_geometry = get_area(p)
else else
s_geometry = capi.screen[screen].geometry s_geometry = capi.screen[screen].geometry
end end
@ -271,11 +281,11 @@ end
-- @return The new client geometry. -- @return The new client geometry.
function placement.center_vertical(c, p) function placement.center_vertical(c, p)
local c = c or capi.client.focus local c = c or capi.client.focus
local c_geometry = c:geometry() local c_geometry = get_area(c)
local screen = c.screen or a_screen.getbycoord(c_geometry.x, c_geometry.y) local screen = c.screen or a_screen.getbycoord(c_geometry.x, c_geometry.y)
local s_geometry local s_geometry
if p then if p then
s_geometry = p:geometry() s_geometry = get_area(p)
else else
s_geometry = capi.screen[screen].geometry s_geometry = capi.screen[screen].geometry
end end