Skip to content

Instantly share code, notes, and snippets.

@20after4
Last active March 31, 2025 21:28
Show Gist options
  • Save 20after4/e394d34bd0cbe24169fcc78c1f1abebc to your computer and use it in GitHub Desktop.
Save 20after4/e394d34bd0cbe24169fcc78c1f1abebc to your computer and use it in GitHub Desktop.
bash script to implement floating scratch windows in `niri`

Notes

  1. Place the files in your path
  2. Make niri-toggle-scratch.sh and json_select executable.
  3. On line 32 of niri-toggle-scratch.sh I have code to focus my floating-kitty window (a dedicated terminal instance) after showing scratch windows. You might want to customize or remove this part depending on how you use scratch windows.

See also

Related discussion is in this thread: YaLTeR/niri#329 (reply in thread)

binds {
// if there are floating windows on the current workspace, move them to the named 'scratch' workspace
// if there are no floating windows then move all windows from the scratch workspace to the current workspace
XF86Explorer { spawn "niri-toggle-scratch.sh"; }
}
workspace "scratch" {
open-on-output "DP-1"
}
#!/bin/bash
key="$1"
val="$2"
if [[ $2 =~ ^true|false|[0-9]+ ]]; then
val="$2"
else
val="\"$2\""
fi
out="${3:-.}"
filter=""
if [[ "$4" == "join" ]]; then
filter=" | join(\" \")"
fi
jq -r "[ .[] | if .$key == $val then $out else null end | values ] $filter"
#!/bin/bash
source niri_functions.sh
focused="$(focused_workspace_idx)"
focused_id=$(focused_workspace)
floats=$(niri msg --json windows | jqsel ".is_floating == true" | jqselraw ".workspace_id == $focused_id" "id")
count=$(echo $floats | wc -w)
if [[ "$count" != "0" ]]; then
niri msg action do-screen-transition -d 150
for i in $(echo -n $floats); do
niri msg action move-window-to-workspace scratch --window-id "$i"
done
niri msg action focus-workspace $focused
niri msg action focus-tiling
else
niri msg action do-screen-transition -d 70
scratch=$(niri msg -j workspaces|json_select name scratch '.id' | json_raw)
match=$(niri msg -j windows | jqselraw ".workspace_id == $scratch" "id")
for i in $(echo -n $match); do
niri msg action move-window-to-workspace $focused --window-id "$i"
done
niri msg action focus-workspace $focused
niri msg action focus-floating
# Make sure the "floating-kitty" termiunal window is focused after showing scratch windows:
# If you don't use kitty, the next two lines are not needed, either remove or replace the
# app_id with something that matches your preferred window.
kitty=$(niri msg -j windows | jqselraw ".app_id == \"floating-kitty\"" "id")
niri msg action focus-window --id $kitty
fi
#!/bin/bash
focused_workspace() {
niri msg -j focused-window | jq -j '.workspace_id'
}
focused_workspace_idx() {
focused=$(focused_workspace)
niri msg -j workspaces | json_select id $focused .idx | json_raw
}
focused_window() {
niri msg -j focused-window | jq -j '.id'
}
is_floating() {
niri msg -j focused-window | jq -j .is_floating
}
jqsel() {
jq -r "[ .[] | select( $1 ) ]";
}
jqselraw() {
jq -r "map(select( $1 ).$2) | join(\" \")"
}
json_raw() {
jq -r .[]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment