1 ---------------------------------------------------------------------------
2 -- @author Lucas de Vries <lucasdevries@gmail.com>
3 -- @author Julien Danjou <julien@danjou.info>
4 -- @copyright 2008 Julien Danjou, Lucas de Vries
5 -- @release @AWESOME_VERSION@
6 ---------------------------------------------------------------------------
8 -- Grab environment we need
9 local capi
= { client
= client
}
12 local awful
= require('awful')
14 --- tabulous: fabulous tabs for awesome
17 local tabbed_tags
= {} -- all tab tables, indexed by tab
18 local tabbed
= {} -- the current tag tab table
23 awful
.hooks
.user
.create('tabbed')
24 awful
.hooks
.user
.create('untabbed')
25 awful
.hooks
.user
.create('tabdisplay')
26 awful
.hooks
.user
.create('tabhide')
32 --- Find a key in a table.
33 -- @param table The table to look into
34 -- @param value The value to find.
35 -- @return The key or nil if not found.
36 function findkey(table, value
)
37 for k
, v
in pairs(table) do
44 --- Swaand select which client in tab is displayed.
45 -- @param tabindex The tab index.
46 -- @param cl The client to show.
47 function display(tabindex
, cl
)
48 local p
= tabbed
[tabindex
][1]
49 if cl
and p
~= cl
then
50 tabbed
[tabindex
][1] = cl
55 capi
.client
.focus
= cl
56 awful
.hooks
.user
.call('tabhide', p
)
57 awful
.hooks
.user
.call('tabdisplay', cl
)
61 --- Check if the client is in the given tabindex.
62 -- @param tabindex The tab index.
63 -- @param cl The client
65 function tabindex_check(tabindex
, cl
)
66 local c
= cl
or capi
.client
.focus
67 return findkey(tabbed
[tabindex
][2], c
)
70 --- Find the tab index or return nil if not tabbed.
71 -- @param cl The client to search.
72 -- @return The tab index.
73 function tabindex_get(cl
)
74 local c
= cl
or capi
.client
.focus
76 for tabindex
, tabdisplay
in pairs(tabbed
) do
77 -- Loop through all tab displays
78 local me
= tabindex_check(tabindex
, c
)
88 --- Get all clients on a tabbed display.
89 -- @param tabindex The tab index.
90 -- @return All tabbed clients.
91 function clients_get(tabindex
)
92 if tabbed
[tabindex
] == nil then return nil end
93 return tabbed
[tabindex
][2]
96 --- Get the displayed client on a tabbed display.
97 -- @param tabindex The tab index.
98 -- @return The displayed client.
99 function displayed_get(tabindex
)
100 if tabbed
[tabindex
] == nil then return nil end
101 return tabbed
[tabindex
][1]
104 --- Get a client by tab number.
105 -- @param tabindex The tab index.
106 -- @param pos The position in the tab.
107 -- @return The client at the given position.
108 function position_get(tabindex
, pos
)
109 if tabbed
[tabindex
] == nil then return nil end
110 return tabbed
[tabindex
][2][pos
]
113 --- Get the next client in a tab display.
114 -- @param tabindex The tab index.
115 -- @param cl The current client.
116 -- @return The next client.
117 function next(tabindex
, cl
)
118 local c
= cl
or tabbed
[tabindex
][1]
120 local i
= findkey(tabbed
[tabindex
][2], c
)
126 if tabbed
[tabindex
][2][i
+1] == nil then
127 return tabbed
[tabindex
][2][1]
130 return tabbed
[tabindex
][2][i
+ 1]
133 --- Get the previous client in a tabdisplay
134 -- @param tabindex The tab index.
135 -- @param cl The current client.
136 -- @return The previous client.
137 function prev(tabindex
, cl
)
138 local c
= cl
or tabbed
[tabindex
][1]
140 local i
= findkey(tabbed
[tabindex
][2], c
)
146 if tabbed
[tabindex
][2][i
-1] == nil then
147 return tabbed
[tabindex
][2][table.maxn(tabbed
[tabindex
][2])]
150 return tabbed
[tabindex
][2][i
- 1]
153 --- Remove a client from a tabbed display.
154 -- @param cl The client to remove.
155 -- @return True if the client has been untabbed.
157 local c
= cl
or capi
.client
.focus
158 local tabindex
= tabindex_get(c
)
160 if tabindex
== nil then return false end
162 local cindex
= findkey(tabbed
[tabindex
][2], c
)
164 if tabbed
[tabindex
][1] == c
then
165 display(tabindex
, next(tabindex
, c
))
168 table.remove(tabbed
[tabindex
][2], cindex
)
170 if table.maxn(tabbed
[tabindex
][2]) == 0 then
171 -- Table is empty now, remove the tabbed display
172 table.remove(tabbed
, tabindex
)
176 awful
.hooks
.user
.call('untabbed', c
)
179 --- Untab all clients in a tabbed display.
180 -- @param tabindex The tab index.
181 function untab_all(tabindex
)
182 for i
,c
in pairs(tabbed
[tabindex
][2]) do
184 awful
.hooks
.user
.call('untabbed', c
)
187 if tabbed
[tabindex
] ~= nil then
188 table.remove(tabbed
, tabindex
)
192 --- Create a new tabbed display with client as the master.
193 -- @param cl The client to set into the tab, focused one otherwise.
194 -- @return The created tab index.
195 function tab_create(cl
)
196 local c
= cl
or capi
.client
.focus
198 if not c
then return end
200 table.insert(tabbed
, {
201 c
, -- Window currently being displayed
202 { c
} -- List of windows in tabbed display
205 awful
.hooks
.user
.call('tabbed', c
)
206 return tabindex_get(c
)
209 --- Add a client to a tabbed display.
210 -- @param tabindex The tab index.
211 -- @param cl The client to add, or the focused one otherwise.
212 function tab(tabindex
, cl
)
213 local c
= cl
or capi
.client
.focus
215 if tabbed
[tabindex
] ~= nil then
216 local x
= tabindex_get(c
)
219 -- Add untabbed client to tabindex
220 table.insert(tabbed
[tabindex
][2], c
)
223 awful
.hooks
.user
.call('tabbed', c
)
224 elseif x
~= tabindex
then
225 -- Merge two tabbed views
226 local cc
= tabbed
[tabindex
][1]
227 local clients
= clients_get(x
)
230 tabindex
= tabindex_get(cc
)
232 for i
,b
in pairs(clients
) do
239 --- Start autotabbing, this automatically tabs new clients when the current
241 function autotab_start()
242 awful
.hooks
.manage
.register(function (c
)
243 local sel
= capi
.client
.focus
244 local index
= tabindex_get(sel
)
247 -- Currently focussed client is tabbed,
248 -- add the new window to the tabbed display
254 --- Update the tabbing when current tags changes, by unactivating
255 -- all tabs that are not in the current tag (and activating the good one)
256 function update_tabbing()
257 -- do nothing if nothing changed
258 if active_tag
== awful
.tag.selected().name
then return end
260 -- needed for initialisation
261 active_tag
= active_tag
or awful
.tag.selected().name
263 -- save the tabbed list for the old active tag
264 tabbed_tags
[active_tag
] = tabbed
266 -- update the active tag and switch to the new tabbed list
267 active_tag
= awful
.tag.selected().name
268 tabbed
= tabbed_tags
[active_tag
] or {}
270 -- update show/hide on the clients
271 for tag,tabs
in pairs(tabbed_tags
) do
272 if tag == active_tag
then
273 -- hide all clients that are not tab masters
274 for i
,tab
in pairs(tabs
) do
275 for i
,c
in pairs(tab
[2]) do
281 -- unhide all clients
282 for i
,tab
in pairs(tabs
) do
283 for i
,c
in pairs(tab
[2]) do
291 --- Keep tabulous in sync when a client is focused but was hidden in a tab
292 -- (show the client and hide the previous one)
293 function hook_focus(cl
)
294 local c
= cl
or awful
.client
.focus
295 local i
= tabindex_get(c
)
296 if i
and tabbed
[i
][1] ~= c
then
301 -- Keep tabulous in sync when focus change
302 awful
.hooks
.focus
.register(hook_focus
)
303 -- update the tabbing when the tags changes
304 awful
.hooks
.arrange
.register(update_tabbing
)
306 -- Set up hook so we don't leave lost hidden clients
307 awful
.hooks
.unmanage
.register(untab
)
310 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80