add command palet and do final fixes for inputs with remote desktop and hvnc from the client.
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
export const CAPTURE_FLAG = "__overlordCapturingKeyboard";
|
||||
|
||||
function isEditableTarget(container) {
|
||||
const el = document.activeElement;
|
||||
if (!el) return false;
|
||||
if (el === document.body) return false;
|
||||
if (container && el === container) return false;
|
||||
const tag = el.tagName;
|
||||
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
|
||||
if (el.isContentEditable) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const SYSTEM_KEY_CODES = [
|
||||
"Escape",
|
||||
"Tab",
|
||||
"ContextMenu",
|
||||
"MetaLeft", "MetaRight", "OSLeft", "OSRight",
|
||||
"AltLeft", "AltRight",
|
||||
"ControlLeft", "ControlRight",
|
||||
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
|
||||
"KeyT", "KeyN", "KeyW", "KeyL", "KeyR", "KeyS", "KeyF", "KeyP", "KeyJ", "KeyH",
|
||||
"PrintScreen",
|
||||
];
|
||||
|
||||
function tryLock() {
|
||||
try {
|
||||
if (navigator.keyboard && navigator.keyboard.lock) {
|
||||
navigator.keyboard.lock(SYSTEM_KEY_CODES);
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function tryUnlock() {
|
||||
try {
|
||||
if (navigator.keyboard && navigator.keyboard.unlock) {
|
||||
navigator.keyboard.unlock();
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
export function createKeyboardCapture({ container, sendKeyDown, sendKeyUp, onTextInput }) {
|
||||
let enabled = false;
|
||||
const pressed = new Map();
|
||||
|
||||
function handleDown(e) {
|
||||
if (!enabled) return;
|
||||
if (isEditableTarget(container)) 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);
|
||||
} else {
|
||||
sendKeyDown(e);
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
function handleUp(e) {
|
||||
if (!enabled) return;
|
||||
if (isEditableTarget(container)) 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();
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
sendKeyUp(e);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
function releaseAll() {
|
||||
for (const v of pressed.values()) sendKeyUp(v);
|
||||
pressed.clear();
|
||||
}
|
||||
|
||||
function handleBlur() { releaseAll(); }
|
||||
function handleVisibility() { if (document.visibilityState === "hidden") releaseAll(); }
|
||||
function handleContextMenu(e) { if (enabled && !isEditableTarget(container)) e.preventDefault(); }
|
||||
function handleFullscreenChange() {
|
||||
if (enabled) tryLock();
|
||||
}
|
||||
|
||||
return {
|
||||
isEnabled() { return enabled; },
|
||||
enable() {
|
||||
if (enabled) return;
|
||||
enabled = true;
|
||||
window[CAPTURE_FLAG] = true;
|
||||
window.addEventListener("keydown", handleDown, { capture: true });
|
||||
window.addEventListener("keyup", handleUp, { capture: true });
|
||||
window.addEventListener("blur", handleBlur);
|
||||
window.addEventListener("contextmenu", handleContextMenu, { capture: true });
|
||||
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];
|
||||
window.removeEventListener("keydown", handleDown, { capture: true });
|
||||
window.removeEventListener("keyup", handleUp, { capture: true });
|
||||
window.removeEventListener("blur", handleBlur);
|
||||
window.removeEventListener("contextmenu", handleContextMenu, { capture: true });
|
||||
document.removeEventListener("visibilitychange", handleVisibility);
|
||||
document.removeEventListener("fullscreenchange", handleFullscreenChange);
|
||||
tryUnlock();
|
||||
releaseAll();
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user