1

I have two monitors and I would like to change client focused by shortcut. Right now I have awful.client.focus.byidx(1) but it only changes clients on one monitor. I know there is awful.client.focus.global_bydirection("right") that works on multiple screens but it only goes to one direction and it stops working when get to last client. I like awful.client.focus.byidx(1) behavior which loops through all clients, so from the last client it goes to the first one.

I would like to use a hybrid between: going through clients as in awful.client.focus.byidx(1) but on all monitors/screens like awful.client.focus.global_bydirection("right") does. Is there a function that would have that behavior so I could use it? If not, do you know how could I achieve that goal?

Arko
  • 13
  • 2

1 Answers1

1

First, let's look at how awful.client.focus.byidx is implemented.

The function itself calls awful.client.next and then focused the returned client, if any is found:

https://github.com/awesomeWM/awesome/blob/9781f14b105ee700c5bca339bf49bb52d2cca4b5/lib/awful/client/focus.lua#L65-L71

awful.client.next is implemented here: https://github.com/awesomeWM/awesome/blob/9781f14b105ee700c5bca339bf49bb52d2cca4b5/lib/awful/client.lua#L262-L284

It does the following:

  • line 263: Get the currently focused client
  • line 267: Get all visible clients on the screen of the visible client
  • line 270-274: Filter out unfocusable clients from the list
  • line 277 - 278: Find the focused client in the resulting list
  • line 280: Get the client at the wanted offset and return it

So, your request sounds like you only need to change one step here: Get the list of all visible clients instead of only those at the currently focused screen. To get that list, you need to call awful.client.visible with nil instead of a specific screen.

Untested code:

function next_global(i, sel, stacked)
  sel = sel or client.focus
  if not sel then return end
  local cls = awful.client.visible(nil, stacked)
  local fcls = {}
  for _, c in ipairs(cls) do
    if awful.client.focus.filter(c) or c == sel then
      table.insert(fcls, c)
    end
  end
  cls = fcls
  for idx, c in ipairs(cls) do
    if c == sel then
      return cls[gears.math.cycle(#cls, idx + i)]
    end
  end
end
function focus_byidx_global(i, c)
  local target = next_global(i, c)
  if target then
    target:emit_signal("request::activate", "client.focus.byidx", {raise=true})
  end
end

I don't know which version of AwesomeWM you are using. If in doubt, look at the installed files in /usr/share/awesome/lib/ and copy the code from there, then change it.

(A little more ugly solution would be something like the following, even though it requires less code; I leave it as an exercise to the reader to figure out what this does, but note that this "breaks stuff" in case a Lua error occurs and the monkey-patching becomes permanent)

function focus_byidx_global(i, c)
  local old = awful.client.visible
  awful.client.visible = function(_, s) return old(nil, s) end
  awful.client.focus.byidx(i, c)
  awful.client.visible = old
end
Uli Schlachter
  • 9,337
  • 1
  • 23
  • 39