Getting and setting window size and position

Jack j4315593 at gmail.com
Wed Sep 3 15:10:16 CEST 2025


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/1e23007b/attachment.htm>


More information about the Xfce mailing list