Getting and setting window size and position
Jack
j4315593 at gmail.com
Wed Sep 3 19:00:33 CEST 2025
The latest version of the code is available here
<https://gist.github.com/mlauronen/cb3dc7bf0e5fa4ef7f86aafaf20e73e1>.
On Wed, Sep 3, 2025 at 4:10 PM Jack <j4315593 at gmail.com> wrote:
> Here’s my script, which gets the job done. It should work with both
> terminal-style and regular application windows in a multi-monitor setup.
> Thank you.
>
> #!/bin/bash
>
> if [ $# -ne 2 ]; then
> echo "Usage: $0 <window_id> <command>"
> echo "<window_id> can be:"
> echo " number Window ID (e.g., 0x1a0000 or 123456)"
> echo " '.' Current active window"
> echo " name Partial window name (e.g., 'firefox')"
> echo "Commands:"
> echo " -1 lower left corner"
> echo " -2 bottom side"
> echo " -3 lower right corner"
> echo " -4 left side"
> echo " -5 full screen"
> echo " -6 right side"
> echo " -7 upper left corner"
> echo " -8 top side"
> echo " -9 upper right corner"
> echo " -gX,Y,W,H move and resize"
> exit 1
> fi
>
> WINDOW_ID="$1"
> COMMAND="$2"
>
> # Handle WINDOW_ID input
> if [ "$WINDOW_ID" = "." ]; then
> # Get active window ID
> WINDOW_ID=$(xdotool getactivewindow)
> if [ -z "$WINDOW_ID" ]; then
> echo "Error: No active window found"
> exit 1
> fi
> elif [[ ! "$WINDOW_ID" =~ ^[0-9]+$ ]]; then
> # Treat as partial window name if not a number
> WINDOW_ID=$(wmctrl -l | grep -i "$WINDOW_ID" | head -n 1 | awk '{print
> $1}')
> if [ -z "$WINDOW_ID" ]; then
> echo "Error: No window found matching partial name: $1"
> exit 1
> fi
> fi
>
> # Verify window ID is valid
> if ! xwininfo -id "$WINDOW_ID" >/dev/null 2>&1; then
> echo "Error: Invalid window ID: $WINDOW_ID"
> exit 1
> fi
>
> wmctrl -ir "$WINDOW_ID" -b remove,maximized_vert,maximized_horz
>
> ABSOLUTE_X=$(xwininfo -id "$WINDOW_ID" | grep "Absolute upper-left X:" |
> awk '{print $4}')
> ABSOLUTE_Y=$(xwininfo -id "$WINDOW_ID" | grep "Absolute upper-left Y:" |
> awk '{print $4}')
>
> RELATIVE_X=$(xwininfo -id "$WINDOW_ID" | grep "Relative upper-left X:" |
> awk '{print $4}')
> RELATIVE_Y=$(xwininfo -id "$WINDOW_ID" | grep "Relative upper-left Y:" |
> awk '{print $4}')
>
> WIDTH_FIX=$((-(RELATIVE_X * 2)))
> HEIGHT_FIX=$((-(RELATIVE_Y + RELATIVE_X)))
>
> MONITOR_INFO=$(xrandr --current)
> MONITOR_X=0
> MONITOR_Y=0
> MONITOR_WIDTH=1920
> MONITOR_HEIGHT=1080
>
> # Loop through xrandr output to find the correct monitor based on window
> position
> while read -r line; do
> if [[ $line =~ ([0-9]+)x([0-9]+)\+([0-9]+)\+([0-9]+) ]]; then
> MON_W=${BASH_REMATCH[1]}
> MON_H=${BASH_REMATCH[2]}
> MON_X=${BASH_REMATCH[3]}
> MON_Y=${BASH_REMATCH[4]}
>
> # Check if the window is within this monitor's coordinates
> if (( ABSOLUTE_X >= MON_X && ABSOLUTE_X < MON_X + MON_W &&
> ABSOLUTE_Y >= MON_Y && ABSOLUTE_Y < MON_Y + MON_H )); then
> MONITOR_WIDTH=$MON_W
> MONITOR_HEIGHT=$MON_H
> MONITOR_X=$MON_X
> MONITOR_Y=$MON_Y
> break
> fi
> fi
> done <<< "$MONITOR_INFO"
>
> HALF_WIDTH=$((MONITOR_WIDTH / 2))
> HALF_HEIGHT=$((MONITOR_HEIGHT / 2))
>
> case $COMMAND in
> -1)
> xdotool windowmove "$WINDOW_ID" $MONITOR_X $((MONITOR_Y +
> HALF_HEIGHT))
> xdotool windowsize "$WINDOW_ID" $((HALF_WIDTH + WIDTH_FIX))
> $((HALF_HEIGHT + HEIGHT_FIX))
> ;;
> -2)
> xdotool windowmove "$WINDOW_ID" $MONITOR_X $((MONITOR_Y +
> HALF_HEIGHT))
> xdotool windowsize "$WINDOW_ID" $((MONITOR_WIDTH + WIDTH_FIX))
> $((HALF_HEIGHT + HEIGHT_FIX))
> ;;
> -3)
> xdotool windowmove "$WINDOW_ID" $((MONITOR_X + HALF_WIDTH))
> $((MONITOR_Y + HALF_HEIGHT))
> xdotool windowsize "$WINDOW_ID" $((HALF_WIDTH + WIDTH_FIX))
> $((HALF_HEIGHT + HEIGHT_FIX))
> ;;
> -4)
> xdotool windowmove "$WINDOW_ID" $MONITOR_X $MONITOR_Y
> xdotool windowsize "$WINDOW_ID" $((HALF_WIDTH + WIDTH_FIX))
> $((MONITOR_HEIGHT + HEIGHT_FIX))
> ;;
> -5)
> xdotool windowmove "$WINDOW_ID" $MONITOR_X $MONITOR_Y
> xdotool windowsize "$WINDOW_ID" $((MONITOR_WIDTH + WIDTH_FIX))
> $((MONITOR_HEIGHT + HEIGHT_FIX))
> ;;
> -6)
> xdotool windowmove "$WINDOW_ID" $((MONITOR_X + HALF_WIDTH))
> $MONITOR_Y
> xdotool windowsize "$WINDOW_ID" $((HALF_WIDTH + WIDTH_FIX))
> $((MONITOR_HEIGHT + HEIGHT_FIX))
> ;;
> -7)
> xdotool windowmove "$WINDOW_ID" $MONITOR_X $MONITOR_Y
> xdotool windowsize "$WINDOW_ID" $((HALF_WIDTH + WIDTH_FIX))
> $((HALF_HEIGHT + HEIGHT_FIX))
> ;;
> -8)
> xdotool windowmove "$WINDOW_ID" $MONITOR_X $MONITOR_Y
> xdotool windowsize "$WINDOW_ID" $((MONITOR_WIDTH + WIDTH_FIX))
> $((HALF_HEIGHT + HEIGHT_FIX))
> ;;
> -9)
> xdotool windowmove "$WINDOW_ID" $((MONITOR_X + HALF_WIDTH))
> $MONITOR_Y
> xdotool windowsize "$WINDOW_ID" $((HALF_WIDTH + WIDTH_FIX))
> $((HALF_HEIGHT + HEIGHT_FIX))
> ;;
> -g*)
> GEOM="${COMMAND:2}" # strip "-g"
> IFS=',' read -r GX GY GW GH <<< "$GEOM"
> if [[ -n $GX && -n $GY && -n $GW && -n $GH ]]; then
> xdotool windowmove "$WINDOW_ID" "$GX" "$GY"
> xdotool windowsize "$WINDOW_ID" "$((GW + WIDTH_FIX))" "$((GH +
> HEIGHT_FIX))"
> else
> echo "Error: invalid geometry format. Use -gX,Y,W,H"
> exit 1
> fi
> ;;
> *)
> echo "Error: Unknown command: $COMMAND"
> exit 1
> ;;
> esac
>
>
> On Wed, Sep 3, 2025 at 10:43 AM Jack <j4315593 at gmail.com> wrote:
>
>> I have three monitors running six virtual desktops, all filled with
>> applications some are tiled and some are floating. I'm currently writing a
>> script to manage them, but it's making me consider just switching to i3 :)
>>
>> On Wed, Sep 3, 2025 at 10:29 AM killermoehre <killermoehre at gmx.net>
>> wrote:
>>
>>> Am Mittwoch, dem 03.09.2025 um 10:17 +0300 schrieb Jack:
>>>
>>> Unfortunately, *built-in commands cannot be used* because after using
>>> them, the window size can no longer be changed programmatically (ie. from
>>> the scripts). This is because if you switch to another desktop and then
>>> return, the window manager no longer correctly remembers the modified
>>> window sizes. This is precisely why I'm creating my own script for this
>>> purpose.
>>>
>>> A really long time ago I wrote
>>> https://github.com/killermoehre/window-gridder for this purpose, but
>>> abondend it, because Xfwm4 hat inbuild what I need and it has problems with
>>> client side decorations.
>>>
>>> You can use it at a starting point.
>>>
>>> But IMHO it sounds like you want more of a tiling WM and not a floating
>>> one, right? Xfce allows to simply *replace* the current WM with another
>>> one. I wrote https://wiki.xfce.org/howto/other_window_manager for this.
>>> _______________________________________________
>>> Xfce mailing list
>>> Xfce at xfce.org
>>> https://mail.xfce.org/mailman/listinfo/xfce
>>> http://www.xfce.org
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.xfce.org/pipermail/xfce/attachments/20250903/fdda8307/attachment-0001.htm>
More information about the Xfce
mailing list