133 lines
3.7 KiB
Lua
133 lines
3.7 KiB
Lua
-- 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
|
|
}
|
|
} |