Hello.
I am a Japanese software developer. I am interested in text input in the CJK language in iced.
As some of you may know, the CJK language requires a mechanism that called “Input Method” for text input (or IME, also known as the abbreviation of Input Method Editor.) In other words, I hope CJK Input method will be supported in iced.
Several Pull requests have been submitted in the past, but since the API Design has not been sufficiently discussed, it seems that the situation of not being merged continues. So, I would like to propose an API Design and start the discussion.
I appreciate for feedbacks to progress discussion!
Supporting input method with winit
Iced relies on winit for the abstraction of the native platform. Therefore, as a premise for discussion, I will explain what is needed for input method support for the winit app.
Following diagram shows basic interaction between input method and winit apps
The word “Preedit” in this figure may be an unfamiliar concept, it shows the intermediate state of the user entering complex words such as “漢字”(kanji) in the Input Method. Depending on the platform, it is also called “Composing Text”, “Composing String”, etc., but I call that “Preedit” here to clarify that it is a concept specific to the Input Method.
There are some display style of the preedit, implementation complexity depends on which style apps/widgets will support.
The following are the well-known types of Preedit display styles.
Off-the-spot | Over-the-spot | On-the-spot(Inline composing) |
---|---|---|
Preedit placed unrelated position | Preedit placed over original text | Preedit temporalily inserted into original text |
*“Off-the-spot” image refers to XIM による日本語入力
Type | Caret position required? |
Need to tell allow state? |
Who draws preedit? |
---|---|---|---|
Off-the-spot | NO | NO | Toolkit* |
Over-the-spot | YES | YES | Toolkit or app, it doesn’t affect to app’s text layout |
On-the-spot | YES | YES | App embeds composing text in document for Ime::Preedit events |
Basic strategy
On-the-spot (Inline) preedit is highest UX quality for CJK users, but it requires (custom) text input widgets to integrate tightly with the input method state. This is not easy for non-CJK developers to support (especially on testing).
So I suggest we have the “Over-the-spot” preedit support on iced first, while we should open the room some custom text input widgets can implement “On-the-spot” preedit style later if they want. We can discuss another mechanisms help to implement those with no hassle, but it is out of scope of this proposal.
How will it work?
How it enables the input method? And how it inputs text to the app?
- Focused text widget can report its “caret information” containig whether it accepts input with input method currently or not.
- Native layer (iced_winit) controls the input method state of a winit window from the current caret information.
- By this, winit starts sending input method events to iced.
- Text widget handles
Commit
input method event to insert the text sent from the input method.- We can basically reuse the clipboard pasting logic of the widget (some refactoring may be desirable, though)
Then, how it shows the “preedit string”?
- Native layer (iced_winit) handles the
Preedit
input method event from winit. - It receives the preedit string and place it as layer over the
UserInterface
with app’sRenderer
.
The caret information should looks like this:
pub struct CaretInfo {
pub position: Point,
pub input_method_allowed: bool,
pub shows_preedit_myself: bool,
}
How custom text widgets or apps can implement on-the-spot (inline) style preedit display in future?
- They can opt-out the over-the-spot preedit layer on reporting its focused caret information.
- Then, they can implement freely preedit with existing mechanisms.
- Handles
Preedit
input method events themselves. - Update in-widget or in-app state and build view tree for it.
- Handles
About reporting the caret information
I propose to let focused text input widget to set its caret information to the Shell
on Widget::update()
.
Because it is better avoiding API change of Widget
trait itself, as there are very limited set of widget types involved.
Controlling input method allowed or enabled state affects how shell (and underlying winit) notifies events for user key input. So there is some relevance.
Widgets decide its caret state on update()
method, so determining also input method related state there is natural and has enough flexibility.