DOM: typed non-ASCII characters reach onTextInput truncated, and Ctrl or Meta letters reach it as text #187

Open
opened 2026-10-31 17:22:47 +00:00 by jorijnvdgraaf · 0 comments

Summary

Two problems with the text the DOM backend takes from keydown, both on the path from additional/dom-env.js:557-563 to __crafterDom_keyDown (implementations/Crafter.Graphics-Window.cpp:2050-2084), at 852ae8a.

Non-ASCII keys arrive truncated

dom-env.js:560 passes e.key.length as the key's length. That counts UTF-16 code units, but __writeUtf8 (:42) wrote the key as UTF-8, so for anything outside ASCII the length is too short. 'é' is one unit and two bytes, so onTextInput gets the lone lead byte C3; '€' becomes E2; a key that produces an emoji (two units, four bytes) gets its first two bytes. An InputField then holds invalid UTF-8. e.code.length is right only because codes are ASCII.

Fix: pass the UTF-8 byte length, for instance by having __writeUtf8 return it with the pointer.

Ctrl and Meta letters become text

__crafterDom_keyDown forwards any one-byte printable key to onTextInput (Window.cpp:2079) without looking at the modifiers, so Ctrl+C, Ctrl+V, Ctrl+A or Cmd+Z in an InputField also types 'c', 'v', 'a' or 'z', besides firing onRawKeyDown. On Win32 those keys arrive as control characters, 0x01 to 0x1A, which the WM_CHAR handler drops.

Fix: pass the modifiers along and skip the text when Ctrl or Meta is down without AltGr. Browsers on Windows report AltGr as Ctrl+Alt, and e.getModifierState("AltGraph") tells them apart, so AltGr+E still types '€'.

Found while reviewing claude/win32-title.

## Summary Two problems with the text the DOM backend takes from `keydown`, both on the path from `additional/dom-env.js:557-563` to `__crafterDom_keyDown` (`implementations/Crafter.Graphics-Window.cpp:2050-2084`), at `852ae8a`. ## Non-ASCII keys arrive truncated `dom-env.js:560` passes `e.key.length` as the key's length. That counts UTF-16 code units, but `__writeUtf8` (`:42`) wrote the key as UTF-8, so for anything outside ASCII the length is too short. 'é' is one unit and two bytes, so `onTextInput` gets the lone lead byte `C3`; '€' becomes `E2`; a key that produces an emoji (two units, four bytes) gets its first two bytes. An `InputField` then holds invalid UTF-8. `e.code.length` is right only because codes are ASCII. Fix: pass the UTF-8 byte length, for instance by having `__writeUtf8` return it with the pointer. ## Ctrl and Meta letters become text `__crafterDom_keyDown` forwards any one-byte printable key to `onTextInput` (`Window.cpp:2079`) without looking at the modifiers, so Ctrl+C, Ctrl+V, Ctrl+A or Cmd+Z in an `InputField` also types 'c', 'v', 'a' or 'z', besides firing `onRawKeyDown`. On Win32 those keys arrive as control characters, 0x01 to 0x1A, which the `WM_CHAR` handler drops. Fix: pass the modifiers along and skip the text when Ctrl or Meta is down without AltGr. Browsers on Windows report AltGr as Ctrl+Alt, and `e.getModifierState("AltGraph")` tells them apart, so AltGr+E still types '€'. Found while reviewing `claude/win32-title`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Catcrafts/Crafter.Graphics#187
No description provided.