Skip to content

Add IME language selection to InputOptions for CJK support#7898

Closed
rustbasic wants to merge 16 commits intoemilk:mainfrom
rustbasic:patch166
Closed

Add IME language selection to InputOptions for CJK support#7898
rustbasic wants to merge 16 commits intoemilk:mainfrom
rustbasic:patch166

Conversation

@rustbasic
Copy link
Copy Markdown
Contributor

Add IME language selection to InputOptions for CJK support

Overview
This PR adds a new configuration option to select specific IME (Input Method Editor) processing modes, particularly for CJK (Chinese, Japanese, Korean) languages. This allows for more specialized handling of character composition depending on the selected language.

Changes

  • Introduced ImeLanguage enum (None, Korean, Japanese, Chinese) with serde support.
  • Added ime_language field to InputOptions struct.
  • Updated InputOptions::ui to include a ComboBox for easy language selection in the settings panel.

Why this is needed
Proper CJK support often requires different composition logic depending on the language. By allowing users to explicitly select their IME mode, we can provide a more robust input experience for international users.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 10, 2026

Preview available at https://egui-pr-preview.github.io/pr/7898-patch166
Note that it might take a couple seconds for the update to show up after the preview_build workflow has completed.

View snapshot changes at kitdiff

@umajho
Copy link
Copy Markdown
Contributor

umajho commented Feb 10, 2026

Backspacing in a TextEdit will stop from working after an IME has been enabled inside that TextEdit.
Even if I switched back to English, this bug still persists.

Tested on macOS Safari and Chrome. The screenshot below is in Chrome.

repro


By the way, since I'm not familiar with Korean at all, I'm curious whether this solution is universal.
As an IME user myself (Chinese Pinyin (Shuangpin)), I don't remember I have ever seen an application that requires the user to configure the IME language explicitly. Though, maybe this is common among Korean IME users…?

On macOS, both Japanese IME and Korean IME already work with the current code. (Japanese IME won't emit an extra Enter while confirming, Korean IME don't need Enter twice. details here)
So maybe there is a way to make the behavior correct on other platforms without the need to ask users to select their IME's language.

