gvlasov
gvlasov

Reputation: 20025

How to set focus on a client under mouse cursor when a tag is changed?

When I switch to another tag, a new client gets selected, but it is sometimes not a client that I have my mouse cursor over. To get a client under my mouse pointer focused, I have to either click somewhere on it, or switch to it with Mod4+j / k, or move mouse cursor out and back on that client.

I want awesome to give focus to a client that is under the mouse cursor whenever a tag is changed. How do I do that?

I found a function mouse.object_under_pointer() that finds the client I need, but I don't know when to call that function. Should I connect a handler to some particular signal? I tried connecting to various signals from Signals page on the wiki and checking with naughty.notify() if that is the right signal, but none of them were triggered when I was switching between tags.

Upvotes: 4

Views: 1932

Answers (3)

David Sorkovsky
David Sorkovsky

Reputation: 1439

I know this is pretty old, but it helped me to come up with this

function focus_client_under_mouse()
    gears.timer( {  timeout = 0.1,
                    autostart = true,
                    single_shot = true,
                    callback =  function()
                                    local n = mouse.object_under_pointer()
                                    if n ~= nil and n ~= client.focus then
                                        client.focus = n end
                                    end
                  } )
end

screen.connect_signal( "tag::history::update", focus_client_under_mouse )

Upvotes: 2

Uli Schlachter
Uli Schlachter

Reputation: 9867

Two things should be done:

First, you should remove require("awful.autofocus") from your config, so that this module no longer tries to focus some client via the focus history when you switch tags.

Then, this code works for me:

do
    local pending = false
    local glib = require("lgi").GLib
    tag.connect_signal("property::selected", function()
        if not pending then
            pending = true
            glib.idle_add(glib.PRIORITY_DEFAULT_IDLE, function()
                pending = false
                local c = mouse.current_client
                if c then
                    client.focus = c
                end
                return false
            end)
        end
    end)
end

This uses GLib directly to get a callback for when no other events are pending. This should mean that "everything else" was handled.

Upvotes: 2

gvlasov
gvlasov

Reputation: 20025

This code did the trick, however there should be a better way to do this than setting up a huge 200 ms timer (smaller timeouts didn't properly focus some clients for me, but you can try setting a smaller one).

tag.connect_signal(
  "property::selected",
  function (t)
    local selected = tostring(t.selected) == "false"
    if selected then
      local focus_timer = timer({ timeout = 0.2 })
      focus_timer:connect_signal("timeout", function()
        local c = awful.mouse.client_under_pointer()
        if not (c == nil) then
          client.focus = c
          c:raise()
        end
        focus_timer:stop()
      end)
      focus_timer:start()
    end
  end
)

tag is this global object, so you should just place this code anywhere in your rc.lua.

Upvotes: 4

Related Questions