mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
* fix(terminal): stop a Hangul-terminating digit being eaten as a candidate pick A digit typed immediately after a Hangul syllable is dropped in the terminal on Wayland. Typing 아1 produces 아. The syllable composes and commits correctly; only the keystroke that ends it is lost. Reproduced on Ubuntu 24.04, GNOME Shell 46, ibus-hangul 1.5.5, in a nested Wayland session with real key injection. The pty receives 아 on Wayland and 아1 under X11 on the same machine with the same engine, and a GTK client in the same Wayland session receives 아1 - so the compositor, the input method and the digit are all behaving. The difference is where the digit is delivered. Under X11 ibus-hangul swallows it into the preedit and commits 아1 as composition text. Under Wayland it commits 아 and lets the digit through as an ordinary key - and the jamo before it arrive with no keydown at all, only keyups. That orphaned keyup is what breaks it. A plain letter keyup with no matching keydown arms a 1500ms window in which a bare digit is treated as a candidate selection, because a Pinyin engine indexes its candidate list by digit. The digit lands microseconds later, inside the window, and is suppressed. The window disarms after exactly one digit, which is why the syllable survives and only the terminating key vanishes. A Hangul engine has no numbered candidates over its preedit - a digit ends the syllable and is literal text - so the guard was spending its one suppression on a keystroke meant for the shell. The tracker now records whether the current preedit is Hangul and the guard declines. Read from compositionupdate rather than compositionend: a Pinyin preedit is the Latin spelling being narrowed while its commit is the Han text, so reading the commit would misclassify Pinyin and reopen the bugs the guard was added for. Space is untouched; only digits are reclassified. Verified A/B/A on that machine: unfixed drops the digit, this change preserves it, reverting drops it again, three runs each. The X11 case and both existing ibus-hangul specs still pass. Closes #15299 * fix(terminal): expire the Hangul preedit flag and narrow its digit exemption Review of the #15299 fix found the Hangul classification could not be retired and that it exempted more than the reported bug. The flag was written only on a non-empty compositionupdate and cleared only on blur, so it latched for the whole focus session. Switching input engine (Hangul -> Pinyin) under fcitx/ibus moves no DOM focus, and the #8241 orphan-digit path emits no composition and no input events, so nothing could refresh or clear it. The stale flag then turned the #8241/#7543 Pinyin candidate-digit guard off silently and permanently - the regression those guards exist to prevent. It now expires against lastCompositionEventAt on the same staleness window as the neighbouring guards, and compositionstart clears it because the following compositionupdate re-reads the preedit script. It is deliberately not cleared on compositionend or on input: the bug is a digit arriving after the commit, and both recordings deliver the commit's own insertText before it. Clearing on either reverts the fix - the orphan-window test fails when input clears it. The exemption also gated suppressCandidateKey as a whole, so it fired during a live composition as well. That is broader than the bug, which is exclusively a digit after compositionend, and it is unsafe: the earlier claim that no Hangul engine indexes candidates by digit over a preedit is wrong. ibus-hangul's Hanja conversion (Hanja key / F9) puts a numbered lookup table over a live Hangul preedit, and its symbol table behaves the same. Only the orphan-keyup guard - which arms off a bare keyup and cannot see which engine produced it - now declines. The tests drove a shape neither recording produces: an empty compositionupdate immediately before compositionend, which armed the 250ms post-composition window. The Wayland reproduction has no empty update, and the X11 fixture follows its empty update with deleteContentBackward + insertText, which disarms that window. The suite now follows the recorded trace, asserts the 250ms window never arms, and covers both the expiry and the live-preedit Hanja case. Refs #15299