#!/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