diff options
author | nepèta dyengxuah <nepeta@canaglie.net> | 2025-04-09 00:03:20 +1000 |
---|---|---|
committer | nepèta dyengxuah <nepeta@canaglie.net> | 2025-04-09 00:03:20 +1000 |
commit | c6ff2e34665ab72a8e460b0e08745509c6500233 (patch) | |
tree | 8824787ea0db0a03db5840d37d2fc1ceb1dd328b /blog/2023-10-03-sticky-tiling-windows-in-bspwm | |
parent | 60b603ebd48c3add90ee40fa9421c3919241ccea (diff) |
bring shit back in
Diffstat (limited to 'blog/2023-10-03-sticky-tiling-windows-in-bspwm')
-rw-r--r-- | blog/2023-10-03-sticky-tiling-windows-in-bspwm/index.md | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/blog/2023-10-03-sticky-tiling-windows-in-bspwm/index.md b/blog/2023-10-03-sticky-tiling-windows-in-bspwm/index.md new file mode 100644 index 0000000..ab2fbad --- /dev/null +++ b/blog/2023-10-03-sticky-tiling-windows-in-bspwm/index.md @@ -0,0 +1,93 @@ +# sticky tiling windows in bspwm + +`bspwm` has a useful `sticky` flag, which keeps the window on whatever the focused desktop +is, basically like using `node -d` whenever you change desktops. +for floating windows this works very well, but the situation is more complicated if +you set the `sticky` flag for a tiled window. + +It works, of course, but since the sticky window is moved away from a desktop when it +stops being focused, it loses its location in the desktop's layout, +and switching back to that desktop places the sticky tiled window in the location any +window would be. This is not ideal if you don't want to constantly reconfigure your +layout after switching to a browser or something similar. + +There's actually a draft pull request from 2019 on `bspwm`'s Github that addresses this, +[#1032](https://github.com/baskerville/bspwm/pull/1032), but patching bspwm to solve this +problem is quite bothersome if you use a binary package. Plus, `bspwm`'s great advantage +is how extensible and scriptable it is; there must be a way to solve this problem that way! + +There absolutely is, but it took a while for me to figure it out. I spent a few hours on this, +getting it to *almost* work, but be flawed in a way that made it not worth using. +But I finally got it working after [emanuele6](https://github.com/emanuele6) helped me +on IRC (thanks!), and now I use it. So, here it is, `bsp_movedesk`: + + #!/bin/sh + # deal with sticky windows when moving workspaces. + test -z "$1" && exit + + # path format: desktop/stickywindow: parent + bspc query -N -n '.local.leaf.!hidden.sticky' | while read -r wid; do + [ "$(bsp_countwindows)" = 1 ] && break + dir="$HOME/run/bspsticky/$(bspc query -D -d focused)" + mkdir -p "$dir" + bspc node "$wid" -i + bspc query -N "$wid" -n '@brother.leaf.!window' > "${dir}/${wid}" + done + + bspc desktop -f "$1" + + bspc query -N -n '.local.leaf.!hidden.sticky' | while read -r wid; do + dir="$HOME/run/bspsticky/$(bspc query -D -d focused)" + [ "$(bsp_countwindows)" = 1 ] && break + stdir="${dir}/${wid}" + if [ -s "$stdir" ]; then + rece="$(cat "$stdir")" + bspc node "$wid" -n "$rece" + rm "$stdir" + fi + done + + # remove hidden window's receptacles. sucks but better than the alternative + while bspc node 'any.local.leaf.!window' -k; do :; done + +The script is a wrapper around `desktop -f`, and can be used by replacing instances +of `bspc desktop -f` with `bsp_movedesk` in your `sxhkd` config. + +It works by reading and writing to a special directory +(on my machine `$HOME/run/bspsticky`, kept inside a ramdisk), +which contains directories named with a desktop's ID. +These directories contain files named for a sticky node's ID, +and contain the ID of a receptacle which the window should be +moved to if that desktop is focused. +These receptacles are placed before the focused desktop changes if there +are multiple windows open (because doing this when the sticky window +is the only open window is unnecessary.) + +This is the `bsp_countwindows` script: + + #!/bin/sh + bspc query -N -n '.window.!hidden' -d | wc -l + +There are definitely improvements that could be made here, +but It Works. the end. + +--- + +here's a completely unrelated script, which swaps a window's parent to its sibling, +in case you want that: + + #!/bin/sh + # move focused window to sibling + set -e + + # possibly causes a race condition if focused changes during script? + focused=$(bspc query -N -n) + + if [ "$1" = "2" ]; then + bspc node -f @parent/parent/brother + else + bspc node -f @parent/brother + fi + bspc node -i + bspc node $focused -n $(bspc query -N -n .local.leaf.!window) + bspc node $focused -f |