Hello, i reloaded tabulous from heaven.
The first patch is tabulous itself. The second one is a patch against tasklist to display something like Tab[1/3] in the name of tabbed client. I wonder if awful.tab would be a better and standard name than tabulous. I refactored tabulous and tried to cleanup the code at the maximum. I removed the hook on tag. I cant find a utility to that one (was unhidding client not in the first selected tag). Am I wrong? Now the code support multiple tag. The autotab_start feature seem's wrong when using teardrop for example. I dont think it's the good way to implement it, as well as the function was there before with the same implementation. I should I get ride of it? (maybe this belong to a user modified rc.lua) There is a little issues with tab, when switching from one tab to another there is a little flickering and sometime focus is not on the good client. I thing lua/c hacking is needed to remove it, and I dont know Awesome so well to do that for now. Because now the following happens: --keep the client at the same place cl:swap(p) --ouch cl.hidden = false --double ouch p.hidden = true --Bang! (insert a little sleep here and the focus is always good) capi.client.focus = cl I would like to display a new tabbar upside the client window to switch between each client in a tab, but I wonder if it would not be better to wait for the $FS542 ? Titlebar seems a little broken in HEAD.
From f5e9914753733b7f743e6553930f18637349dc5c Mon Sep 17 00:00:00 2001 From: Cedric GESTES <cta...@gmail.com> Date: Fri, 28 Aug 2009 03:20:35 +0200 Subject: [PATCH] tabulous : fixed, improved and imported again Signed-off-by: Cedric GESTES <cta...@gmail.com> --- lib/tabulous.lua.in | 384 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 384 insertions(+), 0 deletions(-) create mode 100644 lib/tabulous.lua.in diff --git a/lib/tabulous.lua.in b/lib/tabulous.lua.in new file mode 100644 index 0000000..e837f6b --- /dev/null +++ b/lib/tabulous.lua.in @@ -0,0 +1,384 @@ +--------------------------------------------------------------------------- +-- @author Lucas de Vries <lucasdevr...@gmail.com> +-- @author Julien Danjou <jul...@danjou.info> +-- @author Cedric GESTES <cta...@gmail.com> +-- @copyright 2008 Julien Danjou, Lucas de Vries +-- @copyright 2009 Cedric GESTES +-- @release @AWESOME_VERSION@ +--------------------------------------------------------------------------- + +------------------------ +--- Samples keybindings: +-- --- Tabulous, tab manipulation +-- <code> +-- globalkeys = awful.util.table.join(globalkeys, +-- -- remove the focused client from the tab +-- awful.key({ modkey, "Shift" }, "y", tabulous.tab_remove), +-- -- cycle through clients in a tab +-- awful.key({ modkey, }, "y", tabulous.tab_cycle), +-- -- create a new tab and/or add the next client to the tab +-- awful.key({ modkey, "Control" }, "y", tabulous.tab_add_next_client), +-- -- create a tab from all marked clients +-- awful.key({ modkey, 'Shift' }, "t", tabulous.tab_create_from_marked) +-- ) +-- </code> +-- the autotab_start function can be used to append client to the current tab +-- when a client is created and the current focused client is tabbed + +-------------------- +--- Emitted Signals: +-- client:("tabbed") when a client is added to a tab +-- client:("untabbed") when a client is removed from a tab +-- client:("tabhide") when a client is hidden in a tab +-- client:("tabshow") when a client is shown in a tab + +-------------------------- +--- Possible Improvements: +-- the tab_display function is not perfect (there is flickering) + + +--------------------------------------------------------------------------- +local table = table +local pairs = pairs +local setmetatable = setmetatable +local aclient = require("awful.client") +local atag = require("awful.tag") +local util = require("awful.util") + +local capi = { + client = client, +} + +--- Fabulous tabs +module("tabulous") + +-- the tabs table indexed by tabindex +-- for each tab there is a tabs[x] there is: +-- x is the tabindex +-- tabs[x].active is the active client in the tab +-- tabs[x].clients is the list of clients in the tab +local tabs = {} + + +------------------------------ +-- Client Helper -- +------------------------------ + + +--- Check if the client is in the given tabindex. +-- @param tabindex The tab index. +-- @param cl The client +-- @return The key. +function client_index(tabindex, cl) + local c = cl or capi.client.focus + return util.table.hasitem(tabs[tabindex].clients, c) +end + +--- Find the tab index or return nil if not tabs. +-- @param cl The client to search. +-- @return The tab index. +function client_tabindex(cl) + local c = cl or capi.client.focus + + for tabindex, tabdisplay in pairs(tabs) do + -- Loop through all tab displays + local me = client_index(tabindex, c) + if me ~= nil then + return tabindex + end + end + return nil +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 client_get(tabindex, pos) + if tabs[tabindex] == nil then return nil end + return tabs[tabindex].clients[pos] +end + + + + + +------------------------------ +-- Tab Handling -- +------------------------------ + + +--- 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 + + local t = {} + t.active = c + t.clients = { c } + table.insert(tabs, t) + c:emit_signal("tabbed") + return client_tabindex(c) +end + +-- Get the number of client in a tab +-- @param tabindex The tab index. +-- @return the number of client in a tab +function tab_count(tabindex) + if tabs[tabindex] == nil then + return 0 + end + return table.getn(tabs[tabindex].clients) +end + +--- Get all clients on a tabs display. +-- @param tabindex The tab index. +-- @return All tabs clients. +function tab_clients(tabindex) + if tabs[tabindex] == nil then return nil end + return tabs[tabindex].clients +end + + + +--- Get the displayed client on a tabs display. +-- @param tabindex The tab index. +-- @return The displayed client. +function tab_current(tabindex) + if tabs[tabindex] == nil then return nil end + return tabs[tabindex].active +end + +--- Get the next client in a tab display. +-- @param tabindex The tab index. +-- @param cl The current client. +-- @return The next client. +function tab_next(tabindex, cl) + local c = cl or tabs[tabindex].active + local i = util.table.hasitem(tabs[tabindex].clients, c) + + if i == nil then + return nil + end + if tabs[tabindex].clients[i + 1] == nil then + return tabs[tabindex].clients[1] + end + return tabs[tabindex].clients[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 tab_prev(tabindex, cl) + local c = cl or tabs[tabindex].active + local i = util.table.hasitem(tabs[tabindex].clients, c) + + if i == nil then + return nil + end + if i == 1 then + return tabs[tabindex].clients[table.maxn(tabs[tabindex].clients)] + end + return tabs[tabindex].clients[i - 1] +end + +--- Remove a client from a tabs display. +-- @param cl The client to remove. +-- @return True if the client has been untabs. +function tab_remove(cl) + local c = cl or capi.client.focus + local tabindex = client_tabindex(c) + + if tabindex == nil then + return false + end + local cindex = util.table.hasitem(tabs[tabindex].clients, c) + if tabs[tabindex].active == c then + tab_display(tabindex, tab_next(tabindex, c), false) + end + table.remove(tabs[tabindex].clients, cindex) + if table.maxn(tabs[tabindex].clients) == 0 then + -- Table is empty now, remove the tabs display + table.remove(tabs, tabindex) + end + c.hidden = false + c:emit_signal("untabbed") + return true +end + +--- Untab all clients in a tabs display. +-- @param tabindex The tab index. +function tab_removeall(tabindex) + for i,c in pairs(tabs[tabindex].clients) do + c.hidden = false + c:emit_signal("untabbed") + end + if tabs[tabindex] ~= nil then + table.remove(tabs, tabindex) + end +end + +--- Add a client to a tabs display. +-- @param tabindex The tab index. +-- @param cl The client to add, or the focused one otherwise. +function tab_add(tabindex, cl) + local c = cl or capi.client.focus + + if tabs[tabindex] == nil then + return + end + local x = client_tabindex(c) + if x == nil then + -- Add untabbed client to tabindex + table.insert(tabs[tabindex].clients, c) + tab_display(tabindex, c) + c:emit_signal("tabbed") + elseif x ~= tabindex then + -- Merge two tabbed views + local cc = tabs[tabindex].active + local clients = tab_clients(x) + tab_removeall(x) + tabindex = client_tabindex(cc) + for i,b in pairs(clients) do + tab_add(tabindex, b) + end + end +end + + +--- Swaand select which client in tab is displayed. +-- @param tabindex The tab index. +-- @param cl The client to show. +-- this is not perfect in fact swap/hidden/hidden/focus should be done +-- at the same time to avoid flicking +function tab_display(tabindex, cl, swap) + local p = tabs[tabindex].active or cl + if cl and p ~= cl then + tabs[tabindex].active = cl + + --dont swap when removing client + if swap ~= false then + cl:swap(p) + end + cl.hidden = false + p.hidden = true + + p:emit_signal("tabhide") + cl:emit_signal("tabshow") + capi.client.focus = cl + 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 tab_focus(cl) + local c = cl or awful.client.focus + local i = client_tabindex(c) + + if i and tabs[i].active ~= c then + tab_display(i, c) + end +end + + +------------------------------ +-- Helper Function -- +------------------------------ + + + +--- cycle throught tab clients +-- @param cl The client to that own the tab +-- @param the way to cycle (-1 or 1) +function tab_cycle(cl, idx) + local c = cl or capi.client.focus + local i = idx or 1 + local tabview = client_tabindex(c) + + if tabview == nil then + return + end + if i == 1 then + n = tab_next(tabview) + else + n = tab_prev(tabview) + end + tab_display(tabview, n) +end + + +--- create a tab or add the next focused client to the tab +function tab_add_next_client() + local tabview = client_tabindex() + local nextclient = aclient.next(1) + + if not tabview then + tabview = client_tabindex(nextclient) + + if not tabview then + tabview = tab_create() + tab_add(tabview, nextclient) + else + tab_add(tabview, capi.client.focus) + end + else + tab_add(tabview, nextclient) + end +end + +--- create a new tab from all marked client +function tab_create_from_marked() + local tabview = client_tabindex() + local clients = aclient.getmarked() + + if not tabview then + tabview = tab_create(clients[1]) + table.remove(clients, 1) + end + + for k,c in pairs(clients) do + tab_add(tabview, c) + end +end + + +--- Start autotabbing, this automatically tabs new clients when the current +-- client is tabbed. +function autotab_start() + capi.client.add_signal("manage", function (c, startup) + local sel = capi.client.focus + local index = nil + + --if the current client is already focused => get prev from history + if sel == c then + sel = aclient.focus.history.get(c.screen, 1) + end + + index = client_tabindex(sel) + + --do nothing on startup + if startup then + return + end + if index ~= nil then + -- Currently focused client is tabbed, + -- add the new window to the tabbed display + tab_add(index, c) + end + end) +end + + +-- Keep tabulous in sync when a client is focused but was hidden in a tab +capi.client.add_signal("focus", tab_focus) + +-- rearrange the tab when a window is killed +capi.client.add_signal("unmanage", tab_remove) + + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 -- 1.6.0.4
From b9b7b9ecb2563c30a9781b341ca27f931b07b7ba Mon Sep 17 00:00:00 2001 From: Cedric GESTES <cta...@gmail.com> Date: Fri, 28 Aug 2009 02:52:48 +0200 Subject: [PATCH] tasklist : display Tab[i/c] in the name if the client is tabbed Signed-off-by: Cedric GESTES <cta...@gmail.com> --- lib/awful/widget/tasklist.lua.in | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/lib/awful/widget/tasklist.lua.in b/lib/awful/widget/tasklist.lua.in index 448a38d..ac70979 100644 --- a/lib/awful/widget/tasklist.lua.in +++ b/lib/awful/widget/tasklist.lua.in @@ -18,10 +18,17 @@ local client = require("awful.client") local util = require("awful.util") local tag = require("awful.tag") local layout = require("awful.widget.layout") +local atab = require("tabulous") +local tostring = tostring --- Tasklist widget module for awful module("awful.widget.tasklist") +-- configuration +display = {} +display.tab = true + + -- Public structures label = {} @@ -103,6 +110,15 @@ local function widget_tasklist_label_common(c, args) else name = util.escape(c.name) or util.escape("<untitled>") end + + local tabidx = atab.client_tabindex(c) + if display.tab and tabidx then + local tabcount = atab.tab_count(tabidx) + local cidx = atab.client_index(tabidx, c) or 0 + local tabtext = "Tab[" .. tostring(cidx) .. "/" .. tostring(tabcount) .. "] " + name = tabtext .. name + end + if capi.client.focus == c then bg = bg_focus if fg_focus then -- 1.6.0.4