Yabai: Focus but ignore display boundary

Created on 8 Jul 2019  路  9Comments  路  Source: koekeishiya/yabai

I would like yabai to ignore display boundaries and am unsure how to augment the commands to achieve this with my calls from keyboard shortcuts.

For example, I have two displays next to eachother. If I am in display 1 and focus east and there is no eastern window, I would like it to foucs the display to the east and give me that window. (possibly a reasonable default is the westmost window there. But that would actually be inconvenient for me as my other display is vertically oriented, so I'd probably prefer having this just focus the most recently focussed window on this display).

I am unsure if yabai is aware of the spatial arrangement of the displays (as given in the Display preferences, and used by the mouse) so that may be one issue here. Though I would settle for a workaround being that the displays all wrap. i.e. if I focus west on the left display it wraps to the right display because it does not know their orientation. I don't know how feasible it would be to look at the display orientations in the preferences to avoid this.

Further, completely direction agnostic commands are limited by the displays. e.g. yabai -m window --focus prev could not locate the most recently focused window if it is from a different display. I suspect there is a way to get this to locate the most recently focused windows over all displays, possibly using query, but if there is an obvious way to achieve these display-agnostic behvaiours I would very much like to make use of them.

help wanted question

Most helpful comment

Cycling windows now works really well with the recent changes on master:

You can cycle forward by trying the following things, in order:

  • focus next window on focused space
  • focus first window on visible space on next display
  • focus first window on visible space on first display
  • focus next display
  • focus first display

I consider this issue resolved now.

# cycle forward
yabai -m window --focus next \
    || yabai -m window --focus "$( \
        (yabai -m query --spaces --display next || yabai -m query --spaces --display first) \
            | jq -re '.[] | select(.visible == 1)."first-window"')" \
    || yabai -m display --focus next \
    || yabai -m display --focus first

# cycle backwards
yabai -m window --focus prev \
    || yabai -m window --focus "$( \
        (yabai -m query --spaces --display prev || yabai -m query --spaces --display last) \
            | jq -re '.[] | select(.visible == 1)."last-window"')" \
    || yabai -m display --focus prev \
    || yabai -m display --focus last

All 9 comments

You can abuse the non-zero exit code when a command fails for custom wraparound.

# focus + cycle forwards across displays
# - try to focus next window
# - if that fails, move focus to the next display and focus its first window
# - if the next display cannot be found, do the same except focus the first display
yabai -m window --focus next \
    || ((yabai -m display --focus next || yabai -m display --focus first) \
        && yabai -m window --focus first)

Similarly for backwards cycling.

yabai -m window --focus prev \
    || ((yabai -m display --focus prev || yabai -m display --focus last) \
        && yabai -m window --focus last)

You can do the same thing for directions of course, although you will then have to hard-code prev/next for your displays. yabai has no knowledge about directions of your displays.

@koekeishiya this kind of ties in with your reply given in https://github.com/koekeishiya/yabai/issues/103#issuecomment-509325941.

Do you have any idea on how to focus the first window on a display without focusing another window on it first if that window was more recently focused?

You'll see the flickering when you try the above snippets while having 2+ windows on a monitor. It's not that big a deal and still a lot better than with chunkwm, but I see a possibility for improvement here.

Do you have any idea on how to focus the first window on a display without focusing another window on it first if that window was more recently focused?

The only way I imagine this could be fixed would be to

a) allow window --focus commands to operate across active spaces
b) allow display --focus x to take an optional selector y to identify the target window

@dominiklohmann Thanks, using these to get some of my desired behaviour established.

alt - x : yabai -m window --focus recent \
    || (yabai -m display --focus recent || yabai -m display --focus recent)
alt - h : yabai -m window --focus west \
    || (yabai -m display --focus first || yabai -m display --focus last)
alt - l : yabai -m window --focus east \
    || (yabai -m display --focus last || yabai -m display --focus first)

@jessebett your first one has some redundancy in it, just use this instead:

alt - x : yabai -m window --focus recent || yabai -m display --focus recent

Similarly, the brackets in your other commands are redundant as well.

It's just shell script syntax (sh / bash / zsh / fish... whatever your $SHELL is). So || usually means or, && means and and ; can be used to chain commands regardless of their output. (...) just groups commands.

@koekeishiya option b seems reasonable.

@dominiklohmann thanks I quickly added that one by absentmindedly changing the alt-h and alt-l ones, but yes I see that it is redundant. Thanks for the fix!

Honestly, I don't think that option b is viable. At least not in the long term.

While distinguishing focused/active/inactive is certainly harder to implement than focused/unfocused, why would you want to limit this to focus commands only? The thought should (in my opinion) be "I want to focus this window" and yabai should check whether its on a focused or a non-focused and active space and act accordingly, but it should not be "I want to focus this display鈥攁nd oh, please focus this specific window on it".

The user-facing syntax should be the same, whether the target window is on the focused space or a non-focused and active space.

Thinking long term, it might make more sense to allow window ids to be used as window selectors in WINDOW_SEL, as long as they are ids of windows on active spaces. This should then apply to swap/warp as well, and the same functionality could easily be used for mouse support across displays.

I realise this is a lot more work than option b, but I think it is the proper way鈥攁nd key to deliver a smooth integration with macOS that feels like it should be built-in.

The current syntax is yabai -m window [<window id>] <COMMAND>. With this change the optional window id could be changed to just an optional WINDOW_SEL as well.

Additionally, left click drag across monitors makes more sense as a warp action than a swap action, which should probably be available as an option.

I agree that option b above is not ideal; it was just one of the two possible ways to deal with this situation.

Honestly I don't see why focusing a window should be restricted at all. If I want to focus some window on space 4 on my 3rd display - I should be able to do so instantaneously regardless of whether the space is focused or not. However, to do this you need to refer to the window through its id. At this point we are getting fairly close to implementing something like a fuzzy-window switcher, and that is probably where this should be headed.

I imagine as you said - include window-id as a valid value for WINDOW_SEL and that will allow users to write an Alfred workflow or whatever they want that can retrieve windows - filter by display or spaces, and issue a focus command for said window.

Edit:
To be more precise - Focusing an arbitrary window is already supported, it just has to be exposed by allowing you to specify a target window-id.

I think something like this is best supported by giving the user the ability to script the behaviour on their own by giving them ways to retrieve enough information necessary to do so.

I would imagine this would be possible to do with the addition of window-id as a selector.
However this only holds true for passing focus between windows and not for other operations.

Cycling windows now works really well with the recent changes on master:

You can cycle forward by trying the following things, in order:

  • focus next window on focused space
  • focus first window on visible space on next display
  • focus first window on visible space on first display
  • focus next display
  • focus first display

I consider this issue resolved now.

# cycle forward
yabai -m window --focus next \
    || yabai -m window --focus "$( \
        (yabai -m query --spaces --display next || yabai -m query --spaces --display first) \
            | jq -re '.[] | select(.visible == 1)."first-window"')" \
    || yabai -m display --focus next \
    || yabai -m display --focus first

# cycle backwards
yabai -m window --focus prev \
    || yabai -m window --focus "$( \
        (yabai -m query --spaces --display prev || yabai -m query --spaces --display last) \
            | jq -re '.[] | select(.visible == 1)."last-window"')" \
    || yabai -m display --focus prev \
    || yabai -m display --focus last
Was this page helpful?
0 / 5 - 0 ratings

Related issues

mattsawyer77 picture mattsawyer77  路  4Comments

denisidoro picture denisidoro  路  4Comments

brentd picture brentd  路  4Comments

eraserhd picture eraserhd  路  4Comments

eramdam picture eramdam  路  3Comments