simple-awesome/simple/tiling.lua

133 lines
3.7 KiB
Lua
Raw Normal View History

-- Offers window tiling functionnality
local awful = require("awful")
local grect = require("gears.geometry").rectangle
-- Placements
local leftTileGeometry = awful.placement.scale
+ awful.placement.left
+ awful.placement['maximize_vertically']
local rightTileGeometry = awful.placement.scale
+ awful.placement.right
+ awful.placement['maximize_vertically']
local maximizedTileGeometry = awful.placement.scale
+ awful.placement['maximize']
-- Check if geometries are the same
local geometryEquals = function(geo1, geo2)
return geo1.width == geo2.width and geo1.height == geo2.height and
geo1.x == geo2.x and geo1.y == geo2.y
end
-- Try to apply a tile placement to a client
-- return false if it changed nothing
local applyTile = function(c, geometry)
local initialGeometry = {
x = c.x,
y = c.y,
width = c.width,
height = c.height
}
local newGeometry = geometry(c, {honor_workarea=true, to_percent = 0.5})
return not geometryEquals(initialGeometry, newGeometry)
end
local screenLeft = function(geo)
return function (c)
local newScreen = c.screen.get_next_in_direction(c.screen, "left")
if newScreen ~= nil then
c.screen = newScreen
applyTile(c, geo)
end
end
end
local screenRight = function(geo)
return function (c)
local newScreen = c.screen.get_next_in_direction(c.screen, "right")
if newScreen ~= nil then
c.screen = newScreen
applyTile(c, geo)
end
end
end
local swapClient = function(c, dir)
local sel = c or capi.client.focus
if sel then
local cltbl = sel.screen.tiled_clients
local geomtbl = {}
for i,cl in ipairs(cltbl) do
if not cl.maximized then
geomtbl[i] = cl:geometry()
end
end
local target = grect.get_in_direction(dir, geomtbl, sel:geometry())
-- If we found a client to swap with, then go for it
if target then
cltbl[target]:swap(sel)
return true
end
end
return false
end
client.connect_signal("manage", function (c)
if awesome.startup
and not c.size_hints.user_position
and not c.size_hints.program_position then
-- Prevent clients from being unreachable after screen count changes.
awful.placement.no_offscreen(c)
end
if c.maximized then
applyTile(c, maximizedTileGeometry)
end
end)
return {
key = {
tileRight = function (c)
if c.maximized then
c:raise()
if not applyTile(c, rightTileGeometry) then
screenRight(leftTileGeometry)(c)
end
else
swapClient(c, 'right')
end
end,
tileLeft = function (c)
if c.maximized then
c:raise()
if not applyTile(c, leftTileGeometry) then
screenLeft(rightTileGeometry)(c)
end
else
swapClient(c, 'left')
end
end,
screenLeft = screenLeft(maximizedTileGeometry),
screenRight = screenRight(maximizedTileGeometry),
toggleMaximized = function (c)
if not c.maximized then
if not swapClient(c, 'up') then
c.maximized = true
c:raise()
end
else
if not applyTile(c, maximizedTileGeometry) then
c.maximized = false
end
end
end,
minimize = function(c)
if c.maximized or not swapClient(c, 'down') then
c.minimized = true
end
end
}
}