5

I am using archlinux in combination with awesome-wm for quite a while now. I still haven't figured out how to automatically grab the focus on an application when changing workspace through Mod+number.

For example, I have firefox running on workspace 2 and some terminals on workspace 1. If I am in workspace 2 and press Mod+1 to go to workspace 1, no terminal is focussed. I can ofcourse click on a terminal to grab focus, or press Mod+j or Mod+k, but I would like this to happen automatically.

How can I make this possible? Thanks in advance!

Carlito
  • 233

7 Answers7

5

I figured it out so I will answer my own question. This might not be the best or most efficient way, but it gets the job done. This question might fit more on stackoverflow since it is more focussed on programming.

I wrote this function, which grabs focus on the first client on screen (except for Conky, the system monitor I use).

-- Grab focus on first client on screen
function grab_focus()
    local all_clients = client.get()
    for i, c in pairs(all_clients) do
        if c:isvisible() and c.class ~= "Conky" then
            client.focus = c
        end
    end
end

I now call this function in rc.lua where the numbered keys are mapped:

-- Bind all key numbers to tags.
...
if tags[screen][i] then
    awful.tag.viewonly(tags[screen][i])
    grab_focus()
end
Carlito
  • 233
1

Thank you very much Carlito, I've been struggling around the whole afternoon to solve this problem, and your function works perfectly.

I just call it by itself "grab_focus()" into the keybinding "for" cycle I want to.

I use Awesome 3.5 with Shifty, this is how I fixed it (please notice "grab_focus()"):

-- Bind all key numbers to tags.
-- Be careful: we use keycodes to make it works on any keyboard layout.
-- This should map on the top row of your keyboard, usually 1 to 9.

   for i = 1, (shifty.config.maxtags or 9) do
    globalkeys = awful.util.table.join(globalkeys,
        awful.key({ modkey }, "#" .. i + 9,
                  function ()
                      awful.tag.viewonly(shifty.getpos(i))
                      grab_focus()
                end),
        awful.key({ modkey, "Control" }, "#" .. i + 9,
                  function ()
                      awful.tag.viewtoggle(shifty.getpos(i))
                  end),
        awful.key({ modkey, "Shift" }, "#" .. i + 9,
                  function ()
                      if client.focus then
                          local t = shifty.getpos(i)
                          awful.client.movetotag(t)
                          awful.tag.viewonly(t)
                       end
                  end),
        awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
                  function ()
                      if client.focus then
                          awful.client.toggletag(shifty.getpos(i))
                      end
                  end))
end
Federico
  • 11
  • 1
1

I found the previously mentioned method to work poorly on multiscreen setups as the isvisible check also checks other screens.

After looking around the API documentation I arrived at this solution

Disclaimer: I don't have much experience with awesome and this is my first attempt at doing anything that isn't a copy-paste. So far for me it is working nicely though.

for k,t in pairs(awful.tag.gettags(s)) do t:connect_signal("property::selected", function(t) local c = t.clients(t)[1] if c then client.focus = c end end) end

where 's' is the screen. Do this for each screen. I have it in the same loop as tag setup in the standard rc.lua.

Basically loop through the tags of a screen and add an event listener for when the tag gets selected, which then fires the function which gets the first client connected to the tag and sets it as the focused client.

I am using awesome 3.5 and there are some differences to be aware of if you are using previous versions. In 3.4 for example the connect_signal function is named add_signal.

This solution automatically works when switching tags through other means to as it connects a listener to the operation of switching tags itself.

Reaver
  • 111
0

I use something like this to grab automatically focus on tag change

tag.connect_signal("property::selected", function() focus_on_last_in_history(mouse.screen) end)

and this one to refocus when closing a window on a tag

client.connect_signal("unmanage", function() focus_on_last_in_history(mouse.screen) end)

function focus_on_last_in_history( screen )
  local c = awful.client.focus.history.get(screen, 0)
  if not (c == nil) then
    client.focus = c
    c:raise()
  end
end
0

With the latest 4.0 version of awesome, none of these solutions were working.

Here is one that will automatically focus whichever client is under your mouse whenever you switch tags/workspaces.

tag.connect_signal("property::selected", function (t)
    local selected = tostring(t.selected) == "true"
    if selected then
        local mouseX = mouse.coords().x
        local mouseY = mouse.coords().y
        for k,v in pairs(t.screen.all_clients) do
            if v.first_tag.index==t.index and mouseX>=v.x and mouseX<=(v.x+v.width) and mouseY>=v.y and mouseY<=(v.y+v.height) then
                client.focus = v
                v:raise()
            end
        end
    end
end)
CJM
  • 2,627
Sembiance
  • 161
0

All the solutions above were not working reliably for me, probably due to the double-monitor and my weird tag setup...

This is my solution, which should work in all cases as it directly uses the windows on the focused screen and does not look at the tag clients:


-- auto-focus a client when switching tag
awful.tag.attached_connect_signal(
   nil,
   "property::selected",
   function(t)
      focus_on_last_in_history(awful.screen.focused())
   end
)

-- auto-focus on the next client in history when closing a window client.connect_signal("unmanage", function() focus_on_last_in_history(awful.screen.focused()) end)

-- utility function used for both cases above. function focus_on_last_in_history( screen ) local c = awful.client.focus.history.get(screen, 0) if not (c == nil) then client.focus = c c:raise() end end

0

What I don't like with these solutions is that they don't always focus the client under the mouse.

The best solution I found is that script that you just have to put in your rc.lua :

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)
mperrin
  • 616