awful.placement: Add a 'resize_to_mouse' function
This commit is contained in:
parent
a072e34194
commit
604ea15c45
|
@ -143,6 +143,21 @@ local align_map = {
|
|||
-- Store function -> keys
|
||||
local reverse_align_map = {}
|
||||
|
||||
-- Some parameters to correctly compute the final size
|
||||
local resize_to_point_map = {
|
||||
-- Corners
|
||||
top_left = {p1= nil , p2={1,1}, x_only=false, y_only=false},
|
||||
top_right = {p1={0,1} , p2= nil , x_only=false, y_only=false},
|
||||
bottom_left = {p1= nil , p2={1,0}, x_only=false, y_only=false},
|
||||
bottom_right = {p1={0,0} , p2= nil , x_only=false, y_only=false},
|
||||
|
||||
-- Sides
|
||||
left = {p1= nil , p2={1,1}, x_only=true , y_only=false},
|
||||
right = {p1={0,0} , p2= nil , x_only=true , y_only=false},
|
||||
top = {p1= nil , p2={1,1}, x_only=false, y_only=true },
|
||||
bottom = {p1={0,0} , p2= nil , x_only=false, y_only=true },
|
||||
}
|
||||
|
||||
--- 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
|
||||
|
@ -172,8 +187,6 @@ local function area_common(d, new_geo, ignore_border_width)
|
|||
-- 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
|
||||
geometry.x = geometry.x
|
||||
geometry.y = geometry.y
|
||||
geometry.width = geometry.width + 2 * border
|
||||
geometry.height = geometry.height + 2 * border
|
||||
return geometry
|
||||
|
@ -434,6 +447,24 @@ local function area_remove(areas, elem)
|
|||
return areas
|
||||
end
|
||||
|
||||
-- Convert 2 points into a rectangle
|
||||
local function rect_from_points(p1x, p1y, p2x, p2y)
|
||||
return {
|
||||
x = p1x,
|
||||
y = p1y,
|
||||
width = p2x - p1x,
|
||||
height = p2y - p1y,
|
||||
}
|
||||
end
|
||||
|
||||
-- Convert a rectangle and matrix info into a point
|
||||
local function rect_to_point(rect, corner_i, corner_j)
|
||||
return {
|
||||
x = rect.x + corner_i * math.floor(rect.width ),
|
||||
y = rect.y + corner_j * math.floor(rect.height),
|
||||
}
|
||||
end
|
||||
|
||||
--- Move a drawable to the closest corner of the parent geometry (such as the
|
||||
-- screen).
|
||||
--
|
||||
|
@ -622,6 +653,62 @@ function placement.next_to_mouse(c, offset)
|
|||
return c:geometry({ x = x, y = y })
|
||||
end
|
||||
|
||||
--- Resize the drawable to the cursor.
|
||||
--
|
||||
-- Valid args:
|
||||
--
|
||||
-- * *axis*: The axis (vertical or horizontal). If none is
|
||||
-- specified, then the drawable will be resized on both axis.
|
||||
--
|
||||
-- @tparam drawable d A drawable (like `client`, `mouse` or `wibox`)
|
||||
-- @tparam[opt={}] table args Other arguments
|
||||
function placement.resize_to_mouse(d, args)
|
||||
d = d or capi.client.focus
|
||||
args = add_context(args, "resize_to_mouse")
|
||||
|
||||
local coords = capi.mouse.coords()
|
||||
local ngeo = geometry_common(d, args)
|
||||
local h_only = args.axis == "horizontal"
|
||||
local v_only = args.axis == "vertical"
|
||||
|
||||
-- To support both growing and shrinking the drawable, it is necessary
|
||||
-- to decide to use either "north or south" and "east or west" directions.
|
||||
-- Otherwise, the result will always be 1x1
|
||||
local closest_corner = placement.closest_corner(capi.mouse, {
|
||||
parent = d,
|
||||
include_sides = args.include_sides or false,
|
||||
})
|
||||
|
||||
-- Given "include_sides" wasn't set, it will always return a name
|
||||
-- with the 2 axis. If only one axis is needed, adjust the result
|
||||
if h_only then
|
||||
closest_corner = closest_corner:match("left") or closest_corner:match("right")
|
||||
elseif v_only then
|
||||
closest_corner = closest_corner:match("top") or closest_corner:match("bottom")
|
||||
end
|
||||
|
||||
-- Use p0 (mouse), p1 and p2 to create a rectangle
|
||||
local pts = resize_to_point_map[closest_corner]
|
||||
local p1 = pts.p1 and rect_to_point(ngeo, pts.p1[1], pts.p1[2]) or coords
|
||||
local p2 = pts.p2 and rect_to_point(ngeo, pts.p2[1], pts.p2[2]) or coords
|
||||
|
||||
-- Create top_left and bottom_right points, convert to rectangle
|
||||
ngeo = rect_from_points(
|
||||
pts.y_only and ngeo.x or math.min(p1.x, p2.x),
|
||||
pts.x_only and ngeo.y or math.min(p1.y, p2.y),
|
||||
pts.y_only and ngeo.x + ngeo.width or math.max(p2.x, p1.x),
|
||||
pts.x_only and ngeo.y + ngeo.height or math.max(p2.y, p1.y)
|
||||
)
|
||||
|
||||
local bw = d.border_width or 0
|
||||
|
||||
for _, a in ipairs {"width", "height"} do
|
||||
ngeo[a] = ngeo[a] - 2*bw
|
||||
end
|
||||
|
||||
geometry_common(d, args, ngeo)
|
||||
end
|
||||
|
||||
--- Move the drawable (client or wibox) `d` to a screen position or side.
|
||||
--
|
||||
-- Supported args.positions are:
|
||||
|
|
Loading…
Reference in New Issue