awful.placement: Extend the compositing feature
It can now keep the different return values and use them in later chain nodes. It also add a "virtual" geometry argument so the geometry is applied only after the last node is executed. Finally, it fixes using pretend and a composite chain at the same time.
This commit is contained in:
parent
be455cb140
commit
e6a04a5922
|
@ -90,20 +90,89 @@ end
|
||||||
|
|
||||||
local wrap_client = nil
|
local wrap_client = nil
|
||||||
|
|
||||||
local function compose(w1, w2)
|
--- Allow multiple placement functions to be daisy chained.
|
||||||
return wrap_client(function(...)
|
-- This also allow the functions to be aware they are being chained and act
|
||||||
w1(...)
|
-- upon the previous nodes results to avoid unnecessary processing or deduce
|
||||||
w2(...)
|
-- extra paramaters/arguments.
|
||||||
return --It make no sense to keep a return value
|
local function compose(...)
|
||||||
end)
|
local queue = {}
|
||||||
|
|
||||||
|
local nodes = {...}
|
||||||
|
|
||||||
|
-- Allow placement.foo + (var == 42 and placement.bar)
|
||||||
|
if not nodes[2] then
|
||||||
|
return nodes[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
wrap_client = function(f)
|
-- nodes[1] == self, nodes[2] == other
|
||||||
return setmetatable({is_placement=true}, {
|
for _, w in ipairs(nodes) do
|
||||||
|
-- Build an execution queue
|
||||||
|
if w.context and w.context == "compose" then
|
||||||
|
for _, elem in ipairs(w.queue or {}) do
|
||||||
|
table.insert(queue, elem)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
table.insert(queue, w)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local ret = wrap_client(function(d, args, ...)
|
||||||
|
local rets = {}
|
||||||
|
local last_geo = nil
|
||||||
|
|
||||||
|
-- As some functions may have to take into account results from
|
||||||
|
-- previously execued ones, add the `composition_results` hint.
|
||||||
|
args = setmetatable({composition_results=rets}, {__index=args})
|
||||||
|
|
||||||
|
-- Only apply the geometry once, not once per chain node, to do this,
|
||||||
|
-- Force the "pretend" argument and restore the original value for
|
||||||
|
-- the last node.
|
||||||
|
local pretend_real = args.pretend
|
||||||
|
|
||||||
|
args.pretend = true
|
||||||
|
|
||||||
|
for k, f in ipairs(queue) do
|
||||||
|
if k == #queue then
|
||||||
|
args.pretent = pretend_real
|
||||||
|
end
|
||||||
|
|
||||||
|
local r = {f(d, args, ...)}
|
||||||
|
last_geo = r[1] or last_geo
|
||||||
|
args.override_geometry = last_geo
|
||||||
|
|
||||||
|
-- Keep the return value, store one per context
|
||||||
|
if f.context then
|
||||||
|
-- When 2 composition queue are executed, merge the return values
|
||||||
|
if f.context == "compose" then
|
||||||
|
for k2,v in pairs(r) do
|
||||||
|
rets[k2] = v
|
||||||
|
end
|
||||||
|
else
|
||||||
|
rets[f.context] = r
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return last_geo, rets
|
||||||
|
end, "compose")
|
||||||
|
|
||||||
|
ret.queue = queue
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
wrap_client = function(f, context)
|
||||||
|
return setmetatable(
|
||||||
|
{
|
||||||
|
is_placement= true,
|
||||||
|
context = context,
|
||||||
|
},
|
||||||
|
{
|
||||||
__call = function(_,...) return f(...) end,
|
__call = function(_,...) return f(...) end,
|
||||||
__add = compose, -- Composition is usually defined as +
|
__add = compose, -- Composition is usually defined as +
|
||||||
__mul = compose -- Make sense if you think of the functions as matrices
|
__mul = compose -- Make sense if you think of the functions as matrices
|
||||||
})
|
}
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
local placement_private = {}
|
local placement_private = {}
|
||||||
|
@ -116,7 +185,7 @@ local placement_private = {}
|
||||||
local placement = setmetatable({}, {
|
local placement = setmetatable({}, {
|
||||||
__index = placement_private,
|
__index = placement_private,
|
||||||
__newindex = function(_, k, f)
|
__newindex = function(_, k, f)
|
||||||
placement_private[k] = wrap_client(f)
|
placement_private[k] = wrap_client(f, k)
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -226,6 +295,12 @@ local function geometry_common(obj, args, new_geo, ignore_border_width)
|
||||||
obj, (not args.pretend) and new_geo or nil, ignore_border_width
|
obj, (not args.pretend) and new_geo or nil, ignore_border_width
|
||||||
)
|
)
|
||||||
|
|
||||||
|
-- When using the placement composition along with the "pretend"
|
||||||
|
-- option, it is necessary to keep a "virtual" geometry.
|
||||||
|
if args.override_geometry then
|
||||||
|
dgeo = args.override_geometry
|
||||||
|
end
|
||||||
|
|
||||||
-- Apply the margins
|
-- Apply the margins
|
||||||
if args.margins then
|
if args.margins then
|
||||||
local delta = type(args.margins) == "table" and args.margins or {
|
local delta = type(args.margins) == "table" and args.margins or {
|
||||||
|
|
Loading…
Reference in New Issue