fix: Fixed scale and mouse handler
Server Deploy / deploy (push) Successful in 1m38s

This commit is contained in:
2026-07-20 09:49:20 +01:00
parent c558b81471
commit c3c58581cc
2 changed files with 26 additions and 5 deletions
+17 -4
View File
@@ -15,7 +15,11 @@ export default function ServerConsolePage() {
const serverId = params.id as string;
const containerRef = useRef<HTMLDivElement>(null);
const connectionRef = useRef<{ disconnect: () => void; setScale: (scale: number) => void } | null>(null);
const connectionRef = useRef<{
disconnect: () => void;
setScale: (scale: number) => void;
resize: (width: number, height: number) => void;
} | null>(null);
const [protocol, setProtocol] = useState<string>(searchParams.get("protocol") || "");
const [keyId, setKeyId] = useState<string>("");
@@ -121,9 +125,18 @@ export default function ServerConsolePage() {
setPending(null);
}, [connected, pending]);
// Apply zoom changes live without reconnecting.
// Apply zoom live without reconnecting: resize the remote to a resolution
// that, once scaled to fit the container, yields the requested zoom. Higher
// zoom = fewer remote pixels rendered larger. Display always fits the
// container exactly, so no scrollbars appear.
useEffect(() => {
connectionRef.current?.setScale(zoom / dprRef.current);
if (!connectionRef.current || !containerRef.current) return;
const rect = containerRef.current.getBoundingClientRect();
const dpr = dprRef.current;
const remoteW = Math.floor((rect.width * dpr) / zoom);
const remoteH = Math.floor((rect.height * dpr) / zoom);
connectionRef.current.resize(remoteW, remoteH);
connectionRef.current.setScale(zoom / dpr);
}, [zoom]);
function handleDisconnect() {
@@ -276,7 +289,7 @@ export default function ServerConsolePage() {
<div
ref={containerRef}
className="min-h-[500px] flex-1 overflow-auto rounded-lg border border-border bg-black"
className="min-h-[500px] flex-1 overflow-hidden rounded-lg border border-border bg-black"
/>
</div>
);
+9 -1
View File
@@ -6,7 +6,7 @@ export function openConsole(
container: HTMLElement,
wsUrl: string,
connectData = ""
): { disconnect: () => void; setScale: (scale: number) => void } {
): { disconnect: () => void; setScale: (scale: number) => void; resize: (width: number, height: number) => void } {
// Guacamole's WebSocketTunnel builds the socket URL as `wsUrl + "?" + data`,
// so wsUrl must NOT already contain a query string — pass params via connectData.
const tunnel = new Guacamole.WebSocketTunnel(wsUrl);
@@ -46,10 +46,15 @@ export function openConsole(
const keyboard = new Guacamole.Keyboard(container);
keyboard.onkeydown = (k: number) => client.sendKeyEvent(1, k);
keyboard.onkeyup = (k: number) => client.sendKeyEvent(0, k);
// Guacamole.Mouse consumes the native mousedown, so clicking the console never
// moves DOM focus back to it. Refocus explicitly so keyboard capture resumes.
const refocus = () => container.focus();
container.addEventListener("mousedown", refocus);
container.focus();
return {
disconnect() {
container.removeEventListener("mousedown", refocus);
keyboard.onkeydown = null;
keyboard.onkeyup = null;
if (typeof keyboard.reset === "function") keyboard.reset();
@@ -59,5 +64,8 @@ export function openConsole(
scale = s;
display.scale(s);
},
resize(width: number, height: number) {
client.sendSize(width, height);
},
};
}