placement: Allow to configure the next_to anchors
They were previously hardcoded to match the classic context menu behavior. It isn't flexible enough for some popup type.
This commit is contained in:
parent
3fa42f3b1a
commit
f1145af49d
|
@ -262,16 +262,19 @@ local resize_to_point_map = {
|
|||
}
|
||||
|
||||
-- Outer position matrix
|
||||
-- 1=best case, 2=fallback
|
||||
local outer_positions = {
|
||||
left1 = function(r, w, _) return {x=r.x-w , y=r.y }, "down" end,
|
||||
left2 = function(r, w, h) return {x=r.x-w , y=r.y-h+r.height }, "up" end,
|
||||
right1 = function(r, _, _) return {x=r.x , y=r.y }, "down" end,
|
||||
right2 = function(r, _, h) return {x=r.x , y=r.y-h+r.height }, "up" end,
|
||||
top1 = function(r, _, h) return {x=r.x , y=r.y-h }, "right" end,
|
||||
top2 = function(r, w, h) return {x=r.x-w+r.width, y=r.y-h }, "left" end,
|
||||
bottom1 = function(r, _, _) return {x=r.x , y=r.y }, "right" end,
|
||||
bottom2 = function(r, w, _) return {x=r.x-w+r.width, y=r.y }, "left" end,
|
||||
left_front = function(r, w, _) return {x=r.x-w , y=r.y }, "front" end,
|
||||
left_back = function(r, w, h) return {x=r.x-w , y=r.y-h+r.height }, "back" end,
|
||||
left_middle = function(r, w, h) return {x=r.x-w , y=r.y-h/2+r.height/2 }, "middle" end,
|
||||
right_front = function(r, _, _) return {x=r.x , y=r.y }, "front" end,
|
||||
right_back = function(r, _, h) return {x=r.x , y=r.y-h+r.height }, "back" end,
|
||||
right_middle = function(r, _, h) return {x=r.x , y=r.y-h/2+r.height/2 }, "middle" end,
|
||||
top_front = function(r, _, h) return {x=r.x , y=r.y-h }, "front" end,
|
||||
top_back = function(r, w, h) return {x=r.x-w+r.width , y=r.y-h }, "back" end,
|
||||
top_middle = function(r, w, h) return {x=r.x-w/2+r.width/2, y=r.y-h }, "middle" end,
|
||||
bottom_front = function(r, _, _) return {x=r.x , y=r.y }, "front" end,
|
||||
bottom_back = function(r, w, _) return {x=r.x-w+r.width , y=r.y }, "back" end,
|
||||
bottom_middle = function(r, w, _) return {x=r.x-w/2+r.width/2, y=r.y }, "middle" end,
|
||||
}
|
||||
|
||||
--- Add a context to the arguments.
|
||||
|
@ -1353,28 +1356,55 @@ end
|
|||
|
||||
--- Move a drawable to a relative position next to another one.
|
||||
--
|
||||
-- This placement function offers two additional settings to align the drawable
|
||||
-- alongside the parent geometry. The first one, the position, sets the side
|
||||
-- relative to the parent. The second one, the anchor, set the alignment within
|
||||
-- the side selected by the `preferred_positions`. Both settings are tables of
|
||||
-- priorities. The first available slot will be used. If there isn't enough
|
||||
-- space, then it will fallback to the next until it is possible to fit the
|
||||
-- drawable. This is meant to avoid going offscreen.
|
||||
--
|
||||
-- The `args.preferred_positions` look like this:
|
||||
--
|
||||
-- {"top", "right", "left", "bottom"}
|
||||
--
|
||||
-- The `args.preferred_anchors` are:
|
||||
--
|
||||
-- * "front": The closest to the origin (0,0)
|
||||
-- * "middle": Centered aligned with the parent
|
||||
-- * "back": The opposite side compared to `front`
|
||||
--
|
||||
-- In that case, if there is room on the top of the geometry, then it will have
|
||||
-- priority, followed by all the others, in order.
|
||||
--
|
||||
-- @tparam drawable d A wibox or client
|
||||
-- @tparam table args
|
||||
-- @tparam string args.mode The mode
|
||||
-- @tparam string args.preferred_positions The preferred positions (in order)
|
||||
-- @tparam string|table args.preferred_positions The preferred positions (in order)
|
||||
-- @tparam string|table args.preferred_anchors The preferred anchor(s) (in order)
|
||||
-- @tparam string args.geometry A geometry inside the other drawable
|
||||
-- @treturn table The new geometry
|
||||
-- @treturn string The choosen position
|
||||
-- @treturn string The choosen direction
|
||||
-- @treturn string The choosen position ("left", "right", "top" or "bottom")
|
||||
-- @treturn string The choosen anchor ("front", "middle" or "back")
|
||||
function placement.next_to(d, args)
|
||||
args = add_context(args, "next_to")
|
||||
d = d or capi.client.focus
|
||||
|
||||
local preferred_positions = {}
|
||||
local original_pos, original_anchors = args.preferred_positions, args.preferred_anchors
|
||||
|
||||
for k, v in ipairs(args.preferred_positions or {}) do
|
||||
if type(original_pos) == "string" then
|
||||
original_pos = {original_pos}
|
||||
end
|
||||
|
||||
if type(original_anchors) == "string" then
|
||||
original_anchors = {original_anchors}
|
||||
end
|
||||
|
||||
local preferred_positions = {}
|
||||
local preferred_anchors = #(original_anchors or {}) > 0 and
|
||||
original_anchors or {"front", "back", "middle"}
|
||||
|
||||
for k, v in ipairs(original_pos or {}) do
|
||||
preferred_positions[v] = k
|
||||
end
|
||||
|
||||
|
@ -1406,15 +1436,14 @@ function placement.next_to(d, args)
|
|||
-- and order them by preferred_positions
|
||||
local does_fit = {}
|
||||
for k,v in pairs(regions) do
|
||||
local geo, dir = outer_positions[k.."1"](v, dgeo.width, dgeo.height)
|
||||
geo.width, geo.height = dgeo.width, dgeo.height
|
||||
local fit = fit_in_bounding(v.screen, geo, args)
|
||||
local geo, dir, fit
|
||||
|
||||
-- Try the other compatible geometry
|
||||
if not fit then
|
||||
geo, dir = outer_positions[k.."2"](v, dgeo.width, dgeo.height)
|
||||
-- Try each anchor until one that fits is found
|
||||
for _, anchor in ipairs(preferred_anchors) do
|
||||
geo, dir = outer_positions[k.."_"..anchor](v, dgeo.width, dgeo.height)
|
||||
geo.width, geo.height = dgeo.width, dgeo.height
|
||||
fit = fit_in_bounding(v.screen, geo, args)
|
||||
if fit then break end
|
||||
end
|
||||
|
||||
does_fit[k] = fit and {geo, dir} or nil
|
||||
|
|
Loading…
Reference in New Issue