48
awesome/utils/README.md
Normal file
48
awesome/utils/README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
Utils
|
||||
-----
|
||||
This directory contains a list of convenience utilities for awesome WM.
|
||||
|
||||
## remember_positions.lua
|
||||
By default, awesome WM doesn't remember positions of your floating windows when you cycle through different layouts. This can be a problem both to the users who accidentally switched layouts as well as those wishing to temporarily rearrange windows and come back to original layout once they're done with their work. It's also a problem for those reloading their awesome configuration, since it forgets original window positions as well. This script fixes that. To take advantage of it, install it by adding the following line to your `rc.lua`:
|
||||
|
||||
load_script("utils/remember_positions", true)
|
||||
|
||||
|
||||
## ondemand_tile.lua
|
||||
Move floating window into any corner/tile via convenient shortcuts, i.e:
|
||||
|
||||
local positions = require('utils.ondemand_tile')
|
||||
|
||||
-- later in code
|
||||
awful.key({ modkey, "Shift" }, "Down", function (c) position.at('bottom', c) end),
|
||||
awful.key({ modkey, "Shift" }, "Left", function (c) position.at('left', c) end),
|
||||
awful.key({ modkey, "Shift" }, "Right", function (c) position.at('right', c) end),
|
||||
awful.key({ modkey, "Shift" }, "Up", function (c) position.at('top', c) end),
|
||||
|
||||
Positions can be specified as a table `{x, y, w, h}` or as a string to identify one of existing presets:
|
||||
|
||||
left
|
||||
right
|
||||
top
|
||||
bottom
|
||||
top_left
|
||||
top_right
|
||||
bottom_left
|
||||
bottom_right
|
||||
fullscreen
|
||||
center_pad
|
||||
left_third
|
||||
middle_third
|
||||
right_third
|
||||
left_two_thirds
|
||||
right_two_thirds
|
||||
middle_two_thirds
|
||||
|
||||
There is also a compound-resize option in positions module. It stacks previous tiling actions on top of each other in an intuitive manner. For example, when the window is on the `left` half of the screen, sending `down` event will move it to `bottom_left` position. In this way you can iterate through most of the presets in an intuitive manner with just 4 shortcuts:
|
||||
|
||||
awful.key({ modkey, "Shift" }, "Down", function (c) position.compound('bottom', c) end),
|
||||
awful.key({ modkey, "Shift" }, "Left", function (c) position.compound('left', c) end),
|
||||
awful.key({ modkey, "Shift" }, "Right", function (c) position.compound('right', c) end),
|
||||
awful.key({ modkey, "Shift" }, "Up", function (c) position.compound('top', c) end),
|
||||
|
||||
|
||||
259
awesome/utils/ondemand_tile.lua
Normal file
259
awesome/utils/ondemand_tile.lua
Normal file
@@ -0,0 +1,259 @@
|
||||
-- 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
|
||||
33
awesome/utils/remember_positions.lua
Normal file
33
awesome/utils/remember_positions.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
-- Alexander Tsepkov, 2015
|
||||
--
|
||||
-- By default awesome forgets window positions when you switch between layouts, this is especially a problem
|
||||
-- for floating layout, which awesome wasn't designed to handle gracefully out of the box. This tidbit of code
|
||||
-- fixes that issue by remembering window positions in floating layout and coming back to the same positions when
|
||||
-- you return to floating layout from a tiling one.
|
||||
local awful = require("awful")
|
||||
|
||||
floatgeoms = {}
|
||||
|
||||
tag.connect_signal("property::layout", function(t)
|
||||
for k, c in ipairs(t:clients()) do
|
||||
if ((awful.layout.get(mouse.screen) == awful.layout.suit.floating)
|
||||
or (awful.client.floating.get(c) == true)) then
|
||||
c:geometry(floatgeoms[c.window])
|
||||
end
|
||||
end
|
||||
client.connect_signal("unmanage", function(c) floatgeoms[c.window] = nil end)
|
||||
end)
|
||||
|
||||
client.connect_signal("property::geometry", function(c)
|
||||
if ((awful.layout.get(mouse.screen) == awful.layout.suit.floating) or (awful.client.floating.get(c) == true)) then
|
||||
floatgeoms[c.window] = c:geometry()
|
||||
end
|
||||
end)
|
||||
|
||||
client.connect_signal("unmanage", function(c) floatgeoms[c.window] = nil end)
|
||||
|
||||
client.connect_signal("manage", function(c)
|
||||
if ((awful.layout.get(mouse.screen) == awful.layout.suit.floating) or (awful.client.floating.get(c) == true)) then
|
||||
floatgeoms[c.window] = c:geometry()
|
||||
end
|
||||
end)
|
||||
Reference in New Issue
Block a user