Repository navigation
Expand file tree
/
Copy pathtabulous.lua.in
More file actions
311 lines (253 loc) · 8.22 KB
/
Copy pathtabulous.lua.in
File metadata and controls
311 lines (253 loc) · 8.22 KB
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
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
---------------------------------------------------------------------------
-- @author Lucas de Vries <lucasdevries@gmail.com>
-- @author Julien Danjou <julien@danjou.info>
-- @copyright 2008 Julien Danjou, Lucas de Vries
-- @release @AWESOME_VERSION@
---------------------------------------------------------------------------
-- Grab environment we need
local capi = { client = client }
local table = table
local pairs = pairs
local awful = require('awful')
local otable = otable
--- Fabulous tabs
module("tabulous")
local tabbed_tags = otable() -- all tab tables, indexed by tab
local tabbed = {} -- the current tag tab table
local active_tag
-- Hook creation
awful.hooks.user.create('tabbed')
awful.hooks.user.create('untabbed')
awful.hooks.user.create('tabdisplay')
awful.hooks.user.create('tabhide')
---------------
-- Functions --
---------------
--- Find a key in a table.
-- @param table The table to look into
-- @param value The value to find.
-- @return The key or nil if not found.
function findkey(table, value)
for k, v in pairs(table) do
if v == value then
return k
end
end
end
--- Swaand select which client in tab is displayed.
-- @param tabindex The tab index.
-- @param cl The client to show.
function display(tabindex, cl)
local p = tabbed[tabindex][1]
if cl and p ~= cl then
tabbed[tabindex][1] = cl
cl.hide = false
p.hide = true
capi.client.focus = cl
awful.hooks.user.call('tabhide', p)
awful.hooks.user.call('tabdisplay', cl)
end
end
--- Check if the client is in the given tabindex.
-- @param tabindex The tab index.
-- @param cl The client
-- @return The key.
function tabindex_check(tabindex, cl)
local c = cl or capi.client.focus
return findkey(tabbed[tabindex][2], c)
end
--- Find the tab index or return nil if not tabbed.
-- @param cl The client to search.
-- @return The tab index.
function tabindex_get(cl)
local c = cl or capi.client.focus
for tabindex, tabdisplay in pairs(tabbed) do
-- Loop through all tab displays
local me = tabindex_check(tabindex, c)
if me ~= nil then
return tabindex
end
end
return nil
end
--- Get all clients on a tabbed display.
-- @param tabindex The tab index.
-- @return All tabbed clients.
function clients_get(tabindex)
if tabbed[tabindex] == nil then return nil end
return tabbed[tabindex][2]
end
--- Get the displayed client on a tabbed display.
-- @param tabindex The tab index.
-- @return The displayed client.
function displayed_get(tabindex)
if tabbed[tabindex] == nil then return nil end
return tabbed[tabindex][1]
end
--- Get a client by tab number.
-- @param tabindex The tab index.
-- @param pos The position in the tab.
-- @return The client at the given position.
function position_get(tabindex, pos)
if tabbed[tabindex] == nil then return nil end
return tabbed[tabindex][2][pos]
end
--- Get the next client in a tab display.
-- @param tabindex The tab index.
-- @param cl The current client.
-- @return The next client.
function next(tabindex, cl)
local c = cl or tabbed[tabindex][1]
local i = findkey(tabbed[tabindex][2], c)
if i == nil then
return nil
end
if tabbed[tabindex][2][i+1] == nil then
return tabbed[tabindex][2][1]
end
return tabbed[tabindex][2][i + 1]
end
--- Get the previous client in a tabdisplay
-- @param tabindex The tab index.
-- @param cl The current client.
-- @return The previous client.
function prev(tabindex, cl)
local c = cl or tabbed[tabindex][1]
local i = findkey(tabbed[tabindex][2], c)
if i == nil then
return nil
end
if i == 1 then
return tabbed[tabindex][2][table.maxn(tabbed[tabindex][2])]
end
return tabbed[tabindex][2][i - 1]
end
--- Remove a client from a tabbed display.
-- @param cl The client to remove.
-- @return True if the client has been untabbed.
function untab(cl)
local c = cl or capi.client.focus
local tabindex = tabindex_get(c)
if tabindex == nil then return false end
local cindex = findkey(tabbed[tabindex][2], c)
if tabbed[tabindex][1] == c then
display(tabindex, next(tabindex, c))
end
table.remove(tabbed[tabindex][2], cindex)
if table.maxn(tabbed[tabindex][2]) == 0 then
-- Table is empty now, remove the tabbed display
table.remove(tabbed, tabindex)
end
c.hide = false
awful.hooks.user.call('untabbed', c)
return true
end
--- Untab all clients in a tabbed display.
-- @param tabindex The tab index.
function untab_all(tabindex)
for i,c in pairs(tabbed[tabindex][2]) do
c.hide = false
awful.hooks.user.call('untabbed', c)
end
if tabbed[tabindex] ~= nil then
table.remove(tabbed, tabindex)
end
end
--- Create a new tabbed display with client as the master.
-- @param cl The client to set into the tab, focused one otherwise.
-- @return The created tab index.
function tab_create(cl)
local c = cl or capi.client.focus
if not c then return end
table.insert(tabbed, {
c, -- Window currently being displayed
{ c } -- List of windows in tabbed display
})
awful.hooks.user.call('tabbed', c)
return tabindex_get(c)
end
--- Add a client to a tabbed display.
-- @param tabindex The tab index.
-- @param cl The client to add, or the focused one otherwise.
function tab(tabindex, cl)
local c = cl or capi.client.focus
if tabbed[tabindex] ~= nil then
local x = tabindex_get(c)
if x == nil then
-- Add untabbed client to tabindex
table.insert(tabbed[tabindex][2], c)
display(tabindex, c)
awful.hooks.user.call('tabbed', c)
elseif x ~= tabindex then
-- Merge two tabbed views
local cc = tabbed[tabindex][1]
local clients = clients_get(x)
untab_all(x)
tabindex = tabindex_get(cc)
for i,b in pairs(clients) do
tab(tabindex, b)
end
end
end
end
--- Start autotabbing, this automatically tabs new clients when the current
-- client is tabbed.
function autotab_start()
awful.hooks.manage.register(function (c)
local sel = capi.client.focus
local index = tabindex_get(sel)
if index ~= nil then
-- Currently focussed client is tabbed,
-- add the new window to the tabbed display
tab(index, c)
end
end)
end
--- Update the tabbing when current tags changes, by unactivating
-- all tabs that are not in the current tag (and activating the good one)
function update_tabbing()
-- do nothing if nothing changed
if active_tag == awful.tag.selected() then return end
-- needed for initialisation
active_tag = active_tag or awful.tag.selected()
-- save the tabbed list for the old active tag
tabbed_tags[active_tag] = tabbed
-- update the active tag and switch to the new tabbed list
active_tag = awful.tag.selected()
tabbed = tabbed_tags[active_tag] or {}
-- update show/hide on the clients
for tag,tabs in pairs(tabbed_tags) do
if tag == active_tag then
-- hide all clients that are not tab masters
for i,tab in pairs(tabs) do
for i,c in pairs(tab[2]) do
c.hide = true
end
tab[1].hide = false
end
else
-- unhide all clients
for i,tab in pairs(tabs) do
for i,c in pairs(tab[2]) do
c.hide = false
end
end
end
end
end
--- Keep tabulous in sync when a client is focused but was hidden in a tab
-- (show the client and hide the previous one)
function hook_focus(cl)
local c = cl or awful.client.focus
local i = tabindex_get(c)
if i and tabbed[i][1] ~= c then
display(i, c)
end
end
-- Keep tabulous in sync when focus change
awful.hooks.focus.register(hook_focus)
-- update the tabbing when the tags changes
awful.hooks.arrange.register(update_tabbing)
-- Set up hook so we don't leave lost hidden clients
awful.hooks.unmanage.register(untab)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80