From e66da114c4b3faac3746ba2b7d23cc0f1ea82df2 Mon Sep 17 00:00:00 2001 From: hut Date: Tue, 21 May 2024 16:29:45 +0000 Subject: [PATCH] Ignore synthetic key presses (#4514) This PR discards "synthetic" winit keypresses, as discussed in the issue #4513. * Closes https://github.com/emilk/egui/issues/4513 --- crates/egui-winit/src/lib.rs | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 058a27f1661..fec16c73ae8 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -31,6 +31,7 @@ pub(crate) use profiling_scopes::*; use winit::{ dpi::{PhysicalPosition, PhysicalSize}, + event::ElementState, event_loop::EventLoopWindowTarget, window::{CursorGrabMode, Window, WindowButtons, WindowLevel}, }; @@ -368,16 +369,31 @@ impl State { consumed: self.egui_ctx.wants_keyboard_input(), } } - WindowEvent::KeyboardInput { event, .. } => { - self.on_keyboard_input(event); - - // When pressing the Tab key, egui focuses the first focusable element, hence Tab always consumes. - let consumed = self.egui_ctx.wants_keyboard_input() - || event.logical_key - == winit::keyboard::Key::Named(winit::keyboard::NamedKey::Tab); - EventResponse { - repaint: true, - consumed, + WindowEvent::KeyboardInput { + event, + is_synthetic, + .. + } => { + // Winit generates fake "synthetic" KeyboardInput events when the focus + // is changed to the window, or away from it. Synthetic key presses + // represent no real key presses and should be ignored. + // See https://github.com/rust-windowing/winit/issues/3543 + if *is_synthetic && event.state == ElementState::Pressed { + EventResponse { + repaint: true, + consumed: false, + } + } else { + self.on_keyboard_input(event); + + // When pressing the Tab key, egui focuses the first focusable element, hence Tab always consumes. + let consumed = self.egui_ctx.wants_keyboard_input() + || event.logical_key + == winit::keyboard::Key::Named(winit::keyboard::NamedKey::Tab); + EventResponse { + repaint: true, + consumed, + } } } WindowEvent::Focused(focused) => {