From 958fc1fa02286a239cffd37f9c96e0df6dbd3776 Mon Sep 17 00:00:00 2001 From: drewvogg Date: Fri, 14 Aug 2026 18:36:35 -0500 Subject: [PATCH] fix(chromium-headful): recover keyboard input when Chromium reports keyCode 229 Some Windows + Chromium configurations report keyCode 229 for every keydown on a text field, even when no IME is active. The unconditional early return in the keydown handler then drops every keystroke, while mouse input keeps working -- users can click in the live view but cannot type anywhere, including the browser's own address bar. interpret_event() only interprets an event log that begins with a keydown or a keyup, so the keypress following a dropped keydown is orphaned and never interpreted. That is why no key works rather than only some. Fall through instead of returning, and skip only genuine composition (isComposing, or the "Process" sentinel for the composition-starting keydown, where isComposing is still false). This recovers both observed shapes of the quirk: keyCode 229 with a usable key string resolves via the existing key-over-keyCode preference in KeydownEvent, and keyCode 229 with key "Unidentified" resolves from the following keypress. Co-Authored-By: Claude Opus 5 --- .../client/src/utils/guacamole-keyboard.js | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/images/chromium-headful/client/src/utils/guacamole-keyboard.js b/images/chromium-headful/client/src/utils/guacamole-keyboard.js index df0b93cf..4f1e75a1 100644 --- a/images/chromium-headful/client/src/utils/guacamole-keyboard.js +++ b/images/chromium-headful/client/src/utils/guacamole-keyboard.js @@ -1318,8 +1318,31 @@ Guacamole.Keyboard = function Keyboard(element) { // Ignore (but do not prevent) the "composition" keycode sent by some // browsers when an IME is in use (see: http://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html) - if (keydownEvent.keyCode === 229) - return; + // + // KERNEL: Some Windows + Chromium configurations report keyCode 229 for + // *every* keydown on a text field, even when no IME is in use (see: + // https://bugs.chromium.org/p/chromium/issues/detail?id=864911). + // Returning unconditionally here silently drops all keyboard input on + // those machines, while mouse input keeps working, because + // interpret_event() only interprets a log that begins with a keydown or + // a keyup -- the keypress that follows a dropped keydown is orphaned and + // never interpreted. + // + // Falling through recovers both known shapes of this quirk: + // + // - keyCode 229 with a usable "key" ("a", "Enter"): KeydownEvent + // already prefers "key" over "keyCode" when resolving a keysym. + // - keyCode 229 with key "Unidentified": the keydown resolves to a + // null keysym, and interpret_event() then takes the keysym from the + // following keypress, which carries the correct character. + // + // Only genuine composition is skipped. isComposing is false on the very + // first keydown that *starts* composition, so the "Process" sentinel is + // still needed to catch that event and avoid a duplicate keystroke. + if (keydownEvent.keyCode === 229) { + if (e.isComposing || keydownEvent.key === 'Process') + return; + } // Log event eventLog.push(keydownEvent);