From 53736ab808a35f4d4d7bfb3c2d79a546685e784a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=9A=93?= Date: Sat, 30 Mar 2024 12:14:58 -0400 Subject: [PATCH] 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 --- crates/egui-winit/src/lib.rs | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 41db04952e5..3d8e9184fdc 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -99,6 +99,7 @@ pub struct State { accesskit: Option, allow_ime: bool, + ime_rect_px: Option, } impl State { @@ -139,6 +140,7 @@ impl State { accesskit: None, allow_ime: false, + ime_rect_px: None, }; slf.egui_input @@ -817,19 +819,26 @@ impl State { } if let Some(ime) = ime { - let rect = ime.rect; let pixels_per_point = pixels_per_point(&self.egui_ctx, window); - crate::profile_scope!("set_ime_cursor_area"); - window.set_ime_cursor_area( - winit::dpi::PhysicalPosition { - x: pixels_per_point * rect.min.x, - y: pixels_per_point * rect.min.y, - }, - winit::dpi::PhysicalSize { - width: pixels_per_point * rect.width(), - height: pixels_per_point * rect.height(), - }, - ); + let ime_rect_px = pixels_per_point * ime.rect; + if self.ime_rect_px != Some(ime_rect_px) + || self.egui_ctx.input(|i| !i.events.is_empty()) + { + self.ime_rect_px = Some(ime_rect_px); + crate::profile_scope!("set_ime_cursor_area"); + window.set_ime_cursor_area( + winit::dpi::PhysicalPosition { + 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")]