Awesome: Feature request: Provide capacity to switch windows by usage history

Created on 10 Jun 2020  Â·  5Comments  Â·  Source: awesomeWM/awesome

Output of awesome --version:
awesome v4.3 (Too long)
• Compiled against Lua 5.3.5 (running with Lua 5.3)
• D-Bus support: ✔
• execinfo support: ✔
• xcb-randr version: 1.6
• LGI version: 0.9.2

How to reproduce the issue:
[unapplicable]

Actual result:
[unapplicable]

Expected result:
[unapplicable]

Title is self descriptive. Currently we can switch between one window, and the last one used:
awful.key({ modkey, }, "Tab", function () awful.client.focus.history.previous() if client.focus then client.focus:raise() end end, {description = "go back", group = "client"}),

Why not make this applicable to all windows?

I can imagine the only issue here is the fact that windows are switched immediately on the _tab_ press. I would suggest to update history only on the release of the _mod_ key, not the _tab_ key.

Most helpful comment

There is an example on how to use the new keygrabber for this in the docs.
This is currently not working though as the functions select_previous and select_next don't exist yet (see #2636).

I suggest adding this to the default config once #2636 is resolved.

For now you can use this workaround without the non-existing functions:

-- Alt+Tab to cycle through recently focused clients

-- Id of currently selected client in history
local current_client
-- Number of visible clients
local num_clients
-- Client that was focused before Alt+Tab was pressed
local prev_focused

awful.keygrabber {
    keybindings = {
        awful.key {
            modifiers = {'Mod1'},
            key       = 'Tab',
            on_press  = function()
                -- Get next client
                current_client = (current_client + 1) % num_clients
                local c = awful.client.focus.history.get(awful.screen.focused(), current_client)
                if c then
                    -- Focus client
                    c:activate()
                end
            end,
            description = "Cycle through recently focused clients",
            group = "client"
        },
        awful.key {
            modifiers = {'Mod1'},
            key       = 'Escape',
            on_press  = function() 
                -- Focus previously focused client again
                prev_focused:activate() 
            end
        }
    },
    stop_key           = 'Mod1',
    stop_event         = 'release',
    start_callback     = function() 
        awful.client.focus.history.disable_tracking()
        current_client = 0
        num_clients = #awful.screen.focused().clients
        prev_focused = client.focus
    end,
    stop_callback      = function()
        awful.client.focus.history.enable_tracking()
        -- As client.focus was focused while history tracking was disabled, 
        -- it needs to be manually added to history
        awful.client.focus.history.add(client.focus)
    end,
    export_keybindings = true
}

This is the code that I wrote for my config and it's working fine so far.
I don't know of any more elegant solutions without having functions like select_previous and select_next, but I'd appreciate better suggestions.

All 5 comments

I think (but haven't tested) that calling awful.client.focus.history.disable_tracking() and enable_tracking() around the call to awful.client.focus.history.previous() is all that is needed to fix this. (I stumbled upon this function while investigating "which piece of code adds stuff to the focus history and how can one exempt .history.previous() from this?")

(Does anyone want to guess why these two functions are in client.lua and not client/focus.lua where they clearly belong according to their name?)

It gives an error: _attempt to call a nil value (global 'enable_tracking')_

There is an example on how to use the new keygrabber for this in the docs.
This is currently not working though as the functions select_previous and select_next don't exist yet (see #2636).

I suggest adding this to the default config once #2636 is resolved.

For now you can use this workaround without the non-existing functions:

-- Alt+Tab to cycle through recently focused clients

-- Id of currently selected client in history
local current_client
-- Number of visible clients
local num_clients
-- Client that was focused before Alt+Tab was pressed
local prev_focused

awful.keygrabber {
    keybindings = {
        awful.key {
            modifiers = {'Mod1'},
            key       = 'Tab',
            on_press  = function()
                -- Get next client
                current_client = (current_client + 1) % num_clients
                local c = awful.client.focus.history.get(awful.screen.focused(), current_client)
                if c then
                    -- Focus client
                    c:activate()
                end
            end,
            description = "Cycle through recently focused clients",
            group = "client"
        },
        awful.key {
            modifiers = {'Mod1'},
            key       = 'Escape',
            on_press  = function() 
                -- Focus previously focused client again
                prev_focused:activate() 
            end
        }
    },
    stop_key           = 'Mod1',
    stop_event         = 'release',
    start_callback     = function() 
        awful.client.focus.history.disable_tracking()
        current_client = 0
        num_clients = #awful.screen.focused().clients
        prev_focused = client.focus
    end,
    stop_callback      = function()
        awful.client.focus.history.enable_tracking()
        -- As client.focus was focused while history tracking was disabled, 
        -- it needs to be manually added to history
        awful.client.focus.history.add(client.focus)
    end,
    export_keybindings = true
}

This is the code that I wrote for my config and it's working fine so far.
I don't know of any more elegant solutions without having functions like select_previous and select_next, but I'd appreciate better suggestions.

This is a nice snippet! Good work :)

If it doesn't make its way to the default config, you should definitely add it to https://awesomewm.org/recipes/.

Thank you. I don't think this should make it to the default config though. It is just a workaround for missing API features.
The original code from the keygrabber docs should be added to the default config once the history API has been reworked.

Adding it to the recipes seems like a good idea as the history rework will probably not be finished soon.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Fybe picture Fybe  Â·  5Comments

SethBarberee picture SethBarberee  Â·  3Comments

doronbehar picture doronbehar  Â·  5Comments

batmanm0b1E picture batmanm0b1E  Â·  6Comments

vonpupp picture vonpupp  Â·  5Comments