中文摘要: 在带死键(dead key)的键盘布局上(西班牙语、法语、美式国际、北欧等),打字练习完全无法输入撇号 ':浏览器把死键报告为 key='Dead',会被当成字面字符 "Dead" 进入输入内容;而把死键"落"成字符的组合空格又被当成真正的分词空格,导致正在输入的单词被跳过。现有输入管线(隐藏输入框 + keyCode 229 过滤)是为中文 IME + 美式键盘设计的,没有覆盖死键布局。
Bug description
TypeWords' keydown handling assumes a plain US-English keyboard. On layouts where ', ", ^, ~, ` are dead keys (Spanish, French AZERTY, US-International, Italian, Nordic, Polish-programmer, Turkish…), typing practice breaks in two ways:
- The apostrophe cannot be typed at all. To produce a literal
', users press the dead key and then Space (the composition terminator the OS consumes). Chromium/Gecko report the dead-key keydown as key='Dead', which currently enters the typing pipeline as the literal text "Dead".
- The word being typed gets skipped/hidden. The Space that terminates the dead-key composition is treated as a real word-separator space, so the current word is completed/advanced mid-word (e.g. typing
Harry' + Space + s for Harry's jumps to the next word right after the apostrophe).
Root cause
The existing input pipeline (hidden #typing-listener input + keyCode 229 filter + keydown↔input dedup) was designed for Chinese IME users on a US physical keyboard, and has no dead-key handling:
- Browsers report dead keys two different ways, and neither is currently handled:
- Model 1 —
key='Dead' (Chromium/Gecko on Linux/Windows/macOS): the dead-key keydown itself is forwarded to the typing handlers as a character.
- Model 2 — base character (some environments): the dead-key keydown looks like a normal
' but inserts no character until the next key; the composition Space then arrives as a real Space keydown.
- The composed character does arrive through the hidden input's
input event (layout-agnostic), so no new plumbing is needed — only correct dead-key lifecycle handling on top of it.
Proposed solution
(implemented, PR follows)
- Drop
key='Dead' keydowns from the pipeline — the real character is already delivered by the OS composition through the hidden input's input event.
- Swallow the Space keydown that immediately follows a dead key (it is a composition terminator consumed by the OS, not a word separator).
- For Model 2: track a pending-composition state on apostrophe-class keydowns and clear it when a real character lands in the hidden input — so plain English layouts (real
' followed by real Space) are completely unaffected.
- Unit tests for both reporting models + the English no-regression case.
Impact
Dead-key layouts cover hundreds of millions of typists (es, fr, it, pt, ca, Nordic, US-Intl…). Since TypeWords' audience is precisely non-English-keyboard users learning English, this affects a core audience. The app already partially acknowledges non-US keyboards (keyCode 229 handling, full-width ‘ ’ “ ” Quote mapping).
Environment
- Verified by analysis + unit tests on Linux with the Spanish (
es) layout (Chromium reports key='Dead').
- Not yet verified on real macOS/Windows hardware — reports from users on those platforms are welcome.
中文摘要: 在带死键(dead key)的键盘布局上(西班牙语、法语、美式国际、北欧等),打字练习完全无法输入撇号
':浏览器把死键报告为key='Dead',会被当成字面字符 "Dead" 进入输入内容;而把死键"落"成字符的组合空格又被当成真正的分词空格,导致正在输入的单词被跳过。现有输入管线(隐藏输入框 + keyCode 229 过滤)是为中文 IME + 美式键盘设计的,没有覆盖死键布局。Bug description
TypeWords' keydown handling assumes a plain US-English keyboard. On layouts where
',",^,~,`are dead keys (Spanish, French AZERTY, US-International, Italian, Nordic, Polish-programmer, Turkish…), typing practice breaks in two ways:', users press the dead key and then Space (the composition terminator the OS consumes). Chromium/Gecko report the dead-key keydown askey='Dead', which currently enters the typing pipeline as the literal text"Dead".Harry'+ Space +sforHarry'sjumps to the next word right after the apostrophe).Root cause
The existing input pipeline (hidden
#typing-listenerinput +keyCode 229filter + keydown↔input dedup) was designed for Chinese IME users on a US physical keyboard, and has no dead-key handling:key='Dead'(Chromium/Gecko on Linux/Windows/macOS): the dead-key keydown itself is forwarded to the typing handlers as a character.'but inserts no character until the next key; the composition Space then arrives as a real Space keydown.inputevent (layout-agnostic), so no new plumbing is needed — only correct dead-key lifecycle handling on top of it.Proposed solution
(implemented, PR follows)
key='Dead'keydowns from the pipeline — the real character is already delivered by the OS composition through the hidden input'sinputevent.'followed by real Space) are completely unaffected.Impact
Dead-key layouts cover hundreds of millions of typists (es, fr, it, pt, ca, Nordic, US-Intl…). Since TypeWords' audience is precisely non-English-keyboard users learning English, this affects a core audience. The app already partially acknowledges non-US keyboards (keyCode 229 handling, full-width
‘ ’ “ ”Quote mapping).Environment
es) layout (Chromium reportskey='Dead').