placement: Support 'attach' in composited placement functions

This commit is contained in:
Emmanuel Lepage Vallee 2016-05-07 00:52:39 -04:00
parent e78a07574b
commit 45ff7efce5
1 changed files with 48 additions and 23 deletions

View File

@ -96,6 +96,15 @@ local function get_screen(s)
end
local wrap_client = nil
local placement
-- Store function -> keys
local reverse_align_map = {}
-- Forward declarations
local area_common
local wibox_update_strut
local attach
--- Allow multiple placement functions to be daisy chained.
-- This also allow the functions to be aware they are being chained and act
@ -123,7 +132,8 @@ local function compose(...)
end
end
local ret = wrap_client(function(d, args, ...)
local ret
ret = wrap_client(function(d, args, ...)
local rets = {}
local last_geo = nil
@ -135,6 +145,7 @@ local function compose(...)
-- Force the "pretend" argument and restore the original value for
-- the last node.
local pretend_real = args.pretend
local attach_real = args.attach
args.pretend = true
args.attach = false
@ -161,6 +172,11 @@ local function compose(...)
end
end
if attach_real then
args.attach = true
attach(d, ret, args)
end
return last_geo, rets
end, "compose")
@ -190,7 +206,7 @@ local placement_private = {}
--
-- (awful.placement.no_overlap + awful.placement.no_offscreen)(c)
--
local placement = setmetatable({}, {
placement = setmetatable({}, {
__index = placement_private,
__newindex = function(_, k, f)
placement_private[k] = wrap_client(f, k)
@ -222,9 +238,6 @@ local align_map = {
center_horizontal = function(sw, _ , dw, _ ) return {x=sw/2-dw/2, y= nil } end,
}
-- Store function -> keys
local reverse_align_map = {}
-- Some parameters to correctly compute the final size
local resize_to_point_map = {
-- Corners
@ -308,13 +321,13 @@ local function fix_new_geometry(new_geo, args, force)
}
end
--- Get the area covered by a drawin.
-- Get the area covered by a drawin.
-- @param d The drawin
-- @tparam[opt=nil] table new_geo A new geometry
-- @tparam[opt=false] boolean ignore_border_width Ignore the border
-- @tparam table args the method arguments
-- @treturn The drawin's area.
local function area_common(d, new_geo, ignore_border_width, args)
area_common = function(d, new_geo, ignore_border_width, args)
-- The C side expect no arguments, nil isn't valid
local geometry = new_geo and d:geometry(new_geo) or d:geometry()
local border = ignore_border_width and 0 or d.border_width or 0
@ -339,7 +352,6 @@ end
-- @tparam[opt=false] boolean ignore_border_width Ignore the border
-- @treturn table A table with *x*, *y*, *width* and *height*.
local function geometry_common(obj, args, new_geo, ignore_border_width)
-- Store the current geometry in a singleton-memento
if args.store_geometry and new_geo and args.context then
store_geometry(obj, args.context)
@ -431,7 +443,7 @@ local function move_into_geometry(source, target)
end
-- Update the workarea
local function wibox_update_strut(d, position)
wibox_update_strut = function(d, position, args)
-- If the drawable isn't visible, remove the struts
if not d.visible then
d:struts { left = 0, right = 0, bottom = 0, top = 0 }
@ -446,16 +458,18 @@ local function wibox_update_strut(d, position)
-- the workarea
local struts = { left = 0, right = 0, bottom = 0, top = 0 }
local m = get_decoration(args)
if vertical then
for _, v in ipairs {"right", "left"} do
if (not position) or position:match(v) then
struts[v] = geo.width
struts[v] = geo.width + m[v]
end
end
else
for _, v in ipairs {"top", "bottom"} do
if (not position) or position:match(v) then
struts[v] = geo.height
struts[v] = geo.height + m[v]
end
end
end
@ -464,16 +478,18 @@ local function wibox_update_strut(d, position)
d:struts(struts)
end
--- Pin a drawable to a placement function.
-- Pin a drawable to a placement function.
-- Automatically update the position when the size change.
-- All other arguments will be passed to the `position` function (if any)
-- @tparam[opt=client.focus] drawable d A drawable (like `client`, `mouse`
-- or `wibox`)
-- @param position_f A position name (see `align`) or a position function
-- @tparam[opt={}] table args Other arguments
local function attach(d, position_f, args)
attach = function(d, position_f, args)
args = args or {}
if args.pretend then return end
if not args.attach then return end
-- Avoid a connection loop
@ -492,27 +508,36 @@ local function attach(d, position_f, args)
position_f(d, args)
end
d:connect_signal("property::width" , tracker)
d:connect_signal("property::height", tracker)
d:connect_signal("property::width" , tracker)
d:connect_signal("property::height" , tracker)
d:connect_signal("property::border_width", tracker)
tracker()
local function tracker_struts()
--TODO this is too fragile and doesn't work with all methods.
wibox_update_strut(d, d.position or reverse_align_map[position_f], args)
end
local parent = args.parent or d.screen
if args.update_workarea then
local function tracker_struts()
--TODO this is too fragile and doesn't work with all methods.
wibox_update_strut(d, reverse_align_map[position_f])
end
d:connect_signal("property::geometry" , tracker_struts)
d:connect_signal("property::visible" , tracker_struts)
capi.client.connect_signal("property::struts", tracker_struts)
tracker_struts()
elseif parent == d.screen then
if args.honor_workarea then
parent:connect_signal("property::workarea", tracker)
end
if args.honor_padding then
parent:connect_signal("property::padding", tracker)
end
end
-- If there is a parent drawable, screen or mouse, also track it
local parent = args.parent or d.screen
if parent then
args.parent:connect_signal("property::geometry" , tracker)
parent:connect_signal("property::geometry" , tracker)
end
end