Fix continuous repaint on Wayland when TextEdit is focused or IME output is not None (#4269)

* Closes #4254

Changes egui-winit so that it calls `window.set_ime_cursor_area` when
the IME rect changes or the user interacts with the application instead
of calling it every time the app is rendered. This works around a winit
bug that causes the app to continuously repaint under certain
circumstances on Wayland.

Tested on Wayland and on X11 using the text edit in the egui_demo_app -
no changes in IME functionality as far as I can tell. Untested on
non-Linux platforms.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
刘皓 2024-03-30 12:14:58 -04:00 committed by GitHub
parent 3b147c066b
commit 33221bd4dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 21 additions and 12 deletions

View File

@ -99,6 +99,7 @@ pub struct State {
accesskit: Option<accesskit_winit::Adapter>, accesskit: Option<accesskit_winit::Adapter>,
allow_ime: bool, allow_ime: bool,
ime_rect_px: Option<egui::Rect>,
} }
impl State { impl State {
@ -139,6 +140,7 @@ impl State {
accesskit: None, accesskit: None,
allow_ime: false, allow_ime: false,
ime_rect_px: None,
}; };
slf.egui_input slf.egui_input
@ -817,19 +819,26 @@ impl State {
} }
if let Some(ime) = ime { if let Some(ime) = ime {
let rect = ime.rect;
let pixels_per_point = pixels_per_point(&self.egui_ctx, window); let pixels_per_point = pixels_per_point(&self.egui_ctx, window);
crate::profile_scope!("set_ime_cursor_area"); let ime_rect_px = pixels_per_point * ime.rect;
window.set_ime_cursor_area( if self.ime_rect_px != Some(ime_rect_px)
winit::dpi::PhysicalPosition { || self.egui_ctx.input(|i| !i.events.is_empty())
x: pixels_per_point * rect.min.x, {
y: pixels_per_point * rect.min.y, self.ime_rect_px = Some(ime_rect_px);
}, crate::profile_scope!("set_ime_cursor_area");
winit::dpi::PhysicalSize { window.set_ime_cursor_area(
width: pixels_per_point * rect.width(), winit::dpi::PhysicalPosition {
height: pixels_per_point * rect.height(), x: ime_rect_px.min.x,
}, y: ime_rect_px.min.y,
); },
winit::dpi::PhysicalSize {
width: ime_rect_px.width(),
height: ime_rect_px.height(),
},
);
}
} else {
self.ime_rect_px = None;
} }
#[cfg(feature = "accesskit")] #[cfg(feature = "accesskit")]