1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 22:53:14 -04:00
Files
egui/crates
Umaĵo 33e89e33be Improve IME handling, add public method owns_ime_events on Memory (#7983)
<!--
Please read the "Making a PR" section of
[`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/main/CONTRIBUTING.md)
before opening a Pull Request!

* Keep your PR:s small and focused.
* The PR title is what ends up in the changelog, so make it descriptive!
* If applicable, add a screenshot or gif.
* If it is a non-trivial addition, consider adding a demo for it to
`egui_demo_lib`, or a new example.
* Do NOT open PR:s from your `master` branch, as that makes it hard for
maintainers to test and add commits to your PR.
* Remember to run `cargo fmt` and `cargo clippy`.
* Open the PR as a draft until you have self-reviewed it and run
`./scripts/check.sh`.
* When you have addressed a PR comment, mark it as resolved.

Please be patient! I will review your PR, but my time is limited!
-->

* Depends on #7967
* Closes #7485
* Should fix #7906 (This issue doesn't seem to have been resolved, but
the author closed it; I personally don't have the environment to verify
whether it is fixed.)
* Replaces #4137, #4896, and partially #7810
* [x] I have followed the instructions in the PR template

This PR started as a fix for #7485, but has since evolved into a broader
rewrite of IME-related logic.

## Overview

This PR primarily introduces a new public method, `owns_ime_events`, on
[`Memory`], and refactors parts of [`TextEdit`] to integrate with it.

Previously, each [`TextEdit`] widget independently determined whether to
handle IME events and stored its own IME-related state. This approach
made ownership-handling fragmented and was therefore error-prone.

With this PR:
- IME event ownership is centralized, ensuring that at most a single
widget owns IME events per frame.
- [`PlatformOutput`]'s `ime` field can be set to `None` for at least one
frame when IME composition is interrupted, allowing the IME to be
properly dismissed.

## Details

Two new public methods are introduced on [`Memory`]:

- `fn owns_ime_events(&self, id: Id) -> bool`: check IME event ownership
for the current frame for the widget with the given `id`.
- `fn interrupt_ime(&mut self)`: interrupt the current IME composition,
if any.

Since the newly added methods on [`Memory`] are public, other widgets
can also participate in IME handling without risking ownership conflicts
of IME events.

I also added an internal (`pub(crate)`) field on [`TextEditState`],
called `cursor_purpose`, to distinguish the role of the [`TextEdit`]
cursor.

Additionally, `egui::ImeEvent::Enabled` and `egui::ImeEvent::Disabled`
have been removed, as they are no longer used anywhere.

## Demonstrations

### Windows: The Korean IME text duplication bug fixed in #4137 does not
reappear.

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Correct (no regression)</td>
<td>Correct</td>
</tr>
<tr>
<th>Screencast</th>
<td>


![win-kor-after](https://github.com/user-attachments/assets/1b080c8f-2031-406f-8781-aacafd5c879a)
</td>
<td>


![win-kor-before](https://github.com/user-attachments/assets/20258841-72fe-4652-b9a9-9b40e338ccf2)
</td>
</tr>
</tbody>
</table>

### Windows: Chinese and Japanese IMEs now behave more consistently with
the Korean IME in similar scenarios.

This change does not matter much, as composition is rarely interrupted
mid-process with these IMEs in typical usage.

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Composition can be interrupted by clicking (like Korean IMEs)</td>
<td>Composition can not interrupted by clicking</td>
</tr>
<tr>
<th>Screencast (Builtin Chinese IME)</th>
<td>


![win-cmn-after](https://github.com/user-attachments/assets/2c76b0a9-da6d-48e1-84e0-47d9631f1196)
</td>
<td>


![win-cmn-before](https://github.com/user-attachments/assets/ea125fb8-c325-48d5-abaf-17d495b8f075)
</td>
</tr>
<tr>
<th>Screencast (Builtin Japanese IME)</th>
<td>


![win-jpn-after](https://github.com/user-attachments/assets/c69e5f48-65b1-4c0f-af4a-522d2f47b75d)
</td>
<td>


![win-jpn-before](https://github.com/user-attachments/assets/a0f1fdad-4f6c-40c2-af57-029f42acf6d5)
</td>
</tr>
</tbody>
</table>

### macOS: was buggy, still buggy

Likely due to this upstream bug in `winit`:
https://github.com/rust-windowing/winit/issues/4432
Once `winit` is updated to a version that includes the fix, the behavior
should become correct with this PR.

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Buggy as before</td>
<td>Buggy: Characters are duplicated</td>
</tr>
<tr>
<th>Screencast</th>
<td>


![mac-kor-after](https://github.com/user-attachments/assets/c2bd90e8-e473-49c8-9537-c970c92889bf)
</td>
<td>


![mac-kor-before](https://github.com/user-attachments/assets/63b6cd8a-8903-4743-98bf-ee15296354ba)
</td>
</tr>
</tbody>
</table>

### Wayland + iBus: Korean IME duplication bug fixed

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Correct</td>
<td>Buggy: Characters are duplicated</td>
</tr>
<tr>
<th>Screencast</th>
<td>


![wayland-kor-after-2](https://github.com/user-attachments/assets/b154add5-a1ce-4e3a-b243-e72480820c1b)
</td>
<td>


![wayland-kor-before-2](https://github.com/user-attachments/assets/43b28374-f273-4b6f-9845-3efd96ec9a37)
</td>
</tr>
</tbody>
</table>

### Wayland + iBus: #7485 is fixed

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Correct</td>
<td>Buggy: Only a single ASCII character can be typed after
<code>TextEdit</code> is focused</td>
</tr>
<tr>
<th>Screencast</th>
<td>


![wayland-7485-after](https://github.com/user-attachments/assets/ec33a54d-1d4e-40f9-8c82-202104bd2d85)
</td>
<td>


![wayland-7485-before](https://github.com/user-attachments/assets/20d2d395-03fd-4966-a376-87249a41aab3)
</td>
</tr>
</tbody>
</table>

### Wayland + iBus: selection is also not broken

This PR does not reintroduce the selection bug fixed in #7973.

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Behavior</th>
<td>Correct</td>
</tr>
<tr>
<th>Screencast</th>
<td>


![wayland-focus-after](https://github.com/user-attachments/assets/daa29197-f7f7-4a7b-b454-c28ee9afa9c1)
</td>
</tr>
</tbody>
</table>

### X11 + Fcitx5: IME composition can be interrupted

But due to #7975, the experience is still subpar. (Uncommitted text is
lost after interruption.)

<table>
<thead>
<tr>
<th></th>
<th>With this PR</th>
<th>Without this PR</th>
</tr>
</thead>
<tbody>
<tr>
<th>Screencast</th>
<td>


![x11-after](https://github.com/user-attachments/assets/e626d9ed-89a2-4825-9cde-3a67723bcb82)
</td>
<td>


![x11-before](https://github.com/user-attachments/assets/da93b351-9488-4da9-aa56-b64190e84ec3)
</td>
</tr>
</tbody>
</table>


[`Memory`]: https://docs.rs/egui/latest/egui/struct.Memory.html
[`TextEdit`]:
https://docs.rs/egui/latest/egui/widgets/text_edit/struct.TextEdit.html
[`PlatformOutput`]:
https://docs.rs/egui/latest/egui/struct.PlatformOutput.html
[`TextEditState`]:
https://docs.rs/egui/latest/egui/widgets/text_edit/struct.TextEditState.html
2026-04-06 10:24:50 +02:00
..