When invoking an action that would replace the marked text (“CJK edit buffer”) with a zero-length string, we would continue to be in “CJK” mode and thus allow the input manager to process the next key press.
In this situation though pressing e.g. escape or backspace would result in the input manager inserting the literal character code for this key.
So we now leave “CJK edit mode” if the “edit buffer” is empty.
There is still an issue though where, if the edit buffer is not empty, and the user press backspace, we correctly (?) ask the input manager to handle this key press, but the input manager will (wrongly) replace the selection with the literal backspace character.
We have our own version of interpretKeyEvents: because we want to augment the default key bindings dictionaries (and support multi-stroke key bindings).
When there is marked text (as part of inserting CJK or similar) the system’s version of interpretKeyEvents: seems to handle key bindings slightly different, for example where ↩ is normally bound to insertNewline:, this might be suppressed when the user has just selected a “translation”.