Layouts can define their own resizing handler (FS#1267)

This commit is contained in:
Robert Siska 2014-10-23 01:30:19 +02:00
parent daeb9aee19
commit 8d7b0feedd
4 changed files with 217 additions and 192 deletions

View File

@ -5,9 +5,78 @@
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
--- Dummy function for floating layout --- Dummy function for floating layout
-- Grab environment we need
local math = math
local ipairs = ipairs
local capi =
{
mouse = mouse,
mousegrabber = mousegrabber
}
-- awful.layout.suit.floating -- awful.layout.suit.floating
local floating = {} local floating = {}
function floating.mouse_resize_handler(c, corner, x, y)
local g = c:geometry()
-- Do not allow maximized clients to be resized by mouse
local fixed_x = c.maximized_horizontal
local fixed_y = c.maximized_vertical
-- Warp mouse pointer
capi.mouse.coords({ x = x, y = y })
capi.mousegrabber.run(function (_mouse)
for k, v in ipairs(_mouse.buttons) do
if v then
local ng
if corner == "bottom_right" then
ng = { width = _mouse.x - g.x,
height = _mouse.y - g.y }
elseif corner == "bottom_left" then
ng = { x = _mouse.x,
width = (g.x + g.width) - _mouse.x,
height = _mouse.y - g.y }
elseif corner == "top_left" then
ng = { x = _mouse.x,
width = (g.x + g.width) - _mouse.x,
y = _mouse.y,
height = (g.y + g.height) - _mouse.y }
else
ng = { width = _mouse.x - g.x,
y = _mouse.y,
height = (g.y + g.height) - _mouse.y }
end
if ng.width <= 0 then ng.width = nil end
if ng.height <= 0 then ng.height = nil end
if fixed_x then ng.width = g.width ng.x = g.x end
if fixed_y then ng.height = g.height ng.y = g.y end
c:geometry(ng)
-- Get real geometry that has been applied
-- in case we honor size hints
-- XXX: This should be rewritten when size
-- hints are available from Lua.
local rg = c:geometry()
if corner == "bottom_right" then
ng = {}
elseif corner == "bottom_left" then
ng = { x = (g.x + g.width) - rg.width }
elseif corner == "top_left" then
ng = { x = (g.x + g.width) - rg.width,
y = (g.y + g.height) - rg.height }
else
ng = { y = (g.y + g.height) - rg.height }
end
c:geometry({ x = ng.x, y = ng.y })
return true
end
end
return false
end, corner .. "_corner")
end
function floating.arrange() function floating.arrange()
end end

View File

@ -11,7 +11,9 @@ local tag = require("awful.tag")
local capi = local capi =
{ {
client = client, client = client,
screen = screen screen = screen,
mouse = mouse,
mousegrabber = mousegrabber
} }
local client = require("awful.client") local client = require("awful.client")
@ -19,6 +21,31 @@ local client = require("awful.client")
-- awful.layout.suit.magnifier -- awful.layout.suit.magnifier
local magnifier = {} local magnifier = {}
function magnifier.mouse_resize_handler(c, corner, x, y)
capi.mouse.coords({ x = x, y = y })
local wa = capi.screen[c.screen].workarea
local center_x = wa.x + wa.width / 2
local center_y = wa.y + wa.height / 2
local maxdist_pow = (wa.width^2 + wa.height^2) / 4
capi.mousegrabber.run(function (_mouse)
for k, v in ipairs(_mouse.buttons) do
if v then
local dx = center_x - _mouse.x
local dy = center_y - _mouse.y
local dist = dx^2 + dy^2
-- New master width factor
local mwfact = dist / maxdist_pow
tag.setmwfact(math.min(math.max(0.01, mwfact), 0.99), tag.selected(c.screen))
return true
end
end
return false
end, corner .. "_corner")
end
function magnifier.arrange(p) function magnifier.arrange(p)
-- Fullscreen? -- Fullscreen?
local area = p.workarea local area = p.workarea

View File

@ -7,14 +7,116 @@
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
-- Grab environment we need -- Grab environment we need
local tag = require("awful.tag")
local client = require("awful.client")
local ipairs = ipairs local ipairs = ipairs
local math = math local math = math
local tag = require("awful.tag") local capi =
{
mouse = mouse,
screen = screen,
mousegrabber = mousegrabber
}
--- Tiled layouts module for awful --- Tiled layouts module for awful
-- awful.layout.suit.tile -- awful.layout.suit.tile
local tile = {} local tile = {}
local function mouse_resize_handler(c, corner, x, y, orientation)
local orientation = orientation or "tile"
local wa = capi.screen[c.screen].workarea
local mwfact = tag.getmwfact()
local cursor
local g = c:geometry()
local offset = 0
local x,y
if orientation == "tile" then
cursor = "cross"
if g.height+15 > wa.height then
offset = g.height * .5
cursor = "sb_h_double_arrow"
elseif not (g.y+g.height+15 > wa.y+wa.height) then
offset = g.height
end
capi.mouse.coords({ x = wa.x + wa.width * mwfact, y = g.y + offset })
elseif orientation == "left" then
cursor = "cross"
if g.height+15 >= wa.height then
offset = g.height * .5
cursor = "sb_h_double_arrow"
elseif not (g.y+g.height+15 > wa.y+wa.height) then
offset = g.height
end
capi.mouse.coords({ x = wa.x + wa.width * (1 - mwfact), y = g.y + offset })
elseif orientation == "bottom" then
cursor = "cross"
if g.width+15 >= wa.width then
offset = g.width * .5
cursor = "sb_v_double_arrow"
elseif not (g.x+g.width+15 > wa.x+wa.width) then
offset = g.width
end
capi.mouse.coords({ y = wa.y + wa.height * mwfact, x = g.x + offset})
else
cursor = "cross"
if g.width+15 >= wa.width then
offset = g.width * .5
cursor = "sb_v_double_arrow"
elseif not (g.x+g.width+15 > wa.x+wa.width) then
offset = g.width
end
capi.mouse.coords({ y = wa.y + wa.height * (1 - mwfact), x= g.x + offset })
end
capi.mousegrabber.run(function (_mouse)
for k, v in ipairs(_mouse.buttons) do
if v then
local fact_x = (_mouse.x - wa.x) / wa.width
local fact_y = (_mouse.y - wa.y) / wa.height
local mwfact
local g = c:geometry()
-- we have to make sure we're not on the last visible client where we have to use different settings.
local wfact
local wfact_x, wfact_y
if (g.y+g.height+15) > (wa.y+wa.height) then
wfact_y = (g.y + g.height - _mouse.y) / wa.height
else
wfact_y = (_mouse.y - g.y) / wa.height
end
if (g.x+g.width+15) > (wa.x+wa.width) then
wfact_x = (g.x + g.width - _mouse.x) / wa.width
else
wfact_x = (_mouse.x - g.x) / wa.width
end
if orientation == "tile" then
mwfact = fact_x
wfact = wfact_y
elseif orientation == "left" then
mwfact = 1 - fact_x
wfact = wfact_y
elseif orientation == "bottom" then
mwfact = fact_y
wfact = wfact_x
else
mwfact = 1 - fact_y
wfact = wfact_x
end
tag.setmwfact(math.min(math.max(mwfact, 0.01), 0.99), tag.selected(c.screen))
client.setwfact(math.min(math.max(wfact,0.01), 0.99), c)
return true
end
end
return false
end, cursor)
end
local function tile_group(cls, wa, orientation, fact, group) local function tile_group(cls, wa, orientation, fact, group)
-- get our orientation right -- get our orientation right
local height = "height" local height = "height"
@ -152,6 +254,9 @@ end
tile.right = {} tile.right = {}
tile.right.name = "tile" tile.right.name = "tile"
tile.right.arrange = do_tile tile.right.arrange = do_tile
function tile.right.mouse_resize_handler(c, corner, x, y)
return mouse_resize_handler(c, corner, x, y)
end
--- The main tile algo, on left. --- The main tile algo, on left.
-- @param screen The screen number to tile. -- @param screen The screen number to tile.
@ -160,6 +265,9 @@ tile.left.name = "tileleft"
function tile.left.arrange(p) function tile.left.arrange(p)
return do_tile(p, "left") return do_tile(p, "left")
end end
function tile.left.mouse_resize_handler(c, corner, x, y)
return mouse_resize_handler(c, corner, x, y, "left")
end
--- The main tile algo, on bottom. --- The main tile algo, on bottom.
-- @param screen The screen number to tile. -- @param screen The screen number to tile.
@ -168,6 +276,9 @@ tile.bottom.name = "tilebottom"
function tile.bottom.arrange(p) function tile.bottom.arrange(p)
return do_tile(p, "bottom") return do_tile(p, "bottom")
end end
function tile.bottom.mouse_resize_handler(c, corner, x, y)
return mouse_resize_handler(c, corner, x, y, "bottom")
end
--- The main tile algo, on top. --- The main tile algo, on top.
-- @param screen The screen number to tile. -- @param screen The screen number to tile.
@ -176,8 +287,12 @@ tile.top.name = "tiletop"
function tile.top.arrange(p) function tile.top.arrange(p)
return do_tile(p, "top") return do_tile(p, "top")
end end
function tile.top.mouse_resize_handler(c, corner, x, y)
return mouse_resize_handler(c, corner, x, y, "top")
end
tile.arrange = tile.right.arrange tile.arrange = tile.right.arrange
tile.mouse_resize_handler = tile.right.mouse_resize_handler
tile.name = tile.right.name tile.name = tile.right.name
return tile return tile

View File

@ -335,183 +335,6 @@ function mouse.client.corner(c, corner)
return corner, x, y return corner, x, y
end end
local function client_resize_magnifier(c, corner)
local corner, x, y = mouse.client.corner(c, corner)
capi.mouse.coords({ x = x, y = y })
local wa = capi.screen[c.screen].workarea
local center_x = wa.x + wa.width / 2
local center_y = wa.y + wa.height / 2
local maxdist_pow = (wa.width^2 + wa.height^2) / 4
capi.mousegrabber.run(function (_mouse)
for k, v in ipairs(_mouse.buttons) do
if v then
local dx = center_x - _mouse.x
local dy = center_y - _mouse.y
local dist = dx^2 + dy^2
-- New master width factor
local mwfact = dist / maxdist_pow
tag.setmwfact(math.min(math.max(0.01, mwfact), 0.99), tag.selected(c.screen))
return true
end
end
return false
end, corner .. "_corner")
end
local function client_resize_tiled(c, lay)
local wa = capi.screen[c.screen].workarea
local mwfact = tag.getmwfact()
local cursor
local g = c:geometry()
local offset = 0
local x,y
if lay == layout.suit.tile then
cursor = "cross"
if g.height+15 > wa.height then
offset = g.height * .5
cursor = "sb_h_double_arrow"
elseif not (g.y+g.height+15 > wa.y+wa.height) then
offset = g.height
end
capi.mouse.coords({ x = wa.x + wa.width * mwfact, y = g.y + offset })
elseif lay == layout.suit.tile.left then
cursor = "cross"
if g.height+15 >= wa.height then
offset = g.height * .5
cursor = "sb_h_double_arrow"
elseif not (g.y+g.height+15 > wa.y+wa.height) then
offset = g.height
end
capi.mouse.coords({ x = wa.x + wa.width * (1 - mwfact), y = g.y + offset })
elseif lay == layout.suit.tile.bottom then
cursor = "cross"
if g.width+15 >= wa.width then
offset = g.width * .5
cursor = "sb_v_double_arrow"
elseif not (g.x+g.width+15 > wa.x+wa.width) then
offset = g.width
end
capi.mouse.coords({ y = wa.y + wa.height * mwfact, x = g.x + offset})
else
cursor = "cross"
if g.width+15 >= wa.width then
offset = g.width * .5
cursor = "sb_v_double_arrow"
elseif not (g.x+g.width+15 > wa.x+wa.width) then
offset = g.width
end
capi.mouse.coords({ y = wa.y + wa.height * (1 - mwfact), x= g.x + offset })
end
capi.mousegrabber.run(function (_mouse)
for k, v in ipairs(_mouse.buttons) do
if v then
local fact_x = (_mouse.x - wa.x) / wa.width
local fact_y = (_mouse.y - wa.y) / wa.height
local mwfact
local g = c:geometry()
-- we have to make sure we're not on the last visible client where we have to use different settings.
local wfact
local wfact_x, wfact_y
if (g.y+g.height+15) > (wa.y+wa.height) then
wfact_y = (g.y + g.height - _mouse.y) / wa.height
else
wfact_y = (_mouse.y - g.y) / wa.height
end
if (g.x+g.width+15) > (wa.x+wa.width) then
wfact_x = (g.x + g.width - _mouse.x) / wa.width
else
wfact_x = (_mouse.x - g.x) / wa.width
end
if lay == layout.suit.tile then
mwfact = fact_x
wfact = wfact_y
elseif lay == layout.suit.tile.left then
mwfact = 1 - fact_x
wfact = wfact_y
elseif lay == layout.suit.tile.bottom then
mwfact = fact_y
wfact = wfact_x
else
mwfact = 1 - fact_y
wfact = wfact_x
end
tag.setmwfact(math.min(math.max(mwfact, 0.01), 0.99), tag.selected(c.screen))
aclient.setwfact(math.min(math.max(wfact,0.01), 0.99), c)
return true
end
end
return false
end, cursor)
end
local function client_resize_floating(c, corner, fixed_x, fixed_y)
local corner, x, y = mouse.client.corner(c, corner)
local g = c:geometry()
-- Warp mouse pointer
capi.mouse.coords({ x = x, y = y })
capi.mousegrabber.run(function (_mouse)
for k, v in ipairs(_mouse.buttons) do
if v then
local ng
if corner == "bottom_right" then
ng = { width = _mouse.x - g.x,
height = _mouse.y - g.y }
elseif corner == "bottom_left" then
ng = { x = _mouse.x,
width = (g.x + g.width) - _mouse.x,
height = _mouse.y - g.y }
elseif corner == "top_left" then
ng = { x = _mouse.x,
width = (g.x + g.width) - _mouse.x,
y = _mouse.y,
height = (g.y + g.height) - _mouse.y }
else
ng = { width = _mouse.x - g.x,
y = _mouse.y,
height = (g.y + g.height) - _mouse.y }
end
if ng.width <= 0 then ng.width = nil end
if ng.height <= 0 then ng.height = nil end
if fixed_x then ng.width = g.width ng.x = g.x end
if fixed_y then ng.height = g.height ng.y = g.y end
c:geometry(ng)
-- Get real geometry that has been applied
-- in case we honor size hints
-- XXX: This should be rewritten when size
-- hints are available from Lua.
local rg = c:geometry()
if corner == "bottom_right" then
ng = {}
elseif corner == "bottom_left" then
ng = { x = (g.x + g.width) - rg.width }
elseif corner == "top_left" then
ng = { x = (g.x + g.width) - rg.width,
y = (g.y + g.height) - rg.height }
else
ng = { y = (g.y + g.height) - rg.height }
end
c:geometry({ x = ng.x, y = ng.y })
return true
end
end
return false
end, corner .. "_corner")
end
--- Resize a client. --- Resize a client.
-- @param c The client to resize, or the focused one by default. -- @param c The client to resize, or the focused one by default.
-- @param corner The corner to grab on resize. Auto detected by default. -- @param corner The corner to grab on resize. Auto detected by default.
@ -527,22 +350,13 @@ function mouse.client.resize(c, corner)
return return
end end
-- Do not allow maximized clients to be resized by mouse
local fixed_x = c.maximized_horizontal
local fixed_y = c.maximized_vertical
local lay = layout.get(c.screen) local lay = layout.get(c.screen)
local corner, x, y = mouse.client.corner(c, corner)
if lay == layout.suit.floating or aclient.floating.get(c) then if lay == layout.suit.floating or aclient.floating.get(c) then
return client_resize_floating(c, corner, fixed_x, fixed_y) return layout.suit.floating.mouse_resize_handler(c, corner, x, y)
elseif lay == layout.suit.tile elseif lay.mouse_resize_handler then
or lay == layout.suit.tile.left return lay.mouse_resize_handler(c, corner, x, y)
or lay == layout.suit.tile.top
or lay == layout.suit.tile.bottom
then
return client_resize_tiled(c, lay)
elseif lay == layout.suit.magnifier then
return client_resize_magnifier(c, corner)
end end
end end