diff --git a/dot_local/bin/executable_umbriel-smart-move b/dot_local/bin/executable_umbriel-smart-move new file mode 100755 index 0000000..bad1400 --- /dev/null +++ b/dot_local/bin/executable_umbriel-smart-move @@ -0,0 +1,37 @@ +#!/bin/sh +# umbriel-smart-move left|right +# niri's consume-or-expel move, extended across outputs: +# - stacked in a column → expel to a new column on that side +# - alone, column beside it → consume into that column +# - alone, at the strip's end → move to the output on that side +# Pressing twice therefore steps a window past its neighbour: in, then out the +# far side. Dwindle and master workspaces have no columns; there the window +# moves in that direction, or onto the next output at the edge. Floating and +# scratchpad windows are left alone. +set -eu + +case ${1:-} in +left | right) dir=$1 ;; +*) echo "usage: umbriel-smart-move left|right" >&2; exit 2 ;; +esac + +windows=$(umbriel windows --json) +layout=$(umbriel workspaces --json | jq -r '.[] | select(.focused) | .layout') + +# "" for the focused window, or nothing when it should stay put. +action=$(printf '%s' "$windows" | jq -r --arg dir "$dir" --arg layout "$layout" ' + (map(select(.focused)) | first) as $w + | if $w == null or $w.floating or $w.scratchpad != "" then empty + elif $layout != "scrolling" then "window-move-or-output-\($dir)" + else + [ .[] | select(.workspace == $w.workspace and (.floating | not) and .scratchpad == "") ] as $tiled + | ([ $tiled[] | select(.column == $w.column) ] | length) as $rows + | ([ $tiled[] | .column ] | if $dir == "left" then min else max end) as $edge + | if $rows > 1 or $w.column != $edge then "window-consume-or-expel-\($dir)" + else "window-move-or-output-\($dir)" + end + end') + +[ -n "$action" ] || exit 0 +# At the outermost output, "no output to the left/right" is the expected end. +umbriel msg "$action" >/dev/null 2>&1 || true