New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stacking support #203
Comments
A flexible implementation of this has a lot to offer. Obviously this can already be done using a combination of signals, rules and queries—similar to my monocle mode implementation from #83—but I personally think that yabai has a lot to gain from this if implemented properly. I'm imagining a syntax like this: # stack source window on target window
yabai -m window [<source window selector>] --stack <target window selector>
# the next window gets inserted stacked on top of the source window
# the window command --insert currently supports <DIR_SEL>
yabai -m window [<source window selector>] --insert stack Which would make the source window occupy the same frame and node as the target window. A window could be taken out of a stack through any means that reinserts it, e.g. a warp command. What still needs to be discussed is how window selectors interact with stacked windows: Should directional selectors ( How should stacked windows display? Should there be an overlap, e.g. the lowest window of the stack using the full height of the stack, the 2nd lowest has its frame start a set amount of pixels lower, the 3rd lowest has its frame start twice the set amount of pixels lower and so on? That way, mouse support would not be compromised. I would suggest using 22pt here, which is the height of the menu bar. Some form of stacking could also be the foundation for fixing #68 (would require the internals to be changed in a similar way anyways) and would allow a more robust implementation of a monocle mode, and many more custom ways to tile windows like suggested in #98. Thoughts @koekeishiya? |
I do see the use case for this type of window management, but I am currently not interested in attempting to implement this. I would not be against a well thought out PR that integrates this nicely if anyone wants to give it a shot on their own. |
Just to share some explanation on why I think this is a very VERY useful feature (for me at least): I'm trying to use amethyst right now but the closest I was able to get is a huge pain in comparison to i3. Mostly because it's very hard to identify which window I want to switch to. They all look almost the same and titles are not well exposed. |
To clarify, my main issue with this is not inherently the functionality by itself. It is the fact that macOS does not actually expose the functionality necessary for me to implement the various solutions that would make this a good experience, and so I'm reluctant to spend too much of my time dealing with their garbage. I have this in the back of my mind and iterate on possible solutions that could work, but this is not as simple to solve as it would be with e.g the X windowing system. |
Implemented basic logic and structure necessary for stacking windows. Directional selectors will ignore the additional stacked windows belonging to a node (meaning that they will target the currently focused window in the stack). Stacked windows are not cascaded; their region overlap as is. If a stacked window activates parent zoom or fullscreen zoom, that operation will simultaneously apply to all windows in the same stack. To make a window share node/region with some managed window, use the following command:
To un-stack a window, simply perform a warp operation using With the exception of mouse integration, swap operations should work as it always has. If a stacked window is moved to a different space/display, enters fullscreen, or any operation that would make this window become unmanaged, that operation will only affect that window and it will be removed from the stack. Remaining things that need to be implemented/solved:
|
I would like to be able to perform operations (warp, swap, resize) on a stack, but I’m not sure how to indicate that the stack is what’s selected, not a window inside of it. I suppose resize is no issue—just let the stack inherit sizing from the top (focused) window.
Cycling through the stack with prev/next sounds good to me.
I believe so, yes. Would be odd to be able to focus a window underneath that’s not visible. Moving focused window to the top is also consistent with mouse UI behavior in floated or un-managed windows that layer over one another. But I think what you may be getting at is how to represent the behavior in the tree. Do you want to do so by index in the array of stacked windows (meaning you have to modify that array every time a different window is focused), or track it another way? I’m not sure which way would be best, but I’m happy to discuss and think about it. |
With the current implementation all operations that affect the node tree will apply to the entire stack, except for warp operations where the stacked window is the source operand. You can still warp a non-stacked window onto a stack and it will split the stack using the elected parameters. The
That's pretty much it, yeah. Visually, the window will be at the top of the stack of course. |
I think maintaining order separately from focus will allow you to have an API that is also compatible for managing a tabbed UI. |
I would say as a new command/selector, as this would allow the user to define something like this:
Which would make selecting stacked windows similar to that of the i3 behaviour. On the same topic, I’d say that an important aspect of making this feature easy to use, would be to give the user visual cues for what effects the navigating the stack will have. This could be achieved by introducing cascading of stacked windows, allowing the user to specify a window region offset defined in This might introduce complexities regarding zooming stacked windows, however. |
Cascading is not really something that I consider a good solution because a lot of windows on macOS have size constraints, and this kind of feature will fall apart quickly when more than a couple of windows get stacked. I don't think upwards/downwards are intuitive names. Sure, it is a stack (maybe group would be a better term), but if you are on window 1 out of 3, and go "downwards", window 2 gets focus and is moved to the top (visually), and then intuitively "downwards" feels like it would re-focus window 1, because it is now below window 2 and above window 3. |
Agreed, downwards/upwards certainly aren’t the best descriptors. Dedicated descriptors is probably the way to go though, I believe. On the topic of cascading. My use case with yabai, is that I only tile whitelisted applications. I do this because most windows simply cannot be tiled properly. Either they’re too large or too small. If I whitelist only the applications I want to have tiled, and which I know can be resized, I can have an experience that feels less hacky. I’m sure I’m in the minority in regards to this. But with such a use case, cascading the windows certainly makes sense. Now I’m getting a bit off topic, but is this use case something you might be interested in supporting more fully in the future (There are some things which doesn’t align well with this idea right now)? If so, I’d be happy to work on that, including optionally adding cascading support to stacked windows. |
One thing I'd like to see for this is mouse support à la #142. Maybe there should be an option to have the center drag be |
stacked windows cannot be reordered currently. |
Sorry, its a long thread and didn't have time to quite go through all of it. Is it now possible to have two stacks on a screen and use hotkeys to navigate each? |
yes, you can do it |
Thanks for this new mode! Is there a way to make this work? I can't seem to find the right combination or ordering (allow cycling through both BSP and stack mode):
|
@peppy Is this what you are trying to do?
It's not possible to have a single bind that can both navigate between windows and also cycle within a stack (that's what your sample above looks like it wants to do). |
I'm trying to do the thing you say is not possible, yeah. Since I was trialling having some layouts BSP and some stacking. Thanks for confirming, I guess I'll need to maintain two binds for now. |
What's the command to do this? |
|
Thank you! |
@koekeishiya, do you mind explaining to me? I don't know but cycling through windows in bsp and stack suddenly works for me with just one keybinding. In the short clip above, I have:
|
Sorry for not being aware of this thread before the mention, this really should've gone into a new issue asking how to have a single keybind for cycling instead of repurposing this thread. Here's how I do it: # forward
yabai -m query --spaces --space \
| jq -re ".index" \
| xargs -I{} yabai -m query --windows --space {} \
| jq -sre "add | map(select(.minimized != 1)) | sort_by(.display, .frame.y, .frame.x, .id) | reverse | nth(index(map(select(.focused == 1))) - 1).id" \
| xargs -I{} yabai -m window --focus {}
# backward
yabai -m query --spaces --space \
| jq -re ".index" \
| xargs -I{} yabai -m query --windows --space {} \
| jq -sre "add | map(select(.minimized != 1)) | sort_by(.display, .frame.y, .frame.y, .id) | nth(index(map(select(.focused == 1))) - 1).id" \
| xargs -I{} yabai -m window --focus {} This is a slight deviation from my snippet someone posted earlier with a fix for minimized windows. I've been using this myself and it works as expected. The reason why this works is because it doesn't try to focus the visible window on a stack, but rather performs a stable sort on all windows of the space and just focuses the next entry in the sorted list (with wraparound). |
@dominiklohmann, I just tried it, and it worked perfectly. This snippet deserve to be listed on Wiki Page Tips and Tricks. |
Shout-out! - Very nice contribution. Is there a way to unstack only a single window? |
@stefandeml what about |
sweet - indeed, that does the job. Thanks |
Found koekeishiya/yabai#203 (comment) which will cycle through the current windows instead of just stopping.
bliss koekeishiya/yabai#203 (comment) Signed-off-by: Kipras Melnikovas <kipras@kipras.org>
bliss koekeishiya/yabai#203 (comment) Signed-off-by: Kipras Melnikovas <kipras@kipras.org>
Apply to yabai yabai-v4.0.0
|
Hi @kola-web
Not working? |
|
I ended up going with this alternative (yabai 4.0): cmd + shift - k : if [ "$(yabai -m query --spaces --space | jq -r '.type')" = "stack" ]; then (yabai -m window --focus stack.next || yabai -m window --focus stack.first); else yabai -m window --focus next || yabai -m window --focus first; fi
cmd + shift - j : if [ "$(yabai -m query --spaces --space | jq -r '.type')" = "stack" ]; then (yabai -m window --focus stack.prev || yabai -m window --focus stack.last); else yabai -m window --focus prev || yabai -m window --focus last; fi The alternative suggested above didn't have the behavior I expected. With |
pat-s commentedAug 8, 2019
Wondering if you have thought about supporting stacking of windows (similar to i3 and sway).
I usually use this mode a lot in certain spaces in sway and it can be pretty handy.
Thanks for the great project!
The text was updated successfully, but these errors were encountered: