diff --git a/egui-winit/src/lib.rs b/egui-winit/src/lib.rs index dceb287b7206..d50374e39d42 100644 --- a/egui-winit/src/lib.rs +++ b/egui-winit/src/lib.rs @@ -70,9 +70,14 @@ impl State { } pub fn new_with_wayland_display(wayland_display: Option<*mut c_void>) -> Self { + let egui_input = egui::RawInput { + has_focus: false, // winit will tell us when we have focus + ..Default::default() + }; + Self { start_time: instant::Instant::now(), - egui_input: Default::default(), + egui_input, pointer_pos_in_points: None, any_pointer_button_down: false, current_cursor_icon: egui::CursorIcon::Default, @@ -214,7 +219,8 @@ impl State { egui_ctx.wants_keyboard_input() || input.virtual_keycode == Some(winit::event::VirtualKeyCode::Tab) } - WindowEvent::Focused(_) => { + WindowEvent::Focused(has_focus) => { + self.egui_input.has_focus = *has_focus; // We will not be given a KeyboardInput event when the modifiers are released while // the window does not have focus. Unset all modifier state to be safe. self.egui_input.modifiers = egui::Modifiers::default(); diff --git a/egui/src/data/input.rs b/egui/src/data/input.rs index 6bd28d4d588b..01aa1c6c136d 100644 --- a/egui/src/data/input.rs +++ b/egui/src/data/input.rs @@ -62,6 +62,9 @@ pub struct RawInput { /// Note: when using `eframe` on Windows you need to enable /// drag-and-drop support using `eframe::NativeOptions`. pub dropped_files: Vec, + + /// The window has the keyboard focus (i.e. is receiving key presses). + pub has_focus: bool, } impl Default for RawInput { @@ -76,6 +79,7 @@ impl Default for RawInput { events: vec![], hovered_files: Default::default(), dropped_files: Default::default(), + has_focus: true, // integrations opt into global focus tracking } } } @@ -96,6 +100,7 @@ impl RawInput { events: std::mem::take(&mut self.events), hovered_files: self.hovered_files.clone(), dropped_files: std::mem::take(&mut self.dropped_files), + has_focus: self.has_focus, } } @@ -111,6 +116,7 @@ impl RawInput { mut events, mut hovered_files, mut dropped_files, + has_focus, } = newer; self.screen_rect = screen_rect.or(self.screen_rect); @@ -122,6 +128,7 @@ impl RawInput { self.events.append(&mut events); self.hovered_files.append(&mut hovered_files); self.dropped_files.append(&mut dropped_files); + self.has_focus = has_focus; } } @@ -541,6 +548,7 @@ impl RawInput { events, hovered_files, dropped_files, + has_focus, } = self; ui.label(format!("screen_rect: {:?} points", screen_rect)); @@ -558,6 +566,7 @@ impl RawInput { ui.label(format!("modifiers: {:#?}", modifiers)); ui.label(format!("hovered_files: {}", hovered_files.len())); ui.label(format!("dropped_files: {}", dropped_files.len())); + ui.label(format!("has_focus: {}", has_focus)); ui.scope(|ui| { ui.set_min_height(150.0); ui.label(format!("events: {:#?}", events)) diff --git a/egui/src/response.rs b/egui/src/response.rs index 8edd48ba886d..4a3d0326f229 100644 --- a/egui/src/response.rs +++ b/egui/src/response.rs @@ -213,7 +213,9 @@ impl Response { /// This widget has the keyboard focus (i.e. is receiving key presses). pub fn has_focus(&self) -> bool { - self.ctx.memory().has_focus(self.id) + // Access input and memory in separate statements to prevent deadlock. + let has_global_focus = self.ctx.input().raw.has_focus; + has_global_focus && self.ctx.memory().has_focus(self.id) } /// True if this widget has keyboard focus this frame, but didn't last frame.