-
Notifications
You must be signed in to change notification settings - Fork 0
/
pad.lua
195 lines (175 loc) · 7.46 KB
/
pad.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
---------------------------------------------------------------
-- Basic scratchpad manager for the awesome window manager
---------------------------------------------------------------
-- Coded by: * Adrian C. (anrxc) <[email protected]>
-- * Konstantin Koslowski (konni) <[email protected]>
-- Licensed under the WTFPL version 2
-- * http://sam.zoy.org/wtfpl/COPYING
---------------------------------------------------------------
-- To use this module add:
-- local scratch = require("scratch")
-- to the top of your rc.lua, and call:
-- scratch.pad.set(c, args)
-- from a clientkeys binding, and:
-- scratch.pad.toggle(args)
-- from a globalkeys binding.
--
-- set(c, args)
-- c - Client to scratch or un-scratch
-- args - table containing properties
-- args.vert - vertical position
-- possible values: "left", "right", "top", "bottom", "center"
-- defaults to "center"
-- args.horiz - horizontal position
-- possible values: "left", "right", "top", "bottom", "center"
-- defaults to "center"
-- args.width - Width in absolute pixels, or width percentage
-- when <= 1
-- (0.50 (50% of the screen) by default)
-- args.height - Height in absolute pixels, or height percentage
-- when <= 1
-- (0.50 (50% of the screen) by default)
-- args.sticky - client visible on all workspaces
-- defaults to false
-- args.instance - used to have multiple scratched clients
-- defaults to 0
-- args.screen - screen the client appears on, 0 for any
-- mouse.screen by default
-- toggle(args)
-- args - table containing properties
-- args.vert - vertical position
-- possible values: "left", "right", "top", "bottom", "center"
-- defaults to "center"
-- args.horiz - horizontal position
-- possible values: "left", "right", "top", "bottom", "center"
-- defaults to "center"
-- args.instance - used to have multiple scratched clients
-- defaults to 0
-- args.screen - screen the client appears on, 0 for any
-- mouse.screen by default
--
---------------------------------------------------------------
-- Grab environment
local pairs = pairs
local awful = require("awful")
local naughty = require("naughty")
local capi = {
mouse = mouse,
client = client,
screen = screen
}
-- Scratchpad: basic scratchpad manager for the awesome window manager
local pad = {} -- module scratch.pad
local scratchpad = {}
-- Toggle a set of properties on a client.
local function toggleprop(c, prop)
c.ontop = prop.ontop or false
c.above = prop.above or false
c.hidden = prop.hidden or false
c.sticky = prop.stick or false
c.skip_taskbar = prop.task or false
end
-- Scratch the focused client, or un-scratch and tile it.
-- If another client is already scratched, replace it with the focused client.
function pad.set(c, args)
local vert = args.vert or "center"
local horiz = args.horiz or "center"
local width = args.width or 0.50
local height = args.height or 0.50
local sticky = args.sticky or false
local instance = args.instance or 0
local screen = args.screen or capi.mouse.screen
-- Determine signal usage in this version of awesome
local attach_signal = capi.client.connect_signal or capi.client.add_signal
local detach_signal = capi.client.disconnect_signal or capi.client.remove_signal
local function setscratch(c)
-- Scratchdrop clients are floaters
awful.client.floating.set(c, true)
-- Client geometry and placement
local screengeom = capi.screen[capi.mouse.screen].workarea
if width <= 1 then width = screengeom.width * width end
if height <= 1 then height = screengeom.height * height end
if vert == "top" then y = screengeom.y
elseif vert == "bottom" then y = screengeom.y + screengeom.height - height - 4
else y = screengeom.y + (screengeom.height - height)/2 end
if horiz == "left" then x = screengeom.x
elseif horiz == "right" then x = screengeom.x + screengeom.width - width - 4
else x = screengeom.x + (screengeom.width - width)/2 end
-- Client properties
c:geometry({ x = x, y = y, width = width, height = height })
c.ontop = true
c.above = true
c.skip_taskbar = true
if sticky then c.sticky = true end
awful.titlebar.hide(c)
c:raise()
capi.client.focus = c
end
-- Prepare a table for storing clients,
if not scratchpad.pad then scratchpad.pad = {} end
if not scratchpad.pad[instance] then scratchpad.pad[instance] = {} end
attach_signal("unmanage", function (c)
-- add unmanage signal for scratchpad clients
for scr, cl in pairs(scratchpad.pad[instance]) do
if cl == c then scratchpad.pad[instance][scr] = nil end
end
end)
-- If the scratcphad is emtpy, store the client,
if not scratchpad.pad[instance][screen] then
scratchpad.pad[instance][screen] = c
-- then apply geometry and properties
setscratch(c)
else -- If a client is already scratched,
local oc = scratchpad.pad[instance][screen]
-- unscratch, and compare it with the focused client
awful.client.floating.toggle(oc); toggleprop(oc, {})
-- If it matches clear the table, if not replace it
if oc == c then scratchpad.pad[instance][screen] = nil
else scratchpad.pad[instance][screen] = c; setscratch(c) end
end
end
-- Move the scratchpad[instance] to the current workspace, focus and raise it
-- when it's hidden, or hide it when it's visible.
function pad.toggle(args)
if not args then args = {} end
local instance = args.instance or 0
local screen = args.screen or capi.mouse.screen
local vert = args.vert or nil
local horiz = args.horiz or nil
-- Check if we have a client on storage,
if scratchpad.pad and scratchpad.pad[instance] then
if scratchpad.pad[instance][0] ~= nil then
screen = 0
end
-- and get it out, to play
if scratchpad.pad[instance][screen] ~= nil then
local c = scratchpad.pad[instance][screen]
-- If it's visible on another tag hide it,
if c:isvisible() == false then c.hidden = true
-- and move it to the current worskpace
awful.client.movetotag(awful.tag.selected(capi.mouse.screen), c)
end
-- Focus and raise if it's hidden,
if c.hidden then
local screengeom = capi.screen[capi.mouse.screen].workarea
local g = c:geometry()
if vert then
if vert == "top" then g.y = screengeom.y
elseif vert == "bottom" then g.y = screengeom.y + screengeom.height - g.height - 4
else g.y = screengeom.y + (screengeom.height - g.height)/2 end
end
if horiz then
if horiz == "left" then g.x = screengeom.x
elseif horiz == "right" then g.x = screengeom.x + screengeom.width - g.width - 4
else g.x = screengeom.x + (screengeom.width - g.width)/2 end
end
c:geometry(g)
c.hidden = false
c:raise(); capi.client.focus = c
else -- hide it if it's not
c.hidden = true
end
end
end
end
return pad