stackline
stackline copied to clipboard
yabai -m display --focus does not work for the displays with stacks
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?
I encountered this issue too, and disabling Hammerspoon via yabai does not resolve this.
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.
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.
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:
- Using
yabai -m signal --add
to listen fordisplay_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 runningyabai -m display --focus N
- 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"
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.
@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.
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.
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
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')
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
So the first index in the array is always the most recent window in in that space?
@restfuladi It's not explicitly documented but in my limited testing it seems to work.
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 :(
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.
@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\"')"
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