image: add function to create from argb32 data
[awesome.git] / lib / tabulous.lua.in
blob2f84f28adfc3a954c277d9b8dfffbf649166bcb7
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 }
10 local table = table
11 local pairs = pairs
12 local awful = require('awful')
14 --- tabulous: fabulous tabs for awesome
15 module("tabulous")
17 local tabbed_tags = {} -- all tab tables, indexed by tab
18 local tabbed = {} -- the current tag tab table
20 local active_tag
22 -- Hook creation
23 awful.hooks.user.create('tabbed')
24 awful.hooks.user.create('untabbed')
25 awful.hooks.user.create('tabdisplay')
26 awful.hooks.user.create('tabhide')
28 ---------------
29 -- Functions --
30 ---------------
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
38 if v == value then
39 return k
40 end
41 end
42 end
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
52 cl.hide = false
53 cl:swap(p)
54 p.hide = true
55 capi.client.focus = cl
56 awful.hooks.user.call('tabhide', p)
57 awful.hooks.user.call('tabdisplay', cl)
58 end
59 end
61 --- Check if the client is in the given tabindex.
62 -- @param tabindex The tab index.
63 -- @param cl The client
64 -- @return The key.
65 function tabindex_check(tabindex, cl)
66 local c = cl or capi.client.focus
67 return findkey(tabbed[tabindex][2], c)
68 end
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)
80 if me ~= nil then
81 return tabindex
82 end
83 end
85 return nil
86 end
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]
94 end
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)
122 if i == nil then
123 return nil
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)
142 if i == nil then
143 return nil
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.
156 function untab(cl)
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)
175 c.hide = false
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
183 c.hide = false
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)
218 if x == nil then
219 -- Add untabbed client to tabindex
220 table.insert(tabbed[tabindex][2], c)
221 display(tabindex, 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)
228 untab_all(x)
230 tabindex = tabindex_get(cc)
232 for i,b in pairs(clients) do
233 tab(tabindex, b)
239 --- Start autotabbing, this automatically tabs new clients when the current
240 -- client is tabbed.
241 function autotab_start()
242 awful.hooks.manage.register(function (c)
243 local sel = capi.client.focus
244 local index = tabindex_get(sel)
246 if index ~= nil then
247 -- Currently focussed client is tabbed,
248 -- add the new window to the tabbed display
249 tab(index, c)
251 end)
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
276 c.hide = true
278 tab[1].hide = false
280 else
281 -- unhide all clients
282 for i,tab in pairs(tabs) do
283 for i,c in pairs(tab[2]) do
284 c.hide = false
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
297 display(i, c)
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