joewing / jwm

Joe's Window Manager
http://joewing.net/projects/jwm
MIT License
520 stars 84 forks source link

jwm does not update its panel position when the screen size changes #614

Open achadwick opened 3 months ago

achadwick commented 3 months ago

Version: Debian stable's v2.4.4. Possibly this is just that version, I've not gone delving into the source. Sorry!

Context: I'm running jwm via xrdp. This allows me to resize the X11 screen (Remmina calls it "dynamic resolution update"). However, the details don't matter so much: this is probably going to happen with VMs over Spice or VNC or whatever, too.

What I expect: Resizing my remote desktop window causes jwm to resize and redraw its panel.

What I see: If I do that, jwm's panel stays where it is. It's annoying, and can cause the panel to go out of view, if it's at the bottom.

There are a couple of configurable workarounds, which I'll post in the thread. It would be nice if jwm didn't need them, however.

achadwick commented 3 months ago

Quick workaround

Make your <RootMenu> contain something like

<Restart label="Restart JWM" icon="reload"/>

and run it when things get funky.

Hacky workaround

Make your jwmrc contain

<StartupCommand>jwm-randr-autoresize &amp;</StartupCommand>

And put that shell script somewhere on your $PATH:

#!/bin/bash
# Handle the screen size changing by restarting jwm.

set -e

SCRIPT=$(basename "$0" .sh)
FLAGFILE="/tmp/.${SCRIPT}.$$.${USER:-unknown}"
TIMEOUT_SECONDS=2
INITIAL_DELAY_SECONDS=5

process_line () {
    # Lines matching a given fixed string
    if [ "$1" != "${1%RRScreenChangeNotify*}" ]; then
        touch "$FLAGFILE"
    fi
}

process_timeout () {
    if [ -f "$FLAGFILE" ]; then
        xrandr --auto || true
        jwm -restart || true
        sleep 5
        rm -f "$FLAGFILE"
    fi
}

do_cleanup () {
    rm -f "$FLAGFILE"
}

watch_root_window () {
    # The -1 flag isn't supported everywhere yet.
    stdbuf -oL xev -root -event randr -1 || \
    stdbuf -oL xev -root -event randr
}

do_cleanup
sleep "$INITIAL_DELAY_SECONDS"
trap do_cleanup exit
watch_root_window 2>/dev/null | while true; do
    IFS= read -r line
    process_line "$line"
    while IFS= read -t "$TIMEOUT_SECONDS" -r line; do
        process_line "$line"
    done
    process_timeout
done