1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-02 06:40:06 -04:00

Delegate handling of IME interruptions to integrations to fix virtual keyboard flickering on web (#8078)

* Closes N/A
* Partially replaces #7983
* Related: #8045
* [x] I have followed the instructions in the PR template

## Details

In #7983, I modified `Memory::request_focus` to interrupt any ongoing
IME composition. This fixed a bug where clicking inside an already
focused `TextEdit` failed to cancel the active composition, resulting in
duplicated text:

https://github.com/emilk/egui/pull/8045#issuecomment-4193310616

To avoid introducing API changes in that PR, I ensured the IME state was
reset by forcing `PlatformOutput::ime` to `None` for at least one frame.
While this works well on desktop platforms, it causes virtual keyboard
flickering on the web:

https://github.com/emilk/egui/pull/8045#issuecomment-4193035008

In this PR, I delegate the responsibility for handling IME composition
interruptions to integrations, allowing each integration to decide how
to interrupt compositions in a flexible manner.

### The new field `should_interrupt_composition` on `IMEOutput`.

Instead of introducing a new `OutputCommand` variant, this PR adds a new
field `should_interrupt_composition` to `IMEOutput`.

Interrupting an active composition is only meaningful when IME remains
allowed. If IME should be disabled altogether, `PlatformOutput::ime` can
simply be set to `None`.
Given this, IMO, it is more appropriate to attach the interrupt signal
to `IMEOutput` (i.e., the type of `PlatformOutput::ime`).
This commit is contained in:
Umaĵo
2026-04-08 16:04:15 +08:00
committed by GitHub
parent b117a1ac19
commit 86a7f47738
6 changed files with 49 additions and 46 deletions

View File

@@ -1049,7 +1049,8 @@ impl State {
self.set_cursor_icon(window, cursor_icon);
let allow_ime = ime.is_some();
if self.allow_ime != allow_ime {
let is_toggling_ime = self.allow_ime != allow_ime;
if is_toggling_ime {
self.allow_ime = allow_ime;
#[cfg(target_os = "windows")]
if !self.allow_ime {
@@ -1066,6 +1067,14 @@ impl State {
}
if let Some(ime) = ime {
if !is_toggling_ime && ime.should_interrupt_composition {
// TODO(umajho): use a more proper way to interrupt composition
// if `winit` provides one in the future.
window.set_ime_allowed(false);
window.set_ime_allowed(true);
}
let pixels_per_point = pixels_per_point(&self.egui_ctx, window);
let ime_rect_px = pixels_per_point * ime.rect;
if self.ime_rect_px != Some(ime_rect_px)