awful.placement: Add a memento system.

It is used by the ewmh methods.
This commit is contained in:
Emmanuel Lepage Vallee 2016-04-15 05:09:05 -04:00
parent fcd320c7f6
commit 2b5d918a8d
1 changed files with 65 additions and 12 deletions

View File

@ -39,6 +39,11 @@
-- --
-- **attach** (*boolean*): -- **attach** (*boolean*):
-- --
-- **store_geometry** (*boolean*):
--
-- Keep a single history of each type of placement. It can be restored using
-- `awful.placement.restore` by setting the right `context` argument.
--
-- When either the parent or the screen geometry change, call the placement -- When either the parent or the screen geometry change, call the placement
-- function again. -- function again.
-- --
@ -103,6 +108,26 @@ local align_map = {
-- Store function -> keys -- Store function -> keys
local reverse_align_map = {} local reverse_align_map = {}
--- Add a context to the arguments.
-- This function extend the argument table. The context is used by some
-- internal helper methods. If there already is a context, it has priority and
-- is kept.
local function add_context(args, context)
return setmetatable({context = (args or {}).context or context }, {__index=args})
end
local data = setmetatable({}, { __mode = 'k' })
--- Store a drawable geometry (per context) in a weak table.
-- @param d The drawin
-- @tparam string reqtype The context.
local function store_geometry(d, reqtype)
if not data[d] then data[d] = {} end
if not data[d][reqtype] then data[d][reqtype] = {} end
data[d][reqtype] = d:geometry()
data[d][reqtype].screen = d.screen
end
--- Get the area covered by a drawin. --- Get the area covered by a drawin.
-- @param d The drawin -- @param d The drawin
-- @tparam[opt=nil] table new_geo A new geometry -- @tparam[opt=nil] table new_geo A new geometry
@ -128,6 +153,12 @@ end
-- @tparam[opt=false] boolean ignore_border_width Ignore the border -- @tparam[opt=false] boolean ignore_border_width Ignore the border
-- @treturn table A table with *x*, *y*, *width* and *height*. -- @treturn table A table with *x*, *y*, *width* and *height*.
local function geometry_common(obj, args, new_geo, ignore_border_width) 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)
end
-- It's a mouse -- It's a mouse
if obj.coords then if obj.coords then
local coords = new_geo and obj.coords(new_geo) or obj.coords() local coords = new_geo and obj.coords(new_geo) or obj.coords()
@ -381,6 +412,7 @@ end
-- @tparam[opt={}] table args The arguments -- @tparam[opt={}] table args The arguments
-- @treturn string The corner name -- @treturn string The corner name
function placement.closest_corner(d, args) function placement.closest_corner(d, args)
args = add_context(args, "closest_corner")
d = d or capi.client.focus d = d or capi.client.focus
local sgeo = get_parent_geometry(d, args) local sgeo = get_parent_geometry(d, args)
@ -567,7 +599,7 @@ end
-- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`) -- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`)
-- @tparam[opt={}] table args Other arguments -- @tparam[opt={}] table args Other arguments
function placement.align(d, args) function placement.align(d, args)
args = args or {} args = add_context(args, "align")
d = d or capi.client.focus d = d or capi.client.focus
if not d or not args.position then return end if not d or not args.position then return end
@ -596,8 +628,9 @@ end
-- Add the alias functions -- Add the alias functions
for k in pairs(align_map) do for k in pairs(align_map) do
placement[k] = function(d, args) placement[k] = function(d, args)
local new_args = setmetatable({position = k}, {__index=args}) args = add_context(args, k)
placement.align(d, new_args) args.position = k
placement.align(d, args)
end end
reverse_align_map[placement[k]] = k reverse_align_map[placement[k]] = k
end end
@ -636,7 +669,7 @@ end
-- @tparam[opt=client.focus] drawable d A drawable (like `client` or `wibox`) -- @tparam[opt=client.focus] drawable d A drawable (like `client` or `wibox`)
-- @tparam[opt={}] table args The arguments -- @tparam[opt={}] table args The arguments
function placement.stretch(d, args) function placement.stretch(d, args)
args = args or {} args = add_context(args, "stretch")
d = d or capi.client.focus d = d or capi.client.focus
if not d or not args.direction then return end if not d or not args.direction then return end
@ -644,8 +677,8 @@ function placement.stretch(d, args)
-- In case there is multiple directions, call `stretch` for each of them -- In case there is multiple directions, call `stretch` for each of them
if type(args.direction) == "table" then if type(args.direction) == "table" then
for _, dir in ipairs(args.direction) do for _, dir in ipairs(args.direction) do
local new_args = setmetatable({direction = dir}, {__index=args}) args.direction = dir
placement.stretch(dir, new_args) placement.stretch(dir, args)
end end
return return
end end
@ -681,8 +714,9 @@ end
-- Add the alias functions -- Add the alias functions
for _,v in ipairs {"left", "right", "up", "down"} do for _,v in ipairs {"left", "right", "up", "down"} do
placement["stretch_"..v] = function(d, args) placement["stretch_"..v] = function(d, args)
local new_args = setmetatable({direction = v}, {__index=args}) args = add_context(args, "stretch_"..v)
placement.stretch(d, new_args) args.direction = v
placement.stretch(d, args)
end end
end end
@ -704,7 +738,7 @@ end
-- @tparam[opt=client.focus] drawable d A drawable (like `client` or `wibox`) -- @tparam[opt=client.focus] drawable d A drawable (like `client` or `wibox`)
-- @tparam[opt={}] table args The arguments -- @tparam[opt={}] table args The arguments
function placement.maximize(d, args) function placement.maximize(d, args)
args = args or {} args = add_context(args, "maximize")
d = d or capi.client.focus d = d or capi.client.focus
if not d then return end if not d then return end
@ -731,9 +765,9 @@ end
-- Add the alias functions -- Add the alias functions
for _, v in ipairs {"vertically", "horizontally"} do for _, v in ipairs {"vertically", "horizontally"} do
placement["maximize_"..v] = function(d2, args) placement["maximize_"..v] = function(d2, args)
args = args or {} args = add_context(args, "maximize_"..v)
local new_args = setmetatable({axis = v}, {__index=args}) args.axis = v
placement.maximize(d2, new_args) placement.maximize(d2, args)
end end
end end
@ -741,6 +775,25 @@ end
---@DOC_awful_placement_maximize_horizontally_EXAMPLE@ ---@DOC_awful_placement_maximize_horizontally_EXAMPLE@
--- Restore the geometry.
-- @tparam[opt=client.focus] drawable d A drawable (like `client` or `wibox`)
-- @tparam[opt={}] table args The arguments
-- @treturn boolean If the geometry was restored
function placement.restore(d, args)
if not args or not args.context then return false end
d = d or capi.client.focus
if not data[d] then return false end
local memento = data[d][args.context]
if not memento then return false end
memento.screen = nil --TODO use it
d:geometry(memento)
return true
end
return placement return placement
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80