Backspace, Enter, Tab, Escape and the arrow and page keys are matched by
keysym alone -- strans.c:852, 875 and 882 name them, and searchkey names
the same set at strans.c:746-786. Every other key above Kspec falls
through to the catch-all at strans.c:898, `ks >= Kspec || chord(mod)`,
and goes to the application. So the special keys strans knows by name
are the ones it takes under a modifier, and the ones it does not know are
the ones it hands over. That is backwards: a named special key under a
modifier is exactly the one the application has a binding for.
In Korean a syllable is pending for nearly all the time anyone is typing,
ko.c holding one and no more, and the guards at strans.c:876 and 883
return 0 only when nothing is pending -- so the key is eaten precisely
when it is wanted. Type 안녕하세요 and reach for Ctrl+Backspace to take
the word back: 요 loses ㅛ, then ㅇ, and the word itself goes on the third
press. Ctrl+Enter in a chat box, Ctrl+Tab in a browser and Ctrl+PageDown
in either are the same key eaten by the same lines.
before after
Korean 가, Ctrl+Backspace eaten, pre ㄱ passed, commit 가
Korean 가, Alt+Backspace eaten, pre ㄱ passed, commit 가
Korean 가, Super+Backspace eaten, pre ㄱ passed, commit 가
Korean 가, Backspace eaten, pre ㄱ unchanged
Korean 가, Shift+Backspace eaten, pre ㄱ unchanged
かく, Ctrl+Enter eaten, commit かく passed, commit かく
かく, Ctrl+Tab eaten, commit かく passed, commit かく
かく Space, Ctrl+PageDown eaten, sel 0 -> 9 passed, commit 確
かく Space, PageDown eaten, sel 0 -> 9 unchanged
かく Space, Shift+Tab eaten, sel 0 -> 30 unchanged
Ctrl+E sm, Ctrl+Backspace eaten, query s passed, commit sm
Ctrl+E sm, Backspace eaten, query s unchanged
chord() cannot be reused here. It is `(mod & ~Mshift) != 0 && mod !=
Mctrl` and the exclusion is deliberate, since Ctrl+letter is strans's
whole command set and chord() has to let plain Ctrl through. The rule
this needs is the other one -- any modifier that is not Shift -- and
Shift must stay in: Shift+Tab cycles the candidates backwards, pinned by
engine/candidate-completion and engine/emoji-navigation at
engine_test.c:914 and 1649, and Shift on a Korean key is what makes ㅃ.
One line serves both paths because it sits above the searchkey dispatch,
and it has to sit below the switch at strans.c:829: 한자, 한/영, 変換 and
無変換 arrive as keys above Kspec and are rewritten there into the Ctrl
chords they stand for. Above the switch, 한자 would commit and pass
instead of opening the Hanja list; below it, pressing it with Ctrl held
still opens the list, because the switch sets the modifier itself.
What this does not cover: Space, which is below Kspec, so searchkey:763
still picks a candidate on Ctrl+Space inside a search. transition tests
!(mod & ~Mshift) for its own Space at strans.c:865, so the two disagree
there. Left alone: what Ctrl+Space should mean wants its own argument,
not a widened guard.