Streaming: measure Flash Player's menu bar from the movie's offset #11

Merged
branderson merged 2 commits from flash-menu-offset into main 2026-10-14 18:18:02 -07:00
4 changed files with 39 additions and 14 deletions
+1 -3
View File
@@ -46,9 +46,7 @@ export class DockerDriver implements Driver {
`PUID=${uid}`,
`PGID=${gid}`,
`SUBFOLDER=${streamPath(id)}`,
// The game's exact size, and the display's, rounded up to even for H.264
`GAME_WIDTH=${size.width}`,
`GAME_HEIGHT=${size.height}`,
// The game's size, rounded up to even for H.264
`SELKIES_MANUAL_WIDTH=${size.width + (size.width % 2)}`,
`SELKIES_MANUAL_HEIGHT=${size.height + (size.height % 2)}`,
'SELKIES_UI_SHOW_SIDEBAR=false',
+1
View File
@@ -30,6 +30,7 @@ RUN apt-get update && \
libxtst6 \
libxxf86vm1 \
sqlite3 \
x11-utils \
xdotool && \
rm -rf /var/lib/apt/lists/*
+6 -3
View File
@@ -54,6 +54,9 @@ is Flash Player's save directory, so the session manager syncs both to the
player's browser. OldCPUSimulator hangs under Wine, so its target runs under
`cpulimit` at the same share of the CPU. A Flash projector's window is
stretched to the display and moved up by its menu bar's height, which hides the
menu bar; the height is the window's opening height less the movie's
(`GAME_HEIGHT`). Its full-screen mode isn't used, since some games, such as
Bloons, don't play right in it. Flashpoint Navigator's toolbars are hidden.
menu bar. GTK draws the menu bar in the window itself and the movie in a child
window below it, so the movie's offset, read with `xwininfo`, is the menu bar's
height. The window is made override-redirect first, since the window manager
keeps windows on screen, and is kept in place while it's open, since Flash
Player moves it back once the movie has loaded. Its full-screen mode isn't used, since some games, such
as Bloons, don't play right in it. Flashpoint Navigator's toolbars are hidden.
@@ -49,16 +49,39 @@ case ${app,,} in
if [[ ${app,,} == 'fpsoftware\flash\'* ]]; then
# Hide the projector's menu bar by moving it above the display, and fill
# the display with the movie. Not full screen, which some games, such as
# Bloons, don't play right in. The window opens at the movie's size plus
# the menu bar, which gives the menu bar's height.
# Bloons, don't play right in. The window manager keeps windows on
# screen, so the window is taken out of its hands first.
(
set +eo pipefail
wid=$(xdotool search --sync --onlyvisible --name 'Flash Player' | head -1)
eval "$(xdotool getwindowgeometry --shell "$wid")"
read -r display_width display_height < <(xdotool getdisplaygeometry)
menu=$((HEIGHT - ${GAME_HEIGHT:-$display_height}))
((menu > 0 && menu < 100)) || menu=0
xdotool windowsize "$wid" "$display_width" $((display_height + menu)) \
windowmove "$wid" 0 $((-menu)) windowactivate "$wid"
read -r width height < <(xdotool getdisplaygeometry)
# GTK draws the menu bar in the window itself, and the movie in the
# largest child window, below it: the movie's offset is the menu bar's height
menu=$(xwininfo -children -id "$wid" | awk '
match($0, /[0-9]+x[0-9]+\+-?[0-9]+\+-?[0-9]+/) {
split(substr($0, RSTART, RLENGTH), g, /[x+]/)
if (g[1] * g[2] > area) { area = g[1] * g[2]; top = g[4] }
}
END { print top + 0 }')
((menu >= 0 && menu < height)) || menu=0
echo "Flash Player window $wid: menu bar ${menu}px, display ${width}x${height}"
xdotool windowunmap --sync "$wid"
xdotool set_window --overrideredirect 1 "$wid"
xdotool windowmap --sync "$wid"
place() { xdotool windowsize "$wid" "$width" $((height + menu)) windowmove "$wid" 0 $((-menu)); }
place
xdotool windowfocus "$wid"
# Flash Player moves its window back once the movie has loaded, so it's
# kept in place for as long as it's open
moves=0
while geometry=$(xdotool getwindowgeometry --shell "$wid" 2>/dev/null); do
eval "$geometry"
if ((X != 0 || Y != -menu || WIDTH != width || HEIGHT != height + menu)); then
((++moves <= 3)) && echo "Flash Player window moved to $X,$Y (${WIDTH}x${HEIGHT}); putting it back"
place
fi
sleep 0.5
done
) &
fi
cd "${argv[0]}"