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')
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
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
)
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
)
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