| 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)) |