Search code examples
awesome-wmtasklist

Grouping Windows in the tasklist


I'm currently using the icon-only style tasklist from here on all tags. This gives me a nice overview of everything that's running on my system. If I have a lot of programs running the taskbar tends to get messy rather quickly.

Taskbar

I was wondering if there's a way to group windows by class. To have for example all firefox windows next to each other, all terminals next to each other, etc. Another nice option might be to have them all stacked on top of each other - for example to have only 1 terminal icon in the taskbar that holds all terminal sub processes accessible in a popup menu. I tried to come up with something for both options but unfortunately it's beyond my knowledge :)

Any help would be appreciated!

Thanks in advance


Solution

  • Actually... yes this is kind of possible with the existing code. The function awful.widget.tasklist gets a table as its first argument. The entry source is used to get the list of clients that should be displayed (and filter is used to select only a subset of them, e.g. those on the currently selected tag).

    The default for source is awful.widget.tasklist.source.all_clients which just returns client.get() (all clients that exist). If you replace this with a function that only returns one client per class, then you'd get what you want.

    However, this could interact with the filter. For example, if you have XTerms one another tag and on the current tag, then filtering in the source function could mean that one selects the client on another tag and filter then gets rid of that as well. So, I guess it makes more sense to have the filter do this, but the filter does not see the list of all clients, but only a single one.

    One possible approach is to already call the filter in the source function. Untested sketch:

    s.mytasklist = awful.widget.tasklist {
        screen = s,
        filter = function() return true end, -- Filtering is already done in source
        source = function()
            -- Get all clients
            local cls = client.get()
    
            -- Filter by an existing filter function and allowing only one client per class
            local result = {}
            local class_seen = {}
            for _, c in pairs(cls) do
                if awful.widget.tasklist.filter.currenttags(c, s) then
                    if not class_seen[c.class] then
                        class_seen[c.class] = true
                        table.insert(result, c)
                    end
                end
            end
            return result
        end,
    }
    

    The above code would mean that only the first client of each class is displayed. If you want e.g. a popup menu to open when clicking an entry representing more than one class, you will some more code. This answer only handles the "look", not the "behaviour".