Show input method composition in text fields - #10195
Conversation
Text being composed by an input method was invisible until it was committed, so typing anything through an IME looked like nothing was happening. Take the composition state the engine now reports and draw it at the caret, underlined to mark it as uncommitted, and tell the engine where that caret is so the candidate window can follow it. A single-line field selects all of its text when focused; collapse that to the end of the selection once composing starts, since that is where the text will be inserted and where the candidate window belongs.
| self.sel = nil | ||
| end | ||
| local viewOriginX, viewOriginY = textX, textY | ||
| if self.hasFocus and SetIMECaretRect and not self.lineHeight then |
There was a problem hiding this comment.
IME composition is still skipped in multiline editors such as Notes. NotesTab sets lineHeight = 16, so this guard disables caret reporting and the preedit-rendering block below is bypassed. Users therefore still compose blindly in Notes, with no current caret rectangle for the candidate window. Could the multiline draw path receive equivalent preedit rendering and caret positioning?
Native macOS IME behavior was not exercised in this review.
AI-assisted review disclosure: This finding was identified during a review using OpenAI Codex.
| end | ||
| if SetIMECaretRect then | ||
| -- Refine the position now that the composition width is known. | ||
| SetIMECaretRect(viewOriginX + textX, viewOriginY + textY, 1, textHeight) |
There was a problem hiding this comment.
OnPreedit's caret byte offset is stored in main.imePreeditCaret but never read. Draw advances textX by the full preedit before drawing the caret and calling SetIMECaretRect, so an IME caret inside the composition is shown at the end and the candidate window follows the wrong position. Could the preedit be split at that offset and the caret rectangle placed after its prefix?
Native macOS IME behavior was not exercised in this review.
AI-assisted review disclosure: This finding was identified during a review using OpenAI Codex.
Description of the problem being solved
Text an input method is still composing is invisible until it is committed, so typing through an IME looks like nothing is happening — no characters, no underline, and the candidate window has no caret to attach itself to. This affects anyone typing Chinese, Japanese or Korean into a build name, note or search field.
This is the application half of the work; the engine half is being submitted to the macOS engine port separately. Related: #5632.
Description of the changes
OnPreeditcallback and hold it onmain. It is state rather than an input event, since it is replaced wholesale on every keystroke and discarded when composing ends.EditControl.Everything is guarded:
SetIMECaretRectis only called if the running engine provides it, andmain.imePreeditis nil unless the engine sends a composition. On an engine without IME support this changes nothing.Steps taken to verify a working solution
Tested on macOS with the system Bopomofo input method and a third-party one: