mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-06 01:00:06 +02:00
Serve only the desktop's primary screen over VNC
krdp streams every screen, so the VNC screen is now the primary's size and the FreeRDP window is shifted so the primary fills it (ft-layout remote-view gives the offset). It resizes and reconnects when the layout changes. With remote access on, KWin's D-Bus screenshot interface is open too, for scripts that look at the screens without the headset. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 6f5a23c80f2ecd26e6a96c86b102be36d518ee25)
This commit is contained in:
1 parent
97f853130d
commit
9820e7996f
5 files changed
+102
-31
No files matched your search
@@ -169,13 +169,14 @@ export XDG_STATE_HOME=$HOME/.local/state/frametop
|
||||
mkdir -p "$XDG_CONFIG_HOME" "$XDG_STATE_HOME"
|
||||
|
||||
# Remote desktop over VNC: session/remote-desktop.sh captures the desktop with
|
||||
# krdp on 127.0.0.1, and session/vnc-bridge.sh re-serves it over VNC. krdpserver runs from the container, so KWin can't
|
||||
# krdp on 127.0.0.1, and session/vnc-bridge.sh re-serves its primary screen over VNC. krdpserver runs from the container, so KWin can't
|
||||
# match it to an installed app. KWin's permission check for screencast and fake
|
||||
# input is turned off for this nested session only.
|
||||
# input is turned off for this nested session only, and so is the check on KWin's
|
||||
# D-Bus screenshot interface, which scripts use to see the screens without the headset.
|
||||
if [ "$remote" = 1 ]; then
|
||||
export KWIN_WAYLAND_NO_PERMISSION_CHECKS=1
|
||||
export KWIN_WAYLAND_NO_PERMISSION_CHECKS=1 KWIN_SCREENSHOT_NO_PERMISSION_CHECKS=1
|
||||
"$here/remote-desktop.sh" "$runtime" > /tmp/frametop-remote.log 2>&1 &
|
||||
"$here/vnc-bridge.sh" "$width" "$height" > /tmp/frametop-vnc.log 2>&1 &
|
||||
"$here/vnc-bridge.sh" > /tmp/frametop-vnc.log 2>&1 &
|
||||
fi
|
||||
|
||||
# ft-floatd (floating windows) runs inside the Plasma session, on its D-Bus: started from
|
||||
|
||||
+64
-18
@@ -1,14 +1,19 @@
|
||||
#!/bin/bash
|
||||
# Runs on the Frame host. Serves the Frametop desktop over VNC for clients
|
||||
# like RealVNC Viewer or macOS Screen Sharing. No VNC server here can capture
|
||||
# KWin directly, so this bridges through krdp: Xvnc (a virtual X screen served
|
||||
# over VNC) runs a full-screen FreeRDP client connected to krdpserver on
|
||||
# 127.0.0.1. Both run in the dev container. VNC listens on the tailnet address only.
|
||||
# Runs on the Frame host. Serves the Frametop desktop's primary screen (the one with the
|
||||
# taskbar) over VNC for clients like RealVNC Viewer or macOS Screen Sharing. No VNC server
|
||||
# here can capture KWin directly, so this bridges through krdp: Xvnc (a virtual X screen
|
||||
# served over VNC) runs a FreeRDP client connected to krdpserver on 127.0.0.1. Both run in
|
||||
# the dev container. VNC listens on the tailnet address only.
|
||||
# Started by frametop-session.sh when REMOTE=1, after remote-desktop.sh.
|
||||
#
|
||||
# krdp streams the whole workspace (every screen). Its --monitor would stream one screen,
|
||||
# but krdp 6.7 then maps the pointer as if that screen sat at 0,0, so clicks miss on a
|
||||
# screen placed lower or further right. Instead the VNC screen is the primary's size, and
|
||||
# the workspace-sized RDP window inside it is shifted so the primary fills it. The pointer
|
||||
# maps 1:1. When the layout changes, the VNC screen resizes and the RDP client reconnects.
|
||||
set -eu
|
||||
|
||||
width=${1:-1920}
|
||||
height=${2:-1080}
|
||||
here=$(dirname "$(readlink -f "$0")")
|
||||
vnc_port=${VNC_PORT:-5900}
|
||||
rdp_port=${RDP_PORT:-3390}
|
||||
display=:20
|
||||
@@ -32,24 +37,65 @@ for _ in $(seq 60); do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# "x y width height workspace_width workspace_height" of the primary screen, once Plasma is up.
|
||||
view() { "$here/../layout/ft-layout" remote-view 2>/dev/null | grep -xE '[0-9]+( [0-9]+){5}'; }
|
||||
v=
|
||||
for _ in $(seq 90); do
|
||||
v=$(view) && [ -n "$v" ] && break
|
||||
v=
|
||||
sleep 1
|
||||
done
|
||||
if [ -z "$v" ]; then
|
||||
echo "couldn't read the desktop's screens, not starting VNC" >&2
|
||||
exit 1
|
||||
fi
|
||||
read -r _ _ w h _ _ <<< "$v"
|
||||
|
||||
export XDG_RUNTIME_DIR=/run/user/$(id -u)
|
||||
exec ~/.local/bin/distrobox enter dev -- bash -c '
|
||||
set -eu
|
||||
creds=$1 addr=$2 vnc_port=$3 rdp_port=$4 display=$5 width=$6 height=$7
|
||||
vncpasswd -f < "$creds/vnc-password" > "$creds/vnc-passwd.bin"
|
||||
chmod 600 "$creds/vnc-passwd.bin"
|
||||
Xvnc "$display" -geometry "${width}x${height}" -depth 24 \
|
||||
box() { "$HOME/.local/bin/distrobox" enter dev -- "$@"; }
|
||||
stop_rdp() { pkill -f "[x]freerdp /v:127.0.0.1:$rdp_port " 2>/dev/null || true; }
|
||||
trap 'stop_rdp; pkill -f "[X]vnc $display " 2>/dev/null || true' EXIT
|
||||
|
||||
box bash -c 'vncpasswd -f < "$1/vnc-password" > "$1/vnc-passwd.bin" && chmod 600 "$1/vnc-passwd.bin"' - "$creds"
|
||||
box Xvnc "$display" -geometry "${w}x${h}" -depth 24 \
|
||||
-interface "$addr" -rfbport "$vnc_port" \
|
||||
-SecurityTypes VncAuth -PasswordFile "$creds/vnc-passwd.bin" \
|
||||
-AlwaysShared -desktop "Steam Frame (Frametop)" &
|
||||
xvnc=$!
|
||||
trap "kill $xvnc 2>/dev/null" EXIT
|
||||
sleep 2
|
||||
# Keep an RDP connection open inside the VNC screen. Reconnect if it drops.
|
||||
|
||||
# Keep an RDP connection open inside the VNC screen. Reconnect if it drops or the layout changes.
|
||||
# /cert:ignore is fine here: the connection never leaves this host.
|
||||
while kill -0 $xvnc 2>/dev/null; do
|
||||
DISPLAY=$display xfreerdp /v:"127.0.0.1:$rdp_port" /u:steamos /p:"$(cat "$creds/password")" \
|
||||
/cert:ignore /size:"${width}x${height}" -decorations /f +clipboard >/dev/null 2>&1 || true
|
||||
read -r x y w h ww wh <<< "$v"
|
||||
box env DISPLAY=$display bash -c '
|
||||
size=$1 x=$2 y=$3 ww=$4 wh=$5 creds=$6 rdp_port=$7
|
||||
if [ "$(xrandr | sed -n "s/.*current \([0-9]*\) x \([0-9]*\),.*/\1x\2/p")" != "$size" ]; then
|
||||
xrandr --newmode "$size" 0 "${size%x*}" 0 0 0 "${size#*x}" 0 0 0 2>/dev/null || true
|
||||
xrandr --addmode VNC-0 "$size" 2>/dev/null || true
|
||||
xrandr --fb "$size" --output VNC-0 --mode "$size"
|
||||
fi
|
||||
xfreerdp /v:127.0.0.1:"$rdp_port" /u:steamos /p:"$(cat "$creds/password")" \
|
||||
/cert:ignore /size:"${ww}x${wh}" -decorations +clipboard >/dev/null 2>&1 &
|
||||
rdp=$!
|
||||
# FreeRDP takes no negative position, so move its window once it is up.
|
||||
for _ in $(seq 60); do
|
||||
win=$(xdotool search --class xfreerdp 2>/dev/null | tail -1)
|
||||
[ -n "$win" ] && break
|
||||
sleep 0.5
|
||||
done
|
||||
[ -n "$win" ] && xdotool windowmove "$win" "$((-x))" "$((-y))"
|
||||
wait $rdp
|
||||
' vnc-rdp "${w}x$h" "$x" "$y" "$ww" "$wh" "$creds" "$rdp_port" || true &
|
||||
rdp=$!
|
||||
while kill -0 $rdp 2>/dev/null; do
|
||||
sleep 5
|
||||
now=$(view) || continue
|
||||
[ -n "$now" ] && [ "$now" != "$v" ] || continue
|
||||
echo "layout changed: $v -> $now"
|
||||
v=$now
|
||||
stop_rdp
|
||||
done
|
||||
wait $rdp 2>/dev/null || true
|
||||
sleep 2
|
||||
done
|
||||
' vnc-bridge "$creds" "$addr" "$vnc_port" "$rdp_port" "$display" "$width" "$height"
|
||||
Reference in new issue
Block a user