260 lines
7.1 KiB
Lua
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
|