Implement proper visuals for IME composition#8083
Conversation
|
Preview available at https://egui-pr-preview.github.io/pr/8083-ime-preedit-visuals View snapshot changes at kitdiff |
As its parameter list is not well thought out.
| Preedit { | ||
| text: String, | ||
| active_range_chars: Option<std::ops::Range<usize>>, | ||
| }, |
There was a problem hiding this comment.
I'd actually prefer to define it as:
Preedit {
text: String,
active_range: Option<CCursorRange>,
},However, since CCursorRange doesn't implement Eq, this leaves a few options:
- Use
Option<std::ops::Range<usize>>. (the current approach) - Remove
#[derive(Eq)]fromImeEvent. This is my preferred option, as I don't see a strong need forImeEventto implementEq. That said, I'm unsure whether downstream code might rely on this and thus be affected. - Implement
Eqfor bothCCursorRangeandCCursor, but it is unclear to me what equality should mean for these types. - Implement
EqforImeEventmanually without requiringEqon the underlying types, which feels off.
There was a problem hiding this comment.
Another consideration:
If we define active_range as Option<CCursorRange> and later switch the cursor index base from chars to graphemes (as in #62), should active_range also change accordingly (e.g., to Option<GCursorRange>)?
Alternatively, should we keep a more primitive representation (e.g. active_range_chars: Option<std::ops::Range<usize>> or even active_range_bytes: Option<std::ops::Range<usize>>) and handle the conversion within egui?
This would avoid requiring downstream to pull additional crates (e.g. unicode-segmentation), which could introduce duplicated dependencies in binary or inconsistencies with the ones used internally by egui.
|
In Korean, the text cursor should not be placed before a character; it should be placed after the character. |
Yes, I mentioned this earlier in #8083 (comment), where I described it as a bug. As a workaround, I hid the cursor when it is at the beginning. As I understand it, during Korean composition, the cursor only appears at the end of the composition text. So users should still be able to identify the cursor position by looking at the end of the underline, and since the cursor is hidden, it should not be a distraction. Did this workaround fail to take effect for you? |


This PR adds visual support for IME composition, including the cursor and conversion segment.
These visuals works (mostly) well on native platforms (
egui-winit). On the web (eframe/web), support is limited by browser capabilities: Chromium works well, Firefox shows partial improvement, and Safari remains subpar.Details
We extend
egui::ImeEvent::Preedit(String)toegui::ImeEvent::Preedit { text: String, active_range_chars: Option<std::ops::Range<usize>> }.The new
active_range_charsfield enables rendering of:in IME composition.
In
egui-winit, we now use the range provided bywinit::event::Ime::Preeditinstead of ignoring it.In
eframe/web, we derive the range fromselectionStartandselectionEndon the text agent. This mapping is fully accurate only in Chromium, but represents the best available approach for now.Demonstrations
Chinese IMEs (Shuangpin)
We can see where the cursor is now.
After-macOS-CMN-small.mp4
Before-macOS-CMN-small.mp4
After-macOS-CMN-light-small.mp4
After-windows-CMN-small.mp4
After-wayland-ibus-CMN-IntelligentPinyin-small.mp4
macOS builtin.macOS builtin.Japanese IMEs
We can see where the conversion segment is now.
After-macOS-JPN-small.mp4
Before-macOS-JPN-small.mp4
After-macOS-JPN-light-small.mp4
After-windows-JPN-small.mp4
After-wayland-ibus-JPN-Anthy-small.mp4
macOS builtin.After-Firefox-macOS-JPN-small.mp4
Korean IMEs
We can clearly tell whether we are in composition (in contrast to selection) now.
After-macOS-KOR-small.mp4
Before-macOS-KOR-small.mp4
After-macOS-KOR-light-small.mp4
winitbug applied.)After-windows-KOR-x-small.mp4
After-wayland-ibus-KOR-Hangul-small.mp4
macOS builtin.Windows builtin.macOS builtin. (ignoring the fact that the composition breaks when typing the second Hangul. (This bug predates this PR.))