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
|
-- Outer position matrix
|
||||||
-- 1=best case, 2=fallback
|
|
||||||
local outer_positions = {
|
local outer_positions = {
|
||||||
left1 = function(r, w, _) return {x=r.x-w , y=r.y }, "down" end,
|
left_front = function(r, w, _) return {x=r.x-w , y=r.y }, "front" end,
|
||||||
left2 = function(r, w, h) return {x=r.x-w , y=r.y-h+r.height }, "up" end,
|
left_back = function(r, w, h) return {x=r.x-w , y=r.y-h+r.height }, "back" end,
|
||||||
right1 = function(r, _, _) return {x=r.x , y=r.y }, "down" end,
|
left_middle = function(r, w, h) return {x=r.x-w , y=r.y-h/2+r.height/2 }, "middle" end,
|
||||||
right2 = function(r, _, h) return {x=r.x , y=r.y-h+r.height }, "up" end,
|
right_front = function(r, _, _) return {x=r.x , y=r.y }, "front" end,
|
||||||
top1 = function(r, _, h) return {x=r.x , y=r.y-h }, "right" end,
|
right_back = function(r, _, h) return {x=r.x , y=r.y-h+r.height }, "back" end,
|
||||||
top2 = function(r, w, h) return {x=r.x-w+r.width, y=r.y-h }, "left" end,
|
right_middle = function(r, _, h) return {x=r.x , y=r.y-h/2+r.height/2 }, "middle" end,
|
||||||
bottom1 = function(r, _, _) return {x=r.x , y=r.y }, "right" end,
|
top_front = function(r, _, h) return {x=r.x , y=r.y-h }, "front" end,
|
||||||
bottom2 = function(r, w, _) return {x=r.x-w+r.width, y=r.y }, "left" 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.
|
--- Add a context to the arguments.
|
||||||
|
@ -1353,28 +1356,55 @@ end
|
||||||
|
|
||||||
--- Move a drawable to a relative position next to another one.
|
--- 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:
|
-- The `args.preferred_positions` look like this:
|
||||||
--
|
--
|
||||||
-- {"top", "right", "left", "bottom"}
|
-- {"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
|
-- 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.
|
-- priority, followed by all the others, in order.
|
||||||
--
|
--
|
||||||
-- @tparam drawable d A wibox or client
|
-- @tparam drawable d A wibox or client
|
||||||
-- @tparam table args
|
-- @tparam table args
|
||||||
-- @tparam string args.mode The mode
|
-- @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
|
-- @tparam string args.geometry A geometry inside the other drawable
|
||||||
-- @treturn table The new geometry
|
-- @treturn table The new geometry
|
||||||
-- @treturn string The choosen position
|
-- @treturn string The choosen position ("left", "right", "top" or "bottom")
|
||||||
-- @treturn string The choosen direction
|
-- @treturn string The choosen anchor ("front", "middle" or "back")
|
||||||
function placement.next_to(d, args)
|
function placement.next_to(d, args)
|
||||||
args = add_context(args, "next_to")
|
args = add_context(args, "next_to")
|
||||||
d = d or capi.client.focus
|
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
|
preferred_positions[v] = k
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1406,15 +1436,14 @@ function placement.next_to(d, args)
|
||||||
-- and order them by preferred_positions
|
-- and order them by preferred_positions
|
||||||
local does_fit = {}
|
local does_fit = {}
|
||||||
for k,v in pairs(regions) do
|
for k,v in pairs(regions) do
|
||||||
local geo, dir = outer_positions[k.."1"](v, dgeo.width, dgeo.height)
|
local geo, dir, fit
|
||||||
geo.width, geo.height = dgeo.width, dgeo.height
|
|
||||||
local fit = fit_in_bounding(v.screen, geo, args)
|
|
||||||
|
|
||||||
-- Try the other compatible geometry
|
-- Try each anchor until one that fits is found
|
||||||
if not fit then
|
for _, anchor in ipairs(preferred_anchors) do
|
||||||
geo, dir = outer_positions[k.."2"](v, dgeo.width, dgeo.height)
|
geo, dir = outer_positions[k.."_"..anchor](v, dgeo.width, dgeo.height)
|
||||||
geo.width, geo.height = dgeo.width, dgeo.height
|
geo.width, geo.height = dgeo.width, dgeo.height
|
||||||
fit = fit_in_bounding(v.screen, geo, args)
|
fit = fit_in_bounding(v.screen, geo, args)
|
||||||
|
if fit then break end
|
||||||
end
|
end
|
||||||
|
|
||||||
does_fit[k] = fit and {geo, dir} or nil
|
does_fit[k] = fit and {geo, dir} or nil
|
||||||
|
|
Loading…
Reference in New Issue