stackline icon indicating copy to clipboard operation
stackline copied to clipboard

yabai -m display --focus does not work for the displays with stacks

Open Fouer opened this issue 3 years ago • 16 comments

Hey guys, just found an annoying issue. Once I create a stack at any monitor, I can no longer focus it with -m display --focus command, focus just disappears. Any solutions?

Fouer avatar Jan 31 '21 20:01 Fouer

I encountered this issue too, and disabling Hammerspoon via yabai does not resolve this.

narze avatar Feb 17 '21 05:02 narze

I have just started with yabai and stackline. So far this is what I've found:

  • It seems that if you have a stack and are busy with it.
  • then you try and switch displays, and when you do hammerspoon becomes the "active" application (which has no windows) so you have actually switched displays, but hammerspoon has grabbed the focus (which is why the previous window in the intial display is no longer focused), so you are stuck until you click on a window. Otherwise you can switch displays all you want and nothing will happen.
  • And the really annoying thing about this is that in your Cmd-tab list, hammerspoon is there at the front, so you will have it interfering anytime you switch screens, until you do a bunch of Cmd-tab'bing to send it to the end of the list.
  • But as soon as you do another display switch (which I do all the time) it is back in your face again.
  • Hiding hammerspoon makes the problem go away, but then hammerspoon is inactive and stackline is gone which is the only reason I have it on my machine in the first place. ☹️ Killing the hammerspoon app does the same.
  • The strange thing is I don't know exactly what triggers it to do this, because when I start, and am stacking windows etc. it works perfectly well, and then it suddenly steals the focus, and from then on it is game over.

I don't know if there is a way to make hammerspoon run in a daemon mode, or not as a mac app, but that might help. But until there is a solution, I'm going to have to say sayonara to hammerspoon and hackline, and guess at what is in each stack.

rohni avatar Mar 26 '21 14:03 rohni

Thanks for the report @Fouer .

Aha… I never use yabai -m display --focus, so didn't encounter this.

I will try to reproduce this weekend, and might be able to exclude Hammerspoon from the window filter in Stackline to resolve this.

AdamWagner avatar Jun 10 '21 02:06 AdamWagner

Bad news everyone: I don't see a clear path toward fixing this.

I can reproduce it when using multiple displays. That said, I don't think I can fix this at the "stackline" level – the issue appears to live at the intersection between yabai & hammerspoon.

Things I tried:

  1. Using yabai -m signal --add to listen for display_changed to focus the largest window on the display after it is focused. When hammerspoon is running & the current space has a stack, it's as if no display is focused after running yabai -m display --focus N
  2. Using Hammerspoon's hs.spaces.watcher module to listen for changes in the active space and focus the largest window on the active space. This event isn't even triggered when the space is changed using yabai -m display focus N.

I really appreciate the detail notes @rohni. While this doesn't fix this issue, I thought you might like to know that you can hide Hammerspoon in the doc and from cmd+tab by unchecking "Show doc icon" Screenshot 2021-06-10 at 20 44 03@2x

AdamWagner avatar Jun 11 '21 03:06 AdamWagner

I was able to work around this by sending Hammerspoon below everything else:

yabai -m rule --add app="Hammerspoon" manage=off layer="below"

but note this makes using the Hammerspoon console difficult as it will appear under every other window.

blefevre avatar Feb 10 '22 06:02 blefevre

@AdamWagner I have also hit this issue. If I remove stackline from ~/.hammerspoon/init.lua the issue goes away, so does not look to be solely a HS issue.

jacktuck avatar Mar 06 '22 12:03 jacktuck

I think @rohni was on to something. I have hammerspoon disabled in the dock and menu but when focusing a space on first display the focus changes to hammerspoon (which is not open on this space).

I set hs.logger.setGlobalLogLevel("verbose") to get this output

2022-03-06 13:02:45:                          emitting windowFocused 11145 (Hammerspoon)
2022-03-06 13:02:45:                              iTerm2 <= deactivated (app event)

I have @blefevre's Yabai rule but didn't seem to help.

jacktuck avatar Mar 06 '22 13:03 jacktuck

I wrote a workaround with @koekeishiya's help. If you focus on window ID and not display you avoid the bug where Stackline steals focus.

