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')
15 --- tabulous: fabulous tabs for awesome
18 local tabbed_tags
= otable() -- all tab tables, indexed by tab
19 local tabbed
= {} -- the current tag tab table
24 awful
.hooks
.user
.create('tabbed')
25 awful
.hooks
.user
.create('untabbed')
26 awful
.hooks
.user
.create('tabdisplay')
27 awful
.hooks
.user
.create('tabhide')
33 --- Find a key in a table.
34 -- @param table The table to look into
35 -- @param value The value to find.
36 -- @return The key or nil if not found.
37 function findkey(table, value
)
38 for k
, v
in pairs(table) do
45 --- Swaand select which client in tab is displayed.
46 -- @param tabindex The tab index.
47 -- @param cl The client to show.
48 function display(tabindex
, cl
)
49 local p
= tabbed
[tabindex
][1]
50 if cl
and p
~= cl
then
51 tabbed
[tabindex
][1] = cl
56 capi
.client
.focus
= cl
57 awful
.hooks
.user
.call('tabhide', p
)
58 awful
.hooks
.user
.call('tabdisplay', cl
)
62 --- Check if the client is in the given tabindex.
63 -- @param tabindex The tab index.
64 -- @param cl The client
66 function tabindex_check(tabindex
, cl
)
67 local c
= cl
or capi
.client
.focus
68 return findkey(tabbed
[tabindex
][2], c
)
71 --- Find the tab index or return nil if not tabbed.
72 -- @param cl The client to search.
73 -- @return The tab index.
74 function tabindex_get(cl
)
75 local c
= cl
or capi
.client
.focus
77 for tabindex
, tabdisplay
in pairs(tabbed
) do
78 -- Loop through all tab displays
79 local me
= tabindex_check(tabindex
, c
)
89 --- Get all clients on a tabbed display.
90 -- @param tabindex The tab index.
91 -- @return All tabbed clients.
92 function clients_get(tabindex
)
93 if tabbed
[tabindex
] == nil then return nil end
94 return tabbed
[tabindex
][2]
97 --- Get the displayed client on a tabbed display.
98 -- @param tabindex The tab index.
99 -- @return The displayed client.
100 function displayed_get(tabindex
)
101 if tabbed
[tabindex
] == nil then return nil end
102 return tabbed
[tabindex
][1]
105 --- Get a client by tab number.
106 -- @param tabindex The tab index.
107 -- @param pos The position in the tab.
108 -- @return The client at the given position.
109 function position_get(tabindex
, pos
)
110 if tabbed
[tabindex
] == nil then return nil end
111 return tabbed
[tabindex
][2][pos
]
114 --- Get the next client in a tab display.
115 -- @param tabindex The tab index.
116 -- @param cl The current client.
117 -- @return The next client.
118 function next(tabindex
, cl
)
119 local c
= cl
or tabbed
[tabindex
][1]
121 local i
= findkey(tabbed
[tabindex
][2], c
)
127 if tabbed
[tabindex
][2][i
+1] == nil then
128 return tabbed
[tabindex
][2][1]
131 return tabbed
[tabindex
][2][i
+ 1]
134 --- Get the previous client in a tabdisplay
135 -- @param tabindex The tab index.
136 -- @param cl The current client.
137 -- @return The previous client.
138 function prev(tabindex
, cl
)
139 local c
= cl
or tabbed
[tabindex
][1]
141 local i
= findkey(tabbed
[tabindex
][2], c
)
147 if tabbed
[tabindex
][2][i
-1] == nil then
148 return tabbed
[tabindex
][2][table.maxn(tabbed
[tabindex
][2])]
151 return tabbed
[tabindex
][2][i
- 1]
154 --- Remove a client from a tabbed display.
155 -- @param cl The client to remove.
156 -- @return True if the client has been untabbed.
158 local c
= cl
or capi
.client
.focus
159 local tabindex
= tabindex_get(c
)
161 if tabindex
== nil then return false end
163 local cindex
= findkey(tabbed
[tabindex
][2], c
)
165 if tabbed
[tabindex
][1] == c
then
166 display(tabindex
, next(tabindex
, c
))
169 table.remove(tabbed
[tabindex
][2], cindex
)
171 if table.maxn(tabbed
[tabindex
][2]) == 0 then
172 -- Table is empty now, remove the tabbed display
173 table.remove(tabbed
, tabindex
)
177 awful
.hooks
.user
.call('untabbed', c
)
180 --- Untab all clients in a tabbed display.
181 -- @param tabindex The tab index.
182 function untab_all(tabindex
)
183 for i
,c
in pairs(tabbed
[tabindex
][2]) do
185 awful
.hooks
.user
.call('untabbed', c
)
188 if tabbed
[tabindex
] ~= nil then
189 table.remove(tabbed
, tabindex
)
193 --- Create a new tabbed display with client as the master.
194 -- @param cl The client to set into the tab, focused one otherwise.
195 -- @return The created tab index.
196 function tab_create(cl
)
197 local c
= cl
or capi
.client
.focus
199 if not c
then return end
201 table.insert(tabbed
, {
202 c
, -- Window currently being displayed
203 { c
} -- List of windows in tabbed display
206 awful
.hooks
.user
.call('tabbed', c
)
207 return tabindex_get(c
)
210 --- Add a client to a tabbed display.
211 -- @param tabindex The tab index.
212 -- @param cl The client to add, or the focused one otherwise.
213 function tab(tabindex
, cl
)
214 local c
= cl
or capi
.client
.focus
216 if tabbed
[tabindex
] ~= nil then
217 local x
= tabindex_get(c
)
220 -- Add untabbed client to tabindex
221 table.insert(tabbed
[tabindex
][2], c
)
224 awful
.hooks
.user
.call('tabbed', c
)
225 elseif x
~= tabindex
then
226 -- Merge two tabbed views
227 local cc
= tabbed
[tabindex
][1]
228 local clients
= clients_get(x
)
231 tabindex
= tabindex_get(cc
)
233 for i
,b
in pairs(clients
) do
240 --- Start autotabbing, this automatically tabs new clients when the current
242 function autotab_start()
243 awful
.hooks
.manage
.register(function (c
)
244 local sel
= capi
.client
.focus
245 local index
= tabindex_get(sel
)
248 -- Currently focussed client is tabbed,
249 -- add the new window to the tabbed display
255 --- Update the tabbing when current tags changes, by unactivating
256 -- all tabs that are not in the current tag (and activating the good one)
257 function update_tabbing()
258 -- do nothing if nothing changed
259 if active_tag
== awful
.tag.selected() then return end
261 -- needed for initialisation
262 active_tag
= active_tag
or awful
.tag.selected()
264 -- save the tabbed list for the old active tag
265 tabbed_tags
[active_tag
] = tabbed
267 -- update the active tag and switch to the new tabbed list
268 active_tag
= awful
.tag.selected()
269 tabbed
= tabbed_tags
[active_tag
] or {}
271 -- update show/hide on the clients
272 for tag,tabs
in pairs(tabbed_tags
) do
273 if tag == active_tag
then
274 -- hide all clients that are not tab masters
275 for i
,tab
in pairs(tabs
) do
276 for i
,c
in pairs(tab
[2]) do
282 -- unhide all clients
283 for i
,tab
in pairs(tabs
) do
284 for i
,c
in pairs(tab
[2]) do
292 --- Keep tabulous in sync when a client is focused but was hidden in a tab
293 -- (show the client and hide the previous one)
294 function hook_focus(cl
)
295 local c
= cl
or awful
.client
.focus
296 local i
= tabindex_get(c
)
297 if i
and tabbed
[i
][1] ~= c
then
302 -- Keep tabulous in sync when focus change
303 awful
.hooks
.focus
.register(hook_focus
)
304 -- update the tabbing when the tags changes
305 awful
.hooks
.arrange
.register(update_tabbing
)
307 -- Set up hook so we don't leave lost hidden clients
308 awful
.hooks
.unmanage
.register(untab
)
311 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80