Files
awesome-dotfiles/awesome/utils/ondemand_tile.lua
Rainer Bendig 9b3266a32e ...
Signed-off-by: Rainer Bendig <hexathos@mailbox.org>
2020-02-25 23:55:12 +01:00

260 lines
7.1 KiB
Lua

-- Alexander Tsepkov, 2015
--
-- Logic to compute window positions in order to tile them on the fly, even when in floating layout
local awful = require("awful")
local position = {}
local capi =
{
client = client,
mouse = mouse,
screen = screen,
wibox = wibox,
awesome = awesome,
}
local coords = {
left = {
x = 0,
y = 0,
h = 1,
w = 1 / 2
},
right = {
x = 1 / 2,
y = 0,
h = 1,
w = 1 / 2
},
top = {
x = 0,
y = 0,
h = 1 / 2,
w = 1,
},
bottom = {
x = 0,
y = 1 / 2,
h = 1 / 2,
w = 1
},
top_left = {
x = 0,
y = 0,
h = 1 / 2,
w = 1 / 2
},
top_right = {
x = 1 / 2,
y = 0,
h = 1 / 2,
w = 1 / 2
},
bottom_left = {
x = 0,
y = 1 / 2,
h = 1 / 2,
w = 1 / 2
},
bottom_right = {
x = 1 / 2,
y = 1 / 2,
h = 1 / 2,
w = 1 / 2
},
fullscreen = {
x = 0,
y = 0,
h = 1,
w = 1
},
center_pad = {
x = 1 / 8,
y = 1 / 8,
h = (1 / 4) * 3,
w = (1 / 4) * 3
},
left_third = {
x = 0,
y = 0,
h = 1,
w = 1 / 3
},
middle_third = {
x = (1 / 3),
y = 0,
h = 1,
w = 1 / 3
},
left_two_thirds = {
x = 0,
y = 0,
h = 1,
w = (1 / 3) * 2
},
right_third = {
x = ((1 / 3) * 2),
y = 0,
h = 1,
w = 1 / 3
},
right_two_thirds = {
x = (1 / 3),
y = 0,
h = 1,
w = (1 / 3) * 2
},
middle_two_thirds = {
x = (1 / 6),
y = 0,
h = 1,
w = (1 / 3) * 2
}
}
-- takes geometry, client window, and parent window (uses entire screen as parent window if omitted)
-- resizes client window based on geometry in relation to parent window. If geometry is a string, uses
-- one of existing geometry presets, if geometry is a table, reads x, y, w, h values from it to determine
-- position and size.
function position.at(geometry, c, p)
if type(geometry) == "string" then
geometry = coords[geometry]
end
local c = c or capi.client.focus
local c_geometry = c:geometry()
local screen = c.screen or awful.screen.getbycoord(c_geometry.x, c_geometry.y)
local s_geometry
if p then
s_geometry = p:geometry()
else
-- s_geometry = capi.screen[screen].geometry
s_geometry = capi.screen[screen].workarea
end
return c:geometry({
x = s_geometry.x + s_geometry.width * geometry.x,
y = s_geometry.y + s_geometry.height * geometry.y,
width = s_geometry.width * geometry.w,
height = s_geometry.height * geometry.h
})
end
-- A smarter version of the above function, computes existing window state to see if it already matches
-- a position above, and stacks direction intuitively
-- Direction should be a string identifying 1 of 4 directions: left, right, top, bottom
function position.compound(direction, c, p)
local c = c or capi.client.focus
local c_geometry = c:geometry()
local screen = c.screen or awful.screen.getbycoord(c_geometry.x, c_geometry.y)
local s_geometry
if p then
s_geometry = p:geometry()
else
s_geometry = capi.screen[screen].workarea
end
empirical_geometry = {
x = (c_geometry.x - s_geometry.x) / s_geometry.width,
y = (c_geometry.y - s_geometry.y) / s_geometry.height,
h = c_geometry.height / s_geometry.height,
w = c_geometry.width / s_geometry.width
}
-- figure out if we're already in one of the preset states
local state = nil
for key, val in pairs(coords) do
if equals(val, empirical_geometry) then
state = key
break
end
end
-- local naughty = require('naughty')
-- naughty.notify({text=dump(empirical_geometry)})
local geometry
if state == nil then
-- just starting, no stack yet
geometry = coords[direction]
elseif direction == 'left' then
-- stacking left
if state == 'left' then
geometry = coords['left_third']
elseif state == 'top' then
geometry = coords['top_left']
elseif state == 'bottom' then
geometry = coords['bottom_left']
elseif state == 'right' then
geometry = coords['middle_third']
elseif state == 'middle_third' or state == 'center_pad' then
geometry = coords['left']
elseif state == 'right_third' then
geometry = coords['right']
elseif state == 'top_right' then
geometry = coords['top']
elseif state == 'bottom_right' then
geometry = coords['bottom']
end
elseif direction == 'right' then
-- stacking right
if state == 'right' then
geometry = coords['right_third']
elseif state == 'top' then
geometry = coords['top_right']
elseif state == 'bottom' then
geometry = coords['bottom_right']
elseif state == 'left' then
geometry = coords['middle_third']
elseif state == 'middle_third' or state == 'center_pad' then
geometry = coords['right']
elseif state == 'left_third' then
geometry = coords['left']
elseif state == 'top_left' then
geometry = coords['top']
elseif state == 'bottom_left' then
geometry = coords['bottom']
end
elseif direction == 'top' then
-- stacking up
if state == 'left' or state == 'left_third' then
geometry = coords['top_left']
elseif state == 'bottom' or state == 'middle_third' then
geometry = coords['center_pad']
elseif state == 'right' or state == 'right_third' then
geometry = coords['top_right']
elseif state == 'center_pad' then
geometry = coords['top']
elseif state == 'bottom_left' then
geometry = coords['left']
elseif state == 'bottom_right' then
geometry = coords['right']
end
elseif direction == 'bottom' then
-- stacking down
if state == 'left' or state == 'left_third' then
geometry = coords['bottom_left']
elseif state == 'top' or state == 'middle_third' then
geometry = coords['center_pad']
elseif state == 'right' or state == 'right_third' then
geometry = coords['bottom_right']
elseif state == 'center_pad' then
geometry = coords['bottom']
elseif state == 'top_left' then
geometry = coords['left']
elseif state == 'top_right' then
geometry = coords['right']
end
end
if geometry == nil then return c:geometry() end
return c:geometry({
x = s_geometry.x + s_geometry.width * geometry.x,
y = s_geometry.y + s_geometry.height * geometry.y,
width = s_geometry.width * geometry.w,
height = s_geometry.height * geometry.h
})
end
return position