#!/bin/bash set -e # --- CONFIG --- TOP_BAR=36 DECOR_H=30 DECOR_W=5 MASTER_RATIO_NUM=1 MASTER_RATIO_DEN=2 OUTER_GAP=8 INNER_GAP=8 # Master selection: # focused = currently focused window # first = first window on desktop # last = last window on desktop MASTER_MODE="focused" # ---------------- # Get current screen resolution read SCREEN_W SCREEN_H <<< $(xrandr | awk ' /\*/ { split($1,a,"x") print a[1], a[2] exit }') USABLE_H=$((SCREEN_H - TOP_BAR)) # Work area after outer gaps WORK_X=$OUTER_GAP WORK_Y=$((TOP_BAR + OUTER_GAP)) WORK_W=$((SCREEN_W - 2 * OUTER_GAP)) WORK_H=$((USABLE_H - 2 * OUTER_GAP)) # --- focused window --- FOCUSED=$(printf "0x%08x" "$(xdotool getactivewindow)") # --- current desktop --- CUR_DESKTOP=$(xdotool get_desktop) # --- collect windows on current desktop --- ALL_WINDOWS=$(wmctrl -l -x | awk '$2!="-1" {print $1}') WINDOWS=() for w in $ALL_WINDOWS; do win_desktop=$(xdotool get_desktop_for_window "$(printf "%d" "$w")" 2>/dev/null) || continue if [ "$win_desktop" = "$CUR_DESKTOP" ]; then WINDOWS+=("$w") fi done if [ ${#WINDOWS[@]} -eq 0 ]; then echo "No windows found on current desktop." exit 1 fi # ---------------------------------------------------- # Determine master window # ---------------------------------------------------- case "$MASTER_MODE" in focused) MASTER="$FOCUSED" ;; first) MASTER="${WINDOWS[0]}" ;; last) MASTER="${WINDOWS[$((${#WINDOWS[@]} - 1))]}" ;; *) echo "Invalid MASTER_MODE: $MASTER_MODE" exit 1 ;; esac # --- separate master from stack --- STACK=() for w in "${WINDOWS[@]}"; do if [ "$w" != "$MASTER" ]; then STACK+=("$w") fi done place() { local id=$1 local x=$2 local y=$3 local raw_w=$4 local raw_h=$5 local class decor_h decor_w x_offset y_offset x_offset=0 y_offset=0 class=$(xprop -id "$id" WM_CLASS 2>/dev/null | sed -r 's/.*"(.*)"$/\1/') case "$class" in Alacritty) decor_h=42 decor_w=8 ;; Chromium) decor_h=42 decor_w=5 ;; obsidian) decor_h=5 decor_w=0 x_offset=-0 y_offset=-0 ;; dev.zed.Zed) decor_h=-19 decor_w=-23 x_offset=-13 y_offset=-13 ;; *) decor_h=$DECOR_H decor_w=$DECOR_W ;; esac local w=$((raw_w - decor_w)) local h=$((raw_h - decor_h)) local fx=$((x + x_offset)) local fy=$((y + y_offset)) wmctrl -i -r "$id" -b remove,maximized_vert,maximized_horz wmctrl -i -r "$id" -e 1,"$fx","$fy","$w","$h" } # ---------------------------------------------------- # Single window # ---------------------------------------------------- if [ ${#WINDOWS[@]} -eq 1 ]; then place \ "$MASTER" \ "$WORK_X" \ "$WORK_Y" \ "$WORK_W" \ "$WORK_H" exit 0 fi # ---------------------------------------------------- # Master / Stack layout # ---------------------------------------------------- MID=$((WORK_W * MASTER_RATIO_NUM / MASTER_RATIO_DEN)) MASTER_X=$WORK_X MASTER_Y=$WORK_Y MASTER_W=$((MID - INNER_GAP / 2)) MASTER_H=$WORK_H STACK_X=$((WORK_X + MID + INNER_GAP / 2)) STACK_Y=$WORK_Y STACK_W=$((WORK_W - MID - INNER_GAP / 2)) STACK_H=$WORK_H # --- place master --- place \ "$MASTER" \ "$MASTER_X" \ "$MASTER_Y" \ "$MASTER_W" \ "$MASTER_H" # --- place stack --- COUNT=${#STACK[@]} if [ "$COUNT" -gt 0 ]; then SLOT_H=$(((STACK_H - INNER_GAP * (COUNT - 1)) / COUNT)) i=0 for w in "${STACK[@]}"; do SLOT_Y=$((STACK_Y + i * (SLOT_H + INNER_GAP))) place \ "$w" \ "$STACK_X" \ "$SLOT_Y" \ "$STACK_W" \ "$SLOT_H" i=$((i + 1)) done fi