feat: add window resizing scripts aff10c88
Steve · 2026-09-01 08:59 6 file(s) · +67 −0
scripts/win (added) +62 −0
1 +
#!/bin/sh
2 +
# Requires: xdotool, xprop (xorg-xprop)
3 +
# Size and place the focused window as a percentage of the usable screen.
4 +
# xfwm4's own tile_* keys already cover halves and quarters (Shift+Super+h/l);
5 +
# this is for the geometries it has no name for -- a centered 60% window, a
6 +
# narrow reading column. The argument is WxH, optionally +X+Y, all in percent
7 +
# of the work area, with no offset meaning centered:
8 +
#   win 60x70       60% wide, 70% tall, centered
9 +
#   win 100x40+0+0  full width, top 40%
10 +
# The win-* symlinks beside it are presets, so a keybind is a bare path with
11 +
# no arguments -- the same trick vol-up/vol-down use.
12 +
set -u
13 +
14 +
win=$(xdotool getactivewindow 2>/dev/null) || exit 0
15 +
16 +
# The name it was called by (win-center -> center), or the first argument.
17 +
geom=${1:-$(printf '%s' "${0##*/}" | sed 's/^win-*//')}
18 +
19 +
case "$geom" in
20 +
    center) geom=40x60     ;;
21 +
    big)    geom=90x90     ;;
22 +
    small)  geom=40x50     ;;
23 +
    read)   geom=45x90     ;;
24 +
    full)   geom=100x100   ;;
25 +
esac
26 +
27 +
# Split WxH[+X+Y]. A missing offset stays empty and is read as "centre me".
28 +
pw=${geom%%x*}
29 +
rest=${geom#*x}
30 +
case "$rest" in
31 +
    *+*+*) ph=${rest%%+*}; off=${rest#*+}; px=${off%%+*}; py=${off#*+} ;;
32 +
    *)     ph=$rest;       px=;            py= ;;
33 +
esac
34 +
35 +
case "$pw$ph$px$py" in
36 +
    *[!0-9]*|'') echo "usage: ${0##*/} WxH[+X+Y] | center|big|small|read|full" >&2; exit 2 ;;
37 +
esac
38 +
39 +
# xfwm4 refuses to resize a maximized window, so drop those states first;
40 +
# without this the first press after a maximize silently does nothing.
41 +
xdotool windowstate --remove MAXIMIZED_VERT --remove MAXIMIZED_HORZ "$win" 2>/dev/null
42 +
43 +
# The first desktop's work area: the screen minus polybar's reserved strip, so
44 +
# a 100%-tall window stops at the bar instead of sliding under it.
45 +
set -- $(xprop -root _NET_WORKAREA | sed 's/.*= //; s/,//g')
46 +
ax=$1 ay=$2 aw=$3 ah=$4
47 +
48 +
# windowmove places the frame, but windowsize sets the *client* area, so the
49 +
# decorations have to come off the requested size or every window lands one
50 +
# title bar too tall.
51 +
set -- $(xprop -id "$win" _NET_FRAME_EXTENTS 2>/dev/null | sed 's/.*= //; s/,//g')
52 +
fl=${1:-0} fr=${2:-0} ft=${3:-0} fb=${4:-0}
53 +
54 +
w=$((aw * pw / 100))
55 +
h=$((ah * ph / 100))
56 +
# An omitted offset centres on that axis, which is what most of the presets
57 +
# want; a given one is a percentage from the work area's top-left corner.
58 +
if [ -n "$px" ]; then x=$((ax + aw * px / 100)); else x=$((ax + (aw - w) / 2)); fi
59 +
if [ -n "$py" ]; then y=$((ay + ah * py / 100)); else y=$((ay + (ah - h) / 2)); fi
60 +
61 +
xdotool windowmove "$win" "$x" "$y" \
62 +
        windowsize "$win" $((w - fl - fr)) $((h - ft - fb))
scripts/win-big (added) +1 −0
1 +
win
scripts/win-center (added) +1 −0
1 +
win
scripts/win-full (added) +1 −0
1 +
win
scripts/win-read (added) +1 −0
1 +
win
scripts/win-small (added) +1 −0
1 +
win