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