Clear all keys and modifies on focus change (#2933)
It is very easy for keys to become stuck when we alt-tab, or a save-dialog opens by Ctrl+S, etc. Therefore we new clear all the modifiers and down keys to avoid that.
This commit is contained in:
parent
ede3ded977
commit
d1af798a9b
|
|
@ -927,6 +927,8 @@ pub struct WindowInfo {
|
|||
pub maximized: bool,
|
||||
|
||||
/// Is the window focused and able to receive input?
|
||||
///
|
||||
/// This should be the same as [`egui::InputState::focused`].
|
||||
pub focused: bool,
|
||||
|
||||
/// Window inner size in egui points (logical pixels).
|
||||
|
|
|
|||
|
|
@ -31,9 +31,10 @@ impl WebInput {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn on_web_page_focus_change(&mut self, has_focus: bool) {
|
||||
pub fn on_web_page_focus_change(&mut self, focused: bool) {
|
||||
self.raw.modifiers = egui::Modifiers::default();
|
||||
self.raw.has_focus = has_focus;
|
||||
self.raw.focused = focused;
|
||||
self.raw.events.push(egui::Event::WindowFocused(focused));
|
||||
self.latest_touch_pos = None;
|
||||
self.latest_touch_pos_id = None;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ impl State {
|
|||
/// The returned `State` must not outlive the input `display_target`.
|
||||
pub fn new(display_target: &dyn HasRawDisplayHandle) -> Self {
|
||||
let egui_input = egui::RawInput {
|
||||
has_focus: false, // winit will tell us when we have focus
|
||||
focused: false, // winit will tell us when we have focus
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
|
@ -314,11 +314,14 @@ impl State {
|
|||
consumed,
|
||||
}
|
||||
}
|
||||
WindowEvent::Focused(has_focus) => {
|
||||
self.egui_input.has_focus = *has_focus;
|
||||
WindowEvent::Focused(focused) => {
|
||||
self.egui_input.focused = *focused;
|
||||
// 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();
|
||||
self.egui_input
|
||||
.events
|
||||
.push(egui::Event::WindowFocused(*focused));
|
||||
EventResponse {
|
||||
repaint: true,
|
||||
consumed: false,
|
||||
|
|
|
|||
|
|
@ -1139,7 +1139,7 @@ impl Context {
|
|||
{
|
||||
let state = self.frame_state_mut(|fs| fs.accesskit_state.take());
|
||||
if let Some(state) = state {
|
||||
let has_focus = self.input(|i| i.raw.has_focus);
|
||||
let has_focus = self.input(|i| i.raw.focused);
|
||||
let root_id = crate::accesskit_root_id().accesskit_id();
|
||||
let nodes = self.write(|ctx| {
|
||||
state
|
||||
|
|
|
|||
|
|
@ -63,8 +63,10 @@ pub struct RawInput {
|
|||
/// drag-and-drop support using `eframe::NativeOptions`.
|
||||
pub dropped_files: Vec<DroppedFile>,
|
||||
|
||||
/// The window has the keyboard focus (i.e. is receiving key presses).
|
||||
pub has_focus: bool,
|
||||
/// The native window has the keyboard focus (i.e. is receiving key presses).
|
||||
///
|
||||
/// False when the user alt-tab away from the application, for instance.
|
||||
pub focused: bool,
|
||||
}
|
||||
|
||||
impl Default for RawInput {
|
||||
|
|
@ -79,7 +81,7 @@ impl Default for RawInput {
|
|||
events: vec![],
|
||||
hovered_files: Default::default(),
|
||||
dropped_files: Default::default(),
|
||||
has_focus: true, // integrations opt into global focus tracking
|
||||
focused: true, // integrations opt into global focus tracking
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -100,7 +102,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,
|
||||
focused: self.focused,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +118,7 @@ impl RawInput {
|
|||
mut events,
|
||||
mut hovered_files,
|
||||
mut dropped_files,
|
||||
has_focus,
|
||||
focused,
|
||||
} = newer;
|
||||
|
||||
self.screen_rect = screen_rect.or(self.screen_rect);
|
||||
|
|
@ -128,7 +130,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;
|
||||
self.focused = focused;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -294,6 +296,9 @@ pub enum Event {
|
|||
modifiers: Modifiers,
|
||||
},
|
||||
|
||||
/// The native window gained or lost focused (e.g. the user clicked alt-tab).
|
||||
WindowFocused(bool),
|
||||
|
||||
/// An assistive technology (e.g. screen reader) requested an action.
|
||||
#[cfg(feature = "accesskit")]
|
||||
AccessKitActionRequest(accesskit::ActionRequest),
|
||||
|
|
@ -847,7 +852,7 @@ impl RawInput {
|
|||
events,
|
||||
hovered_files,
|
||||
dropped_files,
|
||||
has_focus,
|
||||
focused,
|
||||
} = self;
|
||||
|
||||
ui.label(format!("screen_rect: {:?} points", screen_rect));
|
||||
|
|
@ -865,7 +870,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.label(format!("focused: {}", focused));
|
||||
ui.scope(|ui| {
|
||||
ui.set_min_height(150.0);
|
||||
ui.label(format!("events: {:#?}", events))
|
||||
|
|
|
|||
|
|
@ -104,6 +104,11 @@ pub struct InputState {
|
|||
/// and will effectively slow down the animation when FPS drops below 10.
|
||||
pub stable_dt: f32,
|
||||
|
||||
/// The native window has the keyboard focus (i.e. is receiving key presses).
|
||||
///
|
||||
/// False when the user alt-tab away from the application, for instance.
|
||||
pub focused: bool,
|
||||
|
||||
/// Which modifier keys are down at the start of the frame?
|
||||
pub modifiers: Modifiers,
|
||||
|
||||
|
|
@ -129,6 +134,7 @@ impl Default for InputState {
|
|||
unstable_dt: 1.0 / 60.0,
|
||||
predicted_dt: 1.0 / 60.0,
|
||||
stable_dt: 1.0 / 60.0,
|
||||
focused: false,
|
||||
modifiers: Default::default(),
|
||||
keys_down: Default::default(),
|
||||
events: Default::default(),
|
||||
|
|
@ -189,6 +195,20 @@ impl InputState {
|
|||
}
|
||||
}
|
||||
|
||||
let mut modifiers = new.modifiers;
|
||||
|
||||
let focused_changed = self.focused != new.focused
|
||||
|| new
|
||||
.events
|
||||
.iter()
|
||||
.any(|e| matches!(e, Event::WindowFocused(_)));
|
||||
if focused_changed {
|
||||
// It is very common for keys to become stuck when we alt-tab, or a save-dialog opens by Ctrl+S.
|
||||
// Therefore we clear all the modifiers and down keys here to avoid that.
|
||||
modifiers = Default::default();
|
||||
keys_down = Default::default();
|
||||
}
|
||||
|
||||
InputState {
|
||||
pointer,
|
||||
touch_states: self.touch_states,
|
||||
|
|
@ -201,7 +221,8 @@ impl InputState {
|
|||
unstable_dt,
|
||||
predicted_dt: new.predicted_dt,
|
||||
stable_dt,
|
||||
modifiers: new.modifiers,
|
||||
focused: new.focused,
|
||||
modifiers,
|
||||
keys_down,
|
||||
events: new.events.clone(), // TODO(emilk): remove clone() and use raw.events
|
||||
raw: new,
|
||||
|
|
@ -926,6 +947,7 @@ impl InputState {
|
|||
unstable_dt,
|
||||
predicted_dt,
|
||||
stable_dt,
|
||||
focused,
|
||||
modifiers,
|
||||
keys_down,
|
||||
events,
|
||||
|
|
@ -969,6 +991,7 @@ impl InputState {
|
|||
));
|
||||
ui.label(format!("predicted_dt: {:.1} ms", 1e3 * predicted_dt));
|
||||
ui.label(format!("stable_dt: {:.1} ms", 1e3 * stable_dt));
|
||||
ui.label(format!("focused: {}", focused));
|
||||
ui.label(format!("modifiers: {:#?}", modifiers));
|
||||
ui.label(format!("keys_down: {:?}", keys_down));
|
||||
ui.scope(|ui| {
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ impl Response {
|
|||
/// also has the keyboard focus. That makes this function suitable
|
||||
/// for style choices, e.g. a thicker border around focused widgets.
|
||||
pub fn has_focus(&self) -> bool {
|
||||
self.ctx.input(|i| i.raw.has_focus) && self.ctx.memory(|mem| mem.has_focus(self.id))
|
||||
self.ctx.input(|i| i.focused) && self.ctx.memory(|mem| mem.has_focus(self.id))
|
||||
}
|
||||
|
||||
/// True if this widget has keyboard focus this frame, but didn't last frame.
|
||||
|
|
|
|||
Loading…
Reference in New Issue