#!/bin/sh set -eu # 1️⃣ Presets PRESETS=" 0.15 0.30 0.40 0.50 0.60 0.70 0.80 0.90 1.00" # Per-window saved-proportion directory PROPORTION_DIR="${XDG_RUNTIME_DIR:-/tmp}/mango-resize" # 2️⃣ Helper: abort with a clear message if a required binary is missing need_cmd() { command -v "$1" >/dev/null 2>&1 || { printf "❌ Required command '%s' not found in PATH. Install it first.\n" "$1" >&2 exit 127 } } need_cmd mmsg need_cmd jq need_cmd awk need_cmd wc need_cmd sed # 3️⃣ Get the *currently focused* client. client_json=$(mmsg get focusing-client || true) # 3a️⃣ Extract the window's unique id (used as the per-window state key) win_id=$(printf '%s' "$client_json" | jq -r '.id // empty' || true) if [ -z "$win_id" ]; then printf "⚠️ Could not determine window id – aborting.\n" >&2 exit 1 fi # Per-window state file PROPORTION_FILE="$PROPORTION_DIR/$win_id" # 3b️⃣ Extract current client width current=$(printf '%s' "$client_json" | jq -r '.width // empty' || true) if [ -z "$current" ]; then printf "⚠️ No focusing client reported – using monitor width as current size.\n" current=$(mmsg get all-monitors | jq -r ' if type == "array" then (map(select(.active == true))[0].width) else (.monitors | map(select(.active == true))[0].width) end ' || true) fi # 4️⃣ Get the *usable* work‑area width usable_width=$(mmsg get workarea 2>/dev/null || true) if [ -n "$usable_width" ]; then usable_width=$(printf '%s' "$usable_width" | jq -r '.width // empty') fi if [ -z "$usable_width" ]; then usable_width=$(mmsg get all-monitors | jq -r ' if type == "array" then (map(select(.active == true))[0].width) else (.monitors | map(select(.active == true))[0].width) end ') fi # 5️⃣ Compute the proportion approx=$(awk -v cw="$current" -v uw="$usable_width" ' BEGIN { if (uw <= 0) { print "0.50"; exit } printf "%.4f\n", cw / uw }') # 6️⃣ Find the nearest preset index nearest_index=$(awk -v target="$approx" ' BEGIN { split("'"$PRESETS"'", a, " "); best_i = 1; best_d = 999; for (i = 1; i <= length(a); i++) { d = a[i] - target; if (d < 0) d = -d; if (d < best_d) { best_d = d; best_i = i; } } print best_i; }') # 7️⃣ Apply the direction argument case "${1:-}" in up) new_index=$((nearest_index + 1)) ;; down) new_index=$((nearest_index - 1)) ;; fullscreen) # Check if currently fullscreen (approx >= 0.95 → treat as fullscreen) is_fullscreen=$(awk -v a="$approx" 'BEGIN { print (a >= 0.95) ? "1" : "0" }') if [ "$is_fullscreen" = "1" ]; then # Currently fullscreen → restore this window's saved proportion if [ -f "$PROPORTION_FILE" ]; then saved=$(cat "$PROPORTION_FILE") mmsg dispatch "set_proportion,$saved" printf "✅ [win %s] Restored proportion to %s (fullscreen toggle off)\n" "$win_id" "$saved" rm -f "$PROPORTION_FILE" else printf "⚠️ [win %s] No saved proportion – defaulting to 0.50\n" "$win_id" >&2 mmsg dispatch "set_proportion,0.50" fi else # Not fullscreen → save this window's proportion & go fullscreen saved=$(printf '%s\n' $PRESETS | sed -n "${nearest_index}p") mkdir -p "$PROPORTION_DIR" printf '%s' "$saved" > "$PROPORTION_FILE" mmsg dispatch "set_proportion,1.00" printf "✅ [win %s] Saved proportion %s, set to 1.00 (fullscreen toggle on)\n" "$win_id" "$saved" fi exit 0 ;; *) printf "❌ Usage: %s [up|down|fullscreen]\n" "$0" >&2; exit 1 ;; esac # 8️⃣ Clamp count=$(printf '%s\n' $PRESETS | wc -l) if [ "$new_index" -lt 1 ]; then new_index=1; fi if [ "$new_index" -gt "$count" ]; then new_index=$count; fi # 9️⃣ Resolve the new preset value new_value=$(printf '%s\n' $PRESETS | sed -n "${new_index}p") # 🔟 Dispatch mmsg dispatch "set_proportion,$new_value" printf "✅ Set proportion to %s (preset %s of %s)\n" "$new_value" "$new_index" "$count"