ctrl - left: yabai -m window --focus west || \
             yabai -m window --focus $(yabai -m query --spaces --display west | jq '.[] | select(."is-visible" == true) | ."last-window"')

ctrl - right: yabai -m window --focus east || \
              yabai -m window --focus $(yabai -m query --spaces --display east | jq '.[] | select(."is-visible" == true) | ."first-window"')

ctrl - up: yabai -m window --focus north || \
           yabai -m window --focus stack.prev || \
           yabai -m window --focus stack.last

ctrl - down: yabai -m window --focus south || \
             yabai -m window --focus stack.next || \
             yabai -m window --focus stack.first

diocletiann avatar Apr 19 '22 01:04 diocletiann

You can also use this method to stack across displays:

ctrl + alt + cmd - left : yabai -m window west --stack $(yabai -m query --windows --window | jq -r '.id') || \
    yabai -m window $(yabai -m query --spaces --display west | jq '.[] | select(."is-visible" == true) | ."last-window"') --stack $(yabai -m query --windows --window | jq -r '.id')

ctrl + alt + cmd - right : yabai -m window east --stack $(yabai -m query --windows --window | jq -r '.id') || \
    yabai -m window $(yabai -m query --spaces --display east | jq '.[] | select(."is-visible" == true) | ."first-window"') --stack $(yabai -m query --windows --window | jq -r '.id')

diocletiann avatar Apr 19 '22 15:04 diocletiann

None of the solutions from here worked for me, but adding the following to ~/.config/yabai worked for me:

# focus window after active space changes
yabai -m signal --add event=space_changed action="yabai -m window --focus \$(yabai -m query --windows --space | jq .[0].id)"

# focus window after active display changes
yabai -m signal --add event=display_changed action="yabai -m window --focus \$(yabai -m query --windows --space | jq .[0].id)"

Source: https://github.com/koekeishiya/yabai/issues/719#issuecomment-728140216

devnoname120 avatar Jul 11 '22 13:07 devnoname120

So the first index in the array is always the most recent window in in that space?

diocletiann avatar Jul 11 '22 14:07 diocletiann

@restfuladi It's not explicitly documented but in my limited testing it seems to work.

devnoname120 avatar Jul 11 '22 14:07 devnoname120

So the first index in the array is always the most recent window in in that space?

@restfuladi I can confirm that my command does not always solve the issue :(

devnoname120 avatar Jul 12 '22 08:07 devnoname120

So the first index in the array is always the most recent window in in that space?

@restfuladi I can confirm that my command does not always solve the issue :(

You can "yabai -m query --spaces --display (direction)" then focus on "first-window" or "last-window". That's what I do and it works well.

diocletiann avatar Jul 13 '22 15:07 diocletiann

@restfuladi

I have two issues when using your approach:

  • If I switch to a space and then back to the previous space the previously focused window loses focus.
  • Floating windows always get relegated behind managed windows.

Here is my code

# focus window after active space changes
yabai -m signal --add event=space_changed action="yabai -m window --focus \$(yabai -m query --spaces | jq '.[] | select(.\"is-visible\" == true) | .\"first-window\"')"


# focus window after active display changes
yabai -m signal --add event=display_changed action="yabai -m window --focus \$(yabai -m query --spaces | jq '.[] | select(.\"is-visible\" == true) | .\"first-window\"')"

devnoname120 avatar Jul 24 '22 20:07 devnoname120

I built upon @blefevre's solution and I can confirm that everything works perfectly now 👌

yabai -m signal --add event=window_created title="Hammerspoon Console" action="yabai -m window \$(yabai -m query --windows | jq -e '.[] | select(.app==\"Hammerspoon\" and .title==\"Hammerspoon Console\") | .id') --minimize"
yabai -m rule --add app="Hammerspoon" title="" manage=off layer="above" sticky=on

Explanations:

  • The first line makes sure that when Hammerspoon Console is opened for the first time it gets minimized immediately.
  • The second line makes sure that stackline is always visible and can be interacted with, without stealing the focus.

If it doesn't work for you, you can alternatively use this solution:

yabai -m rule --add title="Hammerspoon Console" manage=off layer="below"
yabai -m rule --add app="Hammerspoon" title="" manage=on layer="above" sticky=on

devnoname120 avatar Jul 24 '22 21:07 devnoname120