bspwm
bspwm copied to clipboard
Bspc -f {next,prev} not working correctly
Steps to reproduce:
Tree (for example):
- pair 1
- window 1
- pair 2
- window 2
- window 3
Select window 1. Then, execute:
bspc node -f next
Expected behavior:
The command selects window 2.
Observed behavior:
The command selects pair 2.
Is this really intended? Especially since the commands bspc node -f {north,east,south,west} do not work this way.
I could see the argument that you want to select upper nodes to maybe rotate groups of windows, but why does it only work this way for {next,prev}?
I essentially want Alt+Tab functionality. Thank you!
Is this really intended?
Yes.
CYCLE_DIR := next | prev ... CYCLE_DIR Selects the node in the given (cyclic) direction relative to the reference node within a depth-first in-order traversal of the tree.
next and prev can focus any node, not only leaf nodes. At least since d87e6c0f, and since bspwm version 0.9.10 (released almost 2 years ago).
There is no reason why next and prev should be limited to just matching leaf nodes (you can use next.leaf if you want that behaviour) or window nodes (you can use next.window if you want that behaviour) or non-hidden windows (you can use next.window.!hidden for that behaviour; this was the behaviour before 0.9.10 and was very limiting).
Especially since the commands
bspc node -f {north,east,south,west}do not work this way.
It does not really make sense to talk of directions when a node is hidden, or is an inner node. To be to the right or to the left of some node, it needs to be shown. The main reason why DIR will only match the first non-hidden window node in the given direction that matches the modifiers and not inner nodes is that it's unclear how you would even define that. (is the parent of a node more west and more north than its children, but less south and less east? why?)
One thing you could argue is that DIR selectors should be allowed to match any kind of leaf nodes, not just non-hidden windows, but if you want to argue that those descriptors should be allowed to also match inner nodes, you would have to define what that even means; perhaps you could base it on the behaviour of @DIR path node descriptors. If you define that, what would be a use case for DIR node descriptor matching inner nodes?
but why does it only work this way for
{next,prev}?
That is just not true. Most of the node selector descriptors can match any kind of node:
anyselects the first node that matches the modifiers. (Any kind of node.)CYCLE_DIRselects the first node before/after the reference node. (Any kind of node.)- that matches the given modifiers (excluding the reference node). (Any kind of node.)
PATHselects the node at the given path, but only if it matches the modifiers. (Any kind of node.)first_ancestorselects the first ancestor of the reference node that matches the modifier; this one actually can never select a leaf node for obvious reasons. (Only inner nodes.)focusedselects the focused node, but only if it matches the modifiers; this one cannot possibly match receptacles since receptacles cannot be focused. (Inner nodes and windows (except hidden windows).)lastselects the first node that was focused before the reference node (according to the focus history) that matches the modifiers. (Inner nodes and windows; plus an hidden hardcoded restriction that all the history selectors have and that could be removed since it does not make much sense: this selector cannot match nodes that are currentlyhidden.)newestselects the first node from the end of the focus history that matches the modifiers. (Inner nodes and windows that are not currently hidden.)olderis just an alias forlast. (Inner nodes and windows that are not currently hidden.)pointedselects the leaf node under the mouse pointer, but only if it matches the modifiers; this obviously only matches leaves, but not hidden windows since windows must not be hidden to be "under the mouse pointer". (Receptacles and non-hidden windows.)biggestselects the non-vacant leaf node that occupies the biggest area of tiling space that matches the modifiers; since it cannot match vacant nodes, it can only match either receptacles or non-hidden non-floating non-fullscreen windows. (Receptacles and non-hidden windows that are in either tiled or pseudo_tiled state.)smallestselects the non-vacant leaf node that occupies the smallest area of tiling space that matches the modifiers. (Receptacles and non-hidden windows that are in either tiled or pseudo_tiled state.)NODE_IDselects the node with the given id, but only if matches the modifiers. (Any kind of node.)
I essentially want Alt+Tab functionality. Thank you!
I understand what you mean, but that is not very descriptive of what you want without some knowledge.
You want to cycle windows with a key combination.
You can use the sxhkd hotkeys included in the example sxhkdrc file distributed with bspwm.
https://github.com/baskerville/bspwm/blob/1560df35be303807052c235634eb8d59415c37ff/examples/sxhkdrc#L65-L67
These hotkeys use next.local.!hidden.window to select the next window (that is not hidden) in the focused desktop.
Since you seem to prefer it, you can use alt + {_,shift + }Tab instead of super + {_,shift + }c (or even just alt + Tab if you don't want alt + shift + Tab to go backwards).
You can also remove .local (since you didn't include it in your example) in which case, the hotkey will focus windows in other desktops after cycling all the nodes in the focused desktop.
I personally use these two pairs of hotkeys to cycle tiled/pseudo_tiled windows and floating windows separately.
# Focus a floating window / Cycle floating windows.
super + {_,shift + }g
bspc node 'focused.floating#{next,prev}.local.!hidden.floating' -f \
|| bspc node 'last.local.!focused.!hidden.floating' -f \
|| bspc node 'any.local.!focused.!hidden.floating' -f
# Focus a (pseudo_)tiled window / Cycle (pseudo_)tiled windows.
super + {_,shift + }c
bspc node 'focused.!floating.!fullscreen.window#{next,prev}.local.!hidden.!floating.!fullscreen.window' -f \
|| bspc node 'last.local.!focused.!hidden.!floating.!fullscreen.window' -f \
|| bspc node 'any.local.!focused.!hidden.!floating.!fullscreen.window' -f
This setup lets me use
super + c/super + gto quickly swap focus between a tiled (or pseudo_tiled) window and a floating window in the focused desktop.- multiple presses of
super + cto cycle the tiled (and pseudo_tiled) windows in the focused desktop. - multiple presses of
super + gto cycle the floating windows in the focused desktop.
Duplicate of #1168, #1171, #1172, #1177, #1182, #1184, #1187, #1213, #1299 (this is issue #1387).