From 1cb50d769eebb752c374e5f4ace5c003f7181ab6 Mon Sep 17 00:00:00 2001 From: KoppePan <7379133+0141KoppePan@users.noreply.github.com> Date: Wed, 10 Dec 2025 22:21:15 +0900 Subject: [PATCH 1/2] fix: Handle Microsoft IME issue with Shift key detection --- ui/src/components/WebRTCVideo.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ui/src/components/WebRTCVideo.tsx b/ui/src/components/WebRTCVideo.tsx index c7a9d45c0..c0431a473 100644 --- a/ui/src/components/WebRTCVideo.tsx +++ b/ui/src/components/WebRTCVideo.tsx @@ -260,6 +260,9 @@ export default function WebRTCVideo({ hasConnectionIssues }: { hasConnectionIssu code = "Henkan"; } else if (code === "NonConvert") { code = "Muhenkan"; + // Microsoft IME fix + } else if (key === "Shift" && code === "") { + code = "ShiftRight" } return code; From 2b0dc2c67a69c8c5ffec46b429a04a8e052aac5e Mon Sep 17 00:00:00 2001 From: KoppePan <7379133+0141KoppePan@users.noreply.github.com> Date: Wed, 10 Dec 2025 22:53:39 +0900 Subject: [PATCH 2/2] fix: Microsoft IME keydown handling for Zenkaku/Hankaku keys --- ui/src/components/WebRTCVideo.tsx | 37 ++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/ui/src/components/WebRTCVideo.tsx b/ui/src/components/WebRTCVideo.tsx index c0431a473..65eae72e7 100644 --- a/ui/src/components/WebRTCVideo.tsx +++ b/ui/src/components/WebRTCVideo.tsx @@ -306,6 +306,13 @@ export default function WebRTCVideo({ hasConnectionIssues }: { hasConnectionIssu altGrLoopRef.current = true; lastKeyDownRef.current = null; } + + // Microsoft IME fix: + // Effective keydown events are consumed by IME (reported as "Process"), + // so we handle the full press/release cycle in the keyup handler instead. + if (["Zenkaku", "Hankaku", "ZenkakuHankaku"].includes(e.key)) { + return; + } } // When pressing the meta key + another key, the key will never trigger a keyup @@ -345,21 +352,29 @@ export default function WebRTCVideo({ hasConnectionIssues }: { hasConnectionIssu return; } - // On Windows, handle ControlLeft specially to preserve FIFO semantics with AltGr buffering. - if (isWindowsClient && hidKey === keys.ControlLeft) { + if (isWindowsClient) { + // On Windows, handle ControlLeft specially to preserve FIFO semantics with AltGr buffering. + if (hidKey === keys.ControlLeft) { + // Synthetic AltGr ControlLeft: never sent a down, swallow the release as well. + if (altGrLoopRef.current) { + altGrLoopRef.current = false; + return; + } - // Synthetic AltGr ControlLeft: never sent a down, swallow the release as well. - if (altGrLoopRef.current) { - altGrLoopRef.current = false; - return; - } + // Very fast real Ctrl tap: flush the pending down before the up. + if (lastKeyDownRef.current?.hidKey === keys.ControlLeft) { + handleKeyPress(keys.ControlLeft, true); + } - // Very fast real Ctrl tap: flush the pending down before the up. - if (lastKeyDownRef.current?.hidKey === keys.ControlLeft) { - handleKeyPress(keys.ControlLeft, true); + lastKeyDownRef.current = null; } - lastKeyDownRef.current = null; + // Microsoft IME fix: + // Synthesize the missing keydown event to ensure a complete key press cycle. + if (["Zenkaku", "Hankaku", "ZenkakuHankaku"].includes(e.key)) { + console.debug(`Synthesizing missed key down for IME key: ${e.key}`); + handleKeyPress(hidKey, true); + } } console.debug(`Key up: ${hidKey}`);