From a129913bb072bfa77832a7eb28eff9ff9af93959 Mon Sep 17 00:00:00 2001 From: KingKDot Date: Mon, 20 Jul 2026 17:19:44 -0500 Subject: [PATCH] fix keyboard capturing to limit it a bit + default to canvas mode for everything --- Overlord-Server/public/assets/backstage.js | 4 +- .../public/assets/keyboard-capture.js | 60 +++++++++++++++---- .../public/assets/remotedesktop.js | 4 +- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/Overlord-Server/public/assets/backstage.js b/Overlord-Server/public/assets/backstage.js index da5a0a3..3013253 100644 --- a/Overlord-Server/public/assets/backstage.js +++ b/Overlord-Server/public/assets/backstage.js @@ -122,6 +122,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s let whepClient = null; let p2pClient = null; let webrtcActive = false; + const CANVAS_TRANSPORT_PREF_VERSION = 1; function getWebrtcMode() { return webrtcMode ? String(webrtcMode.value || "off") : "off"; @@ -178,7 +179,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s savedDisplay = Number.isFinite(Number(settings.display)) ? Number(settings.display) : savedDisplay; setSelectValue(backstageResolutionSelect, settings.resolution); setSelectValue(targetFpsSelect, settings.targetFps); - setSelectValue(webrtcMode, settings.webrtcMode); + setSelectValue(webrtcMode, settings.transportPreferenceVersion === CANVAS_TRANSPORT_PREF_VERSION ? settings.webrtcMode : "off"); if (qualitySlider && settings.quality !== undefined) qualitySlider.value = String(settings.quality); if (mouseCtrl && typeof settings.mouse === "boolean") mouseCtrl.checked = settings.mouse; if (kbdCtrl && typeof settings.keyboard === "boolean") kbdCtrl.checked = settings.keyboard; @@ -206,6 +207,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s quality: Number(qualitySlider?.value || 90), preferH264: !!prefersH264, webrtcMode: getWebrtcMode(), + transportPreferenceVersion: CANVAS_TRANSPORT_PREF_VERSION, mouse: !!mouseCtrl?.checked, keyboard: !!kbdCtrl?.checked, clipboardSync: !!clipboardSyncCtrl?.checked, diff --git a/Overlord-Server/public/assets/keyboard-capture.js b/Overlord-Server/public/assets/keyboard-capture.js index 502cb32..ef254ba 100644 --- a/Overlord-Server/public/assets/keyboard-capture.js +++ b/Overlord-Server/public/assets/keyboard-capture.js @@ -11,6 +11,12 @@ function isEditableTarget(container) { return false; } +function hasCaptureFocus(container) { + if (!container) return true; + const el = document.activeElement; + return !!el && (el === container || container.contains(el)); +} + const SYSTEM_KEY_CODES = [ "Escape", "Tab", @@ -43,9 +49,39 @@ export function createKeyboardCapture({ container, sendKeyDown, sendKeyUp, onTex let enabled = false; const pressed = new Map(); + function setCaptureFlag(active) { + if (active) window[CAPTURE_FLAG] = true; + else delete window[CAPTURE_FLAG]; + } + + function refreshCaptureState() { + if (!enabled) { + setCaptureFlag(false); + return; + } + if (hasCaptureFocus(container)) { + setCaptureFlag(true); + tryLock(); + } else { + setCaptureFlag(false); + tryUnlock(); + releaseAll(); + } + } + + function shouldCapture() { + if (!enabled) return false; + if (!hasCaptureFocus(container)) { + refreshCaptureState(); + return false; + } + if (isEditableTarget(container)) return false; + setCaptureFlag(true); + return true; + } + function handleDown(e) { - if (!enabled) return; - if (isEditableTarget(container)) return; + if (!shouldCapture()) return; pressed.set(e.code || e.key, { key: e.key, code: e.code }); if (onTextInput && !e.ctrlKey && !e.metaKey && !e.altKey && typeof e.key === "string" && e.key.length === 1) { onTextInput(e); @@ -57,8 +93,7 @@ export function createKeyboardCapture({ container, sendKeyDown, sendKeyUp, onTex } function handleUp(e) { - if (!enabled) return; - if (isEditableTarget(container)) return; + if (!shouldCapture()) return; pressed.delete(e.code || e.key); if (onTextInput && !e.ctrlKey && !e.metaKey && !e.altKey && typeof e.key === "string" && e.key.length === 1) { e.preventDefault(); @@ -77,34 +112,35 @@ export function createKeyboardCapture({ container, sendKeyDown, sendKeyUp, onTex function handleBlur() { releaseAll(); } function handleVisibility() { if (document.visibilityState === "hidden") releaseAll(); } - function handleContextMenu(e) { if (enabled && !isEditableTarget(container)) e.preventDefault(); } - function handleFullscreenChange() { - if (enabled) tryLock(); - } + function handleContextMenu(e) { if (shouldCapture()) e.preventDefault(); } + function handleFocusChange() { setTimeout(refreshCaptureState, 0); } + function handleFullscreenChange() { refreshCaptureState(); } return { isEnabled() { return enabled; }, enable() { if (enabled) return; enabled = true; - window[CAPTURE_FLAG] = true; + refreshCaptureState(); window.addEventListener("keydown", handleDown, { capture: true }); window.addEventListener("keyup", handleUp, { capture: true }); window.addEventListener("blur", handleBlur); window.addEventListener("contextmenu", handleContextMenu, { capture: true }); + document.addEventListener("focusin", handleFocusChange); + document.addEventListener("focusout", handleFocusChange); document.addEventListener("visibilitychange", handleVisibility); document.addEventListener("fullscreenchange", handleFullscreenChange); - tryLock(); - if (container) try { container.focus({ preventScroll: true }); } catch {} }, disable() { if (!enabled) return; enabled = false; - delete window[CAPTURE_FLAG]; + setCaptureFlag(false); window.removeEventListener("keydown", handleDown, { capture: true }); window.removeEventListener("keyup", handleUp, { capture: true }); window.removeEventListener("blur", handleBlur); window.removeEventListener("contextmenu", handleContextMenu, { capture: true }); + document.removeEventListener("focusin", handleFocusChange); + document.removeEventListener("focusout", handleFocusChange); document.removeEventListener("visibilitychange", handleVisibility); document.removeEventListener("fullscreenchange", handleFullscreenChange); tryUnlock(); diff --git a/Overlord-Server/public/assets/remotedesktop.js b/Overlord-Server/public/assets/remotedesktop.js index ee4ac8d..26a937f 100644 --- a/Overlord-Server/public/assets/remotedesktop.js +++ b/Overlord-Server/public/assets/remotedesktop.js @@ -124,6 +124,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s let lastRemoteCursor = null; let remoteCursorShape = null; let remoteCursorImageUrl = ""; + const CANVAS_TRANSPORT_PREF_VERSION = 1; function getWebrtcMode() { return webrtcMode ? String(webrtcMode.value || "off") : "off"; } @@ -483,7 +484,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s : savedStreamProfile); setSelectValue(streamProfileSelect, savedStreamProfile); setSelectValue(bitrateSelect, settings.bitrateMbps); - setSelectValue(webrtcMode, settings.webrtcMode); + setSelectValue(webrtcMode, settings.transportPreferenceVersion === CANVAS_TRANSPORT_PREF_VERSION ? settings.webrtcMode : "off"); setSelectValue(audioTransport, settings.audioTransport); setSelectValue(recordMode, settings.recordMode); setSelectValue(recordFps, settings.recordFps); @@ -519,6 +520,7 @@ import { createSharedUiSettingsSaver, loadSharedUiSettings } from "./shared-ui-s bitrateMbps: Number(bitrateSelect?.value || 0), preferH264: !!prefersH264, webrtcMode: getWebrtcMode(), + transportPreferenceVersion: CANVAS_TRANSPORT_PREF_VERSION, mouse: !!mouseCtrl?.checked, keyboard: !!kbdCtrl?.checked, cursor: !!cursorCtrl?.checked,