Also, since browsers (Safari, Chrome and Firefox (Zen)) on macOS can also handle both (Japanese and Korean) cases correctly, I wonder if this is also true for Windows and Linux. (I don't have access to Windows devices for now, and I have no experience configuring Japanese/Korean IMEs on any Linux DE…)

@rustbasic
Copy link
Copy Markdown
Contributor Author

Thanks @umajho

I also noticed the issue a bit late and am currently in the process of identifying the cause and implementing a fix.

The reason for handling Korean, Japanese, and Chinese separately is that the current implementation is structured such that changes made for Chinese tend to break the Korean logic. Additionally, there is an issue on Linux where IME::Enable is not being triggered, which might lead to divergent handling methods in the future.

To be more precise, it's difficult to find someone who can test all languages across every platform. While it would be ideal for the behavior to be consistent across all systems and languages, from my perspective, the sheer diversity of Chinese input methods and the current state of Linux make that quite challenging.

@rustbasic
Copy link
Copy Markdown
Contributor Author

@umajho

Would you like to test this?
I have even solved problems that couldn't be solved for a year.

@umajho
Copy link
Copy Markdown
Contributor

umajho commented Feb 11, 2026

I can confirm that the backspacing issues is gone.

I have also tested the native build. It seems this doesn't break the already-correct behavior on mac for the builtin Shuangpin (Pinyin), Japanese and 2-Set Korean IMEs, no matter which ime_language is used.

(Although, I still think requiring specifying the IME language a little unintuitive. IMO an ideal solution is to fix the inconsistencies on winit. I speculate that the root issue is that winit doesn't consume the confirming keys1 for Japanese IMEs (and maybe Chinese IMEs as well) on Windows, but unfortunately I don't have the environment to test this.)

Footnotes

  1. The last section of the opening of this pr states that macOS does this, which explains why macOS doesn't have this problem.

@rustbasic
Copy link
Copy Markdown
Contributor Author

@umajho

Users don't need to select a specific language if they have no issues with their IME when 'None' or 'Korean' is selected. This also applies to Japanese or Chinese users; if 'None' works correctly for them, no selection is necessary.

Although not included in this current PR, there is a difference in preference for the IME EventFilter: Chinese users generally want to include 'Enter' in the filter, whereas Korean users prefer it to be excluded.

@umajho
Copy link
Copy Markdown
Contributor

umajho commented Feb 11, 2026

@umajho

Users don't need to select a specific language if they have no issues with their IME when 'None' or 'Korean' is selected. This also applies to Japanese or Chinese users; if 'None' works correctly for them, no selection is necessary.

Although not included in this current PR, there is a difference in preference for the IME EventFilter: Chinese users generally want to include 'Enter' in the filter, whereas Korean users prefer it to be excluded.

I apologize, but I am not very convinced by this approach, because:

  1. Lots of, if not most, apps support IMEs correctly without knowing which kind of IME is used, this should also be possible for egui.
  2. I doubt most developers will know/care that there is an IME language selection thing in egui and bother integrating it into their apps. If an app doesn't make the selector available, users are out of luck.
  3. And even if an app includes the selector, users still need to discover it, which is not ideal for UX.
  4. There are users who use multiple IMEs all the time. To them, switching IME language settings is cumbersome.
  5. As I stated, I think the root issue is likely in winit.

Because of the second and the third point, I think this pr can be considered a temporary workaround for language exclusive (e.g. Japanese exclusive) apps, but it should not be considered as a long term solution. (I see that you didn't link any issue to be closed by this pr, so maybe you and me are on the same page here…?)

Since people do need a workaround, I don't object to this PR being merged.

More on the fifth point

The following behavior:

“while confirming, the key press event of the confirming key is emitted along with the IME commit event for Japanese/Chinese IME.”

is likely a bug of winit's IME handling logic on Windows.

The correct behavior should be:

winit should not emit key press events for confirming keys for Japanese/Chinese IMEs, while it should emit press of Enter for Korean IMEs.”

Which is correctly implemented by winit on macOS and Linux with ibus (I have not tested fcitx).
It is also correctly implemented by eframe's custom integration for web.

Therefore, in my opinion, the ideal way to fix this IME bug in egui is to fix the bug in the winit crate, so that confirming keys for Japanese/Chinese IMEs will always be discarded inside winit on every platform, just like how it is handled on macOS.


Update 1:

I find this line of ignoring commits of newline characters interesting. I'd like to investigate it later.

Update 2:

I just realized that the system the author of #7877 uses is not Linux (I was misled by the look of the top bar). I have tested Linux + KDE + ibus myself, it turns out it also already works with the current code across different IMEs without the need to know the kind of the IME being used, just like macOS.

And I also found out that the function remove_ime_incompatible_events doesn't benefit macOS and Linux (at least for ibus) at all.
In fact, running this function there even leads to a bug: When using a Korean IME in other apps, arrow keys can move the cursor even if the composition has not been done, but with the so-called incompatible events being removed, the first press of arrow keys would not move the cursor.

I suspect that the code I linked in Update 1 filtered out the enter event for Korean IMEs on Windows. I will update my test on this when I have access to Windows. (maybe in 2~3 weeks)

@umajho

This comment was marked as duplicate.

@rustbasic
Copy link
Copy Markdown
Contributor Author

I’ve finished.

I simplified it as much as possible and tested it on both Windows and Web.

There are some bugs when typing in Korean on mobile; it seems like mobile Korean input requires handling a much more complex process directly.
Since I haven't completed that part yet, I didn't include it in this Pull Request.

@rustbasic rustbasic closed this Feb 16, 2026
@umajho umajho mentioned this pull request Mar 11, 2026
1 task
emilk pushed a commit that referenced this pull request Mar 24, 2026
<!--
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!
-->

* Closes #7809
* Closes #7876
* Closes #7908
* Supersedes #7877
* Supersedes #7898
* The author of the PR above replaced it with #7914, which additionally
fixes another IME issue. I believe that fix deserves a separate PR.
* Reverts #4794  
* [x] I have followed the instructions in the PR template

This approach is better than #7898 (#7914) because it correctly handles
all three major IME types (Chinese, Japanese, and Korean) without
requiring a predefined “IME mode”.

## Environments I haved tested this PR in

<details><summary>macOS 15.7.3 (AArch64, Host of other virtual
machines)</summary>

Run command: `cargo run -p egui_demo_app --release`

Tested IMEs:

- builtin Chinese IME (Shuangpin - Simplified)
- builtin Japanese IME (Romaji)
- builtin Korean IME (2-Set)
</details>

<details><summary>Windows 11 25H2 (AArch64, Virtual Machine)</summary>

Build command: `cargo build --release -p egui_demo_app
--target=x86_64-pc-windows-gnu --features=glow --no-default-features`

(I cannot use `wgpu` due to [this
bug](#4381), which prevents
debugging inside the VM. Anyways, the rendering backend should be
irrelevant here.)

Tested IMEs:

- builtin Chinese IME (Shuangpin)
- Sogou IME (Chinese Shuangpin)
- WeType IME (Chinese Shuangpin)
- builtin Japanese IME (Hiragana)
- builtin Korean IME (2 Beolsik)
</details>

<details><summary>Linux [Wayland + IBus] (AArch64, Virtual
Machine)</summary>

Fedora KDE Plasma Desktop 43 [Wayland + IBus 1.5.33-rc2]

(Not working at the moment because of [another
issue](#7485) that will be fixed by
#7983. It is [a complicated
story](#7973 (comment)).
)

> [!NOTE]
>
> IBus is partially broken in this system. The Input Method Selector
refuses to select IBus. As a workaround, I have to open System Settings
-> Virtual Keyboard and select “IBus Wayland” to start an IBus instance
that works in egui.
>
> The funny thing is: the Chinese Intelligent Pinyin IME is broken in
native Apps like System Settings and KWrite, but works correctly in
egui!
>
> <details><summary>Screencast: What</summary>
>
> ![2026-03-13 3 10
11 AM](https://github.com/user-attachments/assets/4001cf12-8089-46f5-9cf4-e41d8f77ee24)
> </details>

Build command: `cross build --release -p egui_demo_app
--target=aarch64-unknown-linux-gnu --features=wayland,wgpu
--no-default-features`

(The Linux toolchain on my mac is somehow broken, so I used `cross`
instead.)

Tested IMEs:

- Chinese Intelligent Pinyin IME (Shuangpin)
- Japanese Anthy IME (Hiragana)
- Korean Hangul IME
</details>

<details><summary>Linux [X11 + Fcitx5] (AArch64, Virtual
Machine)</summary>

Debian 13 [Cinnamon 6.4.10 + X11 + Fcitx5 5.1.2]

Build command: `cross build --release -p egui_demo_app
--target=aarch64-unknown-linux-gnu --features=x11,wgpu
--no-default-features`

Tested IMEs:

- Chinese Shuangpin IME
- Chinese Rime IME with `luna-pinyin`
- Japanese Mozc IME (Hiragana)
- Korean Hangul IME

Unlike macOS and Linux + Wayland, key-release events for keys processed
by the IME are still forwarded to `egui`. These appear to be harmless in
practice.
Unlike on Windows, however, they cannot be filtered reliably because
there are no corresponding key-press events marked as “processed by
IME”.

</details>

---

There are too many possible combinations to test (Operating Systems ×
[Desktop
Environment](https://en.wikipedia.org/wiki/Desktop_environment)s ×
[Windowing System](https://en.wikipedia.org/wiki/Windowing_system)s ×
[IMF](https://wiki.archlinux.org/title/Input_method#Input_method_framework)s
× [IME](https://en.wikipedia.org/wiki/Input_method)s × …), and I only
have access to a limited subset. For example, Google Japanese Input
refused to install on my Windows VM, and some paid Japanese IMEs are not
accessible to me. Therefore, I would appreciate feedback from people
other than me using all kinds of environments.

## Details

There are two possible approaches to removing keyboard events that have
already been processed by an IME:

* Approach 1: Filter out events inside `egui` that appear to have been
received during IME composition.
* Approach 2: Filter out such events in the platform backend
(terminology [borrowed from
imgui](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md#using-standard-backends),
e.g. the `egui-winit` crate or the code under `web/` in the `eframe`
crate.).

Both approaches already exist in `egui`:

* #4794 uses the first approach, filtering these events in the
`TextEdit`-related code.
* `eframe` uses the second approach in its web integration. See:
<https://github.com/emilk/egui/blob/14afefa2521d1baaf4fd02105eec2d3727a7ac36/crates/eframe/src/web/events.rs#L173-L176>

Compared to the first approach, the second has a clear advantage: when
events are passed from the platform backends into `egui`, they are
simplified and lose information. In contrast, events in the platform
backends are the original events, which allows them to be handled more
flexibly. This is also why #7898 (#7914), which attempts to address the
issue from within the `egui` crate, struggles to make all IMEs work
correctly at the same time and requires manually selecting an “IME
mode”: the events received by `egui` have already been reduced and
therefore lack necessary information.

A more appropriate solution is to consistently follow the second
approach, explicitly requiring platform backends not to forward events
that have already been processed by the IME to `egui`. This is the
method used in this PR. Specifically, this PR works within the
`egui-winit` crate, where the original `KeyboardInput` events can be
accessed. At least for key press events, these can be used directly to
determine whether the event has already been processed by the IME on
Windows (by checking whether `logical_key` equals
`winit::keyboard::NamedKey::Process`). This makes it straightforward to
ensure that all IMEs work correctly at the same time.

This PR also reverts #4794, which took the first approach. It filters
out some events that merely look like they were received during IME
composition but actually are not. It also messes up the order of those
events along the way.
As a result, it caused several IME-related issues. One of the sections
in the Demonstrations below will illustrate these problems.

## Demonstrations

<details><summary>Changes not included in this PR for displaying Unicode
characters in demonstrations</summary>

Download `unifont-17.0.03.otf` from
<https://unifoundry.com/pub/unifont/unifont-17.0.03/font-builds/>, and
place it at `crates/egui_demo_app/src/unifont-17.0.03.otf`.

In `crates/egui_demo_app/src/wrap_app.rs`, add these lines at the
beginning of `impl WrapApp`'s `pub fn new`:
```rust
        {
            const MAIN_FONT: &'static [u8] = include_bytes!("./unifont-17.0.03.otf");

            let mut fonts = egui::FontDefinitions::default();

            fonts.font_data.insert(
                "main-font".to_owned(),
                std::sync::Arc::new(egui::FontData::from_static(MAIN_FONT)),
            );

            let proportional = fonts
                .families
                .entry(egui::FontFamily::Proportional)
                .or_default();
            proportional.insert(0, "main-font".to_owned());

            cc.egui_ctx.set_fonts(fonts);
        }
```

(I took this from somewhere, but I forgot where it is. Sorry…)
</details>

[GNU Unifont](https://unifoundry.com/unifont/index.html) is licensed
under [OFL-1.1](https://unifoundry.com/OFL-1.1.txt).

### This PR Fixes: Focus on a single-line `TextEdit` is lost after
completing candidate selection with Japanese IME on Windows (#7809)

<details><summary>Screencast: ✅ Japanese IME now behaves correctly while
Korean IME behaves as before</summary>


![7809](https://github.com/user-attachments/assets/6e92f6e6-fed4-46f4-96e1-e0e12dadc360)
</details>

### This PR Fixes: Committing Japanese IME text with <kbd>Enter</kbd>
inserts an unintended newline in multiline `TextEdit` on Windows (#7876)

<details><summary>Screencast: ✅ Japanese IME now behaves correctly while
Korean IME behaves as before</summary>


![7876](https://github.com/user-attachments/assets/03d2cb22-fd0c-45fe-9132-e59fa39bfcf3)
</details>

### This PR Fixes: Backspacing deletes characters during composition in
certain Chinese IMEs (e.g., Sogou) on Windows (#7908)

<details><summary>Screencast: ✅ Sogou IME now behaves
correctly</summary>


![7908](https://github.com/user-attachments/assets/2c63de28-26f0-4387-9c50-dceabfdbe99d)
</details>

### This PR Obsoletes #4794, because `egui` receives only IME events
during composition from now on

On Windows, “incompatible” events are filtered in `egui-winit`, aligning
the behavior with other systems.

<details><summary>Screencasts</summary>

Some Chinese IMEs on Windows:
![2026-03-13 12 25
37 AM](https://github.com/user-attachments/assets/064fd1c7-244b-4053-bd24-c65d768cd943)

The default Japanese IMEs on Windows:
![2026-03-13 12 28
33 AM](https://github.com/user-attachments/assets/f799b0b5-350b-4b05-a769-bcef16255bdb)
</details>

The 2-set Korean IMEs handle arrow keys differently. It will be
discussed in the next section.

### This PR Reverts #4794, because it introduced several bugs

Some of its bugs have already been worked around in the past, but those
workarounds might also be problematic. For example, #4912 is a
workaround for a bug (#4908) introduced by #4794, and that workaround is
in fact the root cause of the macOS backspacing bug I have worked around
with #7810. (The reversion of #4912 is out of the scope of this PR, I
will do that in #7983.)

#### It Caused: Arrow keys are incorrectly blocked during typical Korean
IME composition

When composing Korean text using 2-Set IMEs, users should still be able
to move the cursor with arrow keys regardless if the composition is
committed.

##### Correct behavior

<details><summary>Screencasts</summary>

macOS TextEdit:
![2026-03-12 8 04
15 PM](https://github.com/user-attachments/assets/24383568-f51c-4a74-9251-adfd942cad8f)

Windows Notepad:
![2026-03-12 8 05
08 PM](https://github.com/user-attachments/assets/5a29a5b5-69b8-407b-b1a4-84fdb8f8847d)

With #4794 reverted, `egui` also behaves correctly (tested on Linux +
Wayland, macOS, and Windows):
![2026-03-12 8 03
51 PM](https://github.com/user-attachments/assets/fcb7f25c-1329-4eb1-82f2-1cea33dcca73)
</details>

##### Incorrect behavior caused by #4794

`remove_ime_incompatible_events` removed arrow-key events in such cases.
As a result, the first arrow key press only commits the composition, and
users need to press the arrow key again to move the cursor:

<details><summary>Screencast</summary>

![2026-03-12 8 06
40 PM](https://github.com/user-attachments/assets/6760c6bd-b6ce-44ea-b192-6bd165191c01)
</details>

This is essentially the same issue described here:
#7877 (comment)

#### It Caused: Backspacing leaves the last character in Korean IME
pre-edit text not removed on macOS

<details><summary>Screencasts</summary>

Before this PR:
![2026-03-17 10 48
12 PM](https://github.com/user-attachments/assets/88021e7e-caf6-4aa9-8f73-ecffc63cda06)

After this PR:
![2026-03-17 10 47
23 PM](https://github.com/user-attachments/assets/379cd0db-24e0-4c0e-a5b4-edb37d3e1df7)
</details>

### Korean IMEs also use <kbd>Enter</kbd> to confirm Hanja selections,
and will not work properly in the Korean “IME mode” proposed by #7898
(#7914)

<details><summary>Screencast: Korean IME using <kbd>Enter</kbd> and
<kbd>Space</kbd> for confirmation (IBus Korean Hangul IME)</summary>

The screencast below demonstrates that some Korean IMEs handle Hanja
selection in a way similar to Japanese IMEs: the
<kbd>Up</kbd>/<kbd>Down</kbd> arrow keys are used to navigate
candidates, and <kbd>Enter</kbd> confirms the selected candidate.

![2026-03-13 6 39
17 AM](https://github.com/user-attachments/assets/0b054cc6-2251-4689-95a4-d69a9be36371)
</details>

<details><summary>Screencasts: Another example</summary>

Using the built-in Korean IME on Windows, I type two lines: the first
line in Hangul, and the second line as the same word converted to Hanja.

Correct behavior in Notepad (reference):

![7914-ref](https://github.com/user-attachments/assets/1e9f9315-eb71-497a-b6e2-2b11eb6bbf7f)

Behavior after applying this PR, which matches the Notepad behavior:

![7914-7967](https://github.com/user-attachments/assets/26f12b9f-9354-45b8-b2a8-ede28c34c5b1)

Behavior after applying #7914 with the “IME mode” set to Korean (which
is also the behavior before this PR being applied):

![7914-7914](https://github.com/user-attachments/assets/0f82a019-c491-4b64-a92a-d88d62dfbd84)
On the second line, each time a Hanja character is confirmed, an
unintended newline is inserted. This mirrors the Japanese IME issues
that are supposed to be fixed by setting the “IME mode” to Japanese.
(These Japanese IME issues are fixed in this PR as mentioned before.)

</details>
Masterchef365 pushed a commit to Masterchef365/egui that referenced this pull request Apr 3, 2026
<!--
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!
-->

* Closes emilk#7809
* Closes emilk#7876
* Closes emilk#7908
* Supersedes emilk#7877
* Supersedes emilk#7898
* The author of the PR above replaced it with emilk#7914, which additionally
fixes another IME issue. I believe that fix deserves a separate PR.
* Reverts emilk#4794  
* [x] I have followed the instructions in the PR template

This approach is better than emilk#7898 (emilk#7914) because it correctly handles
all three major IME types (Chinese, Japanese, and Korean) without
requiring a predefined “IME mode”.

## Environments I haved tested this PR in

<details><summary>macOS 15.7.3 (AArch64, Host of other virtual
machines)</summary>

Run command: `cargo run -p egui_demo_app --release`

Tested IMEs:

- builtin Chinese IME (Shuangpin - Simplified)
- builtin Japanese IME (Romaji)
- builtin Korean IME (2-Set)
</details>

<details><summary>Windows 11 25H2 (AArch64, Virtual Machine)</summary>

Build command: `cargo build --release -p egui_demo_app
--target=x86_64-pc-windows-gnu --features=glow --no-default-features`

(I cannot use `wgpu` due to [this
bug](emilk#4381), which prevents
debugging inside the VM. Anyways, the rendering backend should be
irrelevant here.)

Tested IMEs:

- builtin Chinese IME (Shuangpin)
- Sogou IME (Chinese Shuangpin)
- WeType IME (Chinese Shuangpin)
- builtin Japanese IME (Hiragana)
- builtin Korean IME (2 Beolsik)
</details>

<details><summary>Linux [Wayland + IBus] (AArch64, Virtual
Machine)</summary>

Fedora KDE Plasma Desktop 43 [Wayland + IBus 1.5.33-rc2]

(Not working at the moment because of [another
issue](emilk#7485) that will be fixed by
emilk#7983. It is [a complicated
story](emilk#7973 (comment)).
)

> [!NOTE]
>
> IBus is partially broken in this system. The Input Method Selector
refuses to select IBus. As a workaround, I have to open System Settings
-> Virtual Keyboard and select “IBus Wayland” to start an IBus instance
that works in egui.
>
> The funny thing is: the Chinese Intelligent Pinyin IME is broken in
native Apps like System Settings and KWrite, but works correctly in
egui!
>
> <details><summary>Screencast: What</summary>
>
> ![2026-03-13 3 10
11 AM](https://github.com/user-attachments/assets/4001cf12-8089-46f5-9cf4-e41d8f77ee24)
> </details>

Build command: `cross build --release -p egui_demo_app
--target=aarch64-unknown-linux-gnu --features=wayland,wgpu
--no-default-features`

(The Linux toolchain on my mac is somehow broken, so I used `cross`
instead.)

Tested IMEs:

- Chinese Intelligent Pinyin IME (Shuangpin)
- Japanese Anthy IME (Hiragana)
- Korean Hangul IME
</details>

<details><summary>Linux [X11 + Fcitx5] (AArch64, Virtual
Machine)</summary>

Debian 13 [Cinnamon 6.4.10 + X11 + Fcitx5 5.1.2]

Build command: `cross build --release -p egui_demo_app
--target=aarch64-unknown-linux-gnu --features=x11,wgpu
--no-default-features`

Tested IMEs:

- Chinese Shuangpin IME
- Chinese Rime IME with `luna-pinyin`
- Japanese Mozc IME (Hiragana)
- Korean Hangul IME

Unlike macOS and Linux + Wayland, key-release events for keys processed
by the IME are still forwarded to `egui`. These appear to be harmless in
practice.
Unlike on Windows, however, they cannot be filtered reliably because
there are no corresponding key-press events marked as “processed by
IME”.

</details>

---

There are too many possible combinations to test (Operating Systems ×
[Desktop
Environment](https://en.wikipedia.org/wiki/Desktop_environment)s ×
[Windowing System](https://en.wikipedia.org/wiki/Windowing_system)s ×
[IMF](https://wiki.archlinux.org/title/Input_method#Input_method_framework)s
× [IME](https://en.wikipedia.org/wiki/Input_method)s × …), and I only
have access to a limited subset. For example, Google Japanese Input
refused to install on my Windows VM, and some paid Japanese IMEs are not
accessible to me. Therefore, I would appreciate feedback from people
other than me using all kinds of environments.

## Details

There are two possible approaches to removing keyboard events that have
already been processed by an IME:

* Approach 1: Filter out events inside `egui` that appear to have been
received during IME composition.
* Approach 2: Filter out such events in the platform backend
(terminology [borrowed from
imgui](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md#using-standard-backends),
e.g. the `egui-winit` crate or the code under `web/` in the `eframe`
crate.).

Both approaches already exist in `egui`:

* emilk#4794 uses the first approach, filtering these events in the
`TextEdit`-related code.
* `eframe` uses the second approach in its web integration. See:
<https://github.com/emilk/egui/blob/14afefa2521d1baaf4fd02105eec2d3727a7ac36/crates/eframe/src/web/events.rs#L173-L176>

Compared to the first approach, the second has a clear advantage: when
events are passed from the platform backends into `egui`, they are
simplified and lose information. In contrast, events in the platform
backends are the original events, which allows them to be handled more
flexibly. This is also why emilk#7898 (emilk#7914), which attempts to address the
issue from within the `egui` crate, struggles to make all IMEs work
correctly at the same time and requires manually selecting an “IME
mode”: the events received by `egui` have already been reduced and
therefore lack necessary information.

A more appropriate solution is to consistently follow the second
approach, explicitly requiring platform backends not to forward events
that have already been processed by the IME to `egui`. This is the
method used in this PR. Specifically, this PR works within the
`egui-winit` crate, where the original `KeyboardInput` events can be
accessed. At least for key press events, these can be used directly to
determine whether the event has already been processed by the IME on
Windows (by checking whether `logical_key` equals
`winit::keyboard::NamedKey::Process`). This makes it straightforward to
ensure that all IMEs work correctly at the same time.

This PR also reverts emilk#4794, which took the first approach. It filters
out some events that merely look like they were received during IME
composition but actually are not. It also messes up the order of those
events along the way.
As a result, it caused several IME-related issues. One of the sections
in the Demonstrations below will illustrate these problems.

## Demonstrations

<details><summary>Changes not included in this PR for displaying Unicode
characters in demonstrations</summary>

Download `unifont-17.0.03.otf` from
<https://unifoundry.com/pub/unifont/unifont-17.0.03/font-builds/>, and
place it at `crates/egui_demo_app/src/unifont-17.0.03.otf`.

In `crates/egui_demo_app/src/wrap_app.rs`, add these lines at the
beginning of `impl WrapApp`'s `pub fn new`:
```rust
        {
            const MAIN_FONT: &'static [u8] = include_bytes!("./unifont-17.0.03.otf");

            let mut fonts = egui::FontDefinitions::default();

            fonts.font_data.insert(
                "main-font".to_owned(),
                std::sync::Arc::new(egui::FontData::from_static(MAIN_FONT)),
            );

            let proportional = fonts
                .families
                .entry(egui::FontFamily::Proportional)
                .or_default();
            proportional.insert(0, "main-font".to_owned());

            cc.egui_ctx.set_fonts(fonts);
        }
```

(I took this from somewhere, but I forgot where it is. Sorry…)
</details>

[GNU Unifont](https://unifoundry.com/unifont/index.html) is licensed
under [OFL-1.1](https://unifoundry.com/OFL-1.1.txt).

### This PR Fixes: Focus on a single-line `TextEdit` is lost after
completing candidate selection with Japanese IME on Windows (emilk#7809)

<details><summary>Screencast: ✅ Japanese IME now behaves correctly while
Korean IME behaves as before</summary>


![7809](https://github.com/user-attachments/assets/6e92f6e6-fed4-46f4-96e1-e0e12dadc360)
</details>

### This PR Fixes: Committing Japanese IME text with <kbd>Enter</kbd>
inserts an unintended newline in multiline `TextEdit` on Windows (emilk#7876)

<details><summary>Screencast: ✅ Japanese IME now behaves correctly while
Korean IME behaves as before</summary>


![7876](https://github.com/user-attachments/assets/03d2cb22-fd0c-45fe-9132-e59fa39bfcf3)
</details>

### This PR Fixes: Backspacing deletes characters during composition in
certain Chinese IMEs (e.g., Sogou) on Windows (emilk#7908)

<details><summary>Screencast: ✅ Sogou IME now behaves
correctly</summary>


![7908](https://github.com/user-attachments/assets/2c63de28-26f0-4387-9c50-dceabfdbe99d)
</details>

### This PR Obsoletes emilk#4794, because `egui` receives only IME events
during composition from now on

On Windows, “incompatible” events are filtered in `egui-winit`, aligning
the behavior with other systems.

<details><summary>Screencasts</summary>

Some Chinese IMEs on Windows:
![2026-03-13 12 25
37 AM](https://github.com/user-attachments/assets/064fd1c7-244b-4053-bd24-c65d768cd943)

The default Japanese IMEs on Windows:
![2026-03-13 12 28
33 AM](https://github.com/user-attachments/assets/f799b0b5-350b-4b05-a769-bcef16255bdb)
</details>

The 2-set Korean IMEs handle arrow keys differently. It will be
discussed in the next section.

### This PR Reverts emilk#4794, because it introduced several bugs

Some of its bugs have already been worked around in the past, but those
workarounds might also be problematic. For example, emilk#4912 is a
workaround for a bug (emilk#4908) introduced by emilk#4794, and that workaround is
in fact the root cause of the macOS backspacing bug I have worked around
with emilk#7810. (The reversion of emilk#4912 is out of the scope of this PR, I
will do that in emilk#7983.)

#### It Caused: Arrow keys are incorrectly blocked during typical Korean
IME composition

When composing Korean text using 2-Set IMEs, users should still be able
to move the cursor with arrow keys regardless if the composition is
committed.

##### Correct behavior

<details><summary>Screencasts</summary>

macOS TextEdit:
![2026-03-12 8 04
15 PM](https://github.com/user-attachments/assets/24383568-f51c-4a74-9251-adfd942cad8f)

Windows Notepad:
![2026-03-12 8 05
08 PM](https://github.com/user-attachments/assets/5a29a5b5-69b8-407b-b1a4-84fdb8f8847d)

With emilk#4794 reverted, `egui` also behaves correctly (tested on Linux +
Wayland, macOS, and Windows):
![2026-03-12 8 03
51 PM](https://github.com/user-attachments/assets/fcb7f25c-1329-4eb1-82f2-1cea33dcca73)
</details>

##### Incorrect behavior caused by emilk#4794

`remove_ime_incompatible_events` removed arrow-key events in such cases.
As a result, the first arrow key press only commits the composition, and
users need to press the arrow key again to move the cursor:

<details><summary>Screencast</summary>

![2026-03-12 8 06
40 PM](https://github.com/user-attachments/assets/6760c6bd-b6ce-44ea-b192-6bd165191c01)
</details>

This is essentially the same issue described here:
emilk#7877 (comment)

#### It Caused: Backspacing leaves the last character in Korean IME
pre-edit text not removed on macOS

<details><summary>Screencasts</summary>

Before this PR:
![2026-03-17 10 48
12 PM](https://github.com/user-attachments/assets/88021e7e-caf6-4aa9-8f73-ecffc63cda06)

After this PR:
![2026-03-17 10 47
23 PM](https://github.com/user-attachments/assets/379cd0db-24e0-4c0e-a5b4-edb37d3e1df7)
</details>

### Korean IMEs also use <kbd>Enter</kbd> to confirm Hanja selections,
and will not work properly in the Korean “IME mode” proposed by emilk#7898
(emilk#7914)

<details><summary>Screencast: Korean IME using <kbd>Enter</kbd> and
<kbd>Space</kbd> for confirmation (IBus Korean Hangul IME)</summary>

The screencast below demonstrates that some Korean IMEs handle Hanja
selection in a way similar to Japanese IMEs: the
<kbd>Up</kbd>/<kbd>Down</kbd> arrow keys are used to navigate
candidates, and <kbd>Enter</kbd> confirms the selected candidate.

![2026-03-13 6 39
17 AM](https://github.com/user-attachments/assets/0b054cc6-2251-4689-95a4-d69a9be36371)
</details>

<details><summary>Screencasts: Another example</summary>

Using the built-in Korean IME on Windows, I type two lines: the first
line in Hangul, and the second line as the same word converted to Hanja.

Correct behavior in Notepad (reference):

![7914-ref](https://github.com/user-attachments/assets/1e9f9315-eb71-497a-b6e2-2b11eb6bbf7f)

Behavior after applying this PR, which matches the Notepad behavior:

![7914-7967](https://github.com/user-attachments/assets/26f12b9f-9354-45b8-b2a8-ede28c34c5b1)

Behavior after applying emilk#7914 with the “IME mode” set to Korean (which
is also the behavior before this PR being applied):

![7914-7914](https://github.com/user-attachments/assets/0f82a019-c491-4b64-a92a-d88d62dfbd84)
On the second line, each time a Hanja character is confirmed, an
unintended newline is inserted. This mirrors the Japanese IME issues
that are supposed to be fixed by setting the “IME mode” to Japanese.
(These Japanese IME issues are fixed in this PR as mentioned before.)

</details>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants