mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
Fix window spawning triggering ButtonInput<KeyCode>::just_pressed/just_released (#12372)
# Objective Fix #12273 ## Solution – Only emit `KeyboardFocusLost` when the keyboard focus is lost – ignore synthetic key releases too, not just key presses (as they're already covered by `KeyboardFocusLost`) --- ## Changelog ### Fixed - Don't trigger `ButtonInput<KeyCode>::just_pressed`/`just_released` when spawning a window/focus moving between Bevy windows
This commit is contained in:
parent
c2d193abd5
commit
e7c6228e8b
5 changed files with 32 additions and 19 deletions
|
@ -62,8 +62,7 @@ use {
|
|||
///
|
||||
/// `ButtonInput<KeyCode>` is tied to window focus. For example, if the user holds a button
|
||||
/// while the window loses focus, [`ButtonInput::just_released`] will be triggered. Similarly if the window
|
||||
/// regains focus, [`ButtonInput::just_pressed`] will be triggered. Currently this happens even if the
|
||||
/// focus switches from one Bevy window to another (for example because a new window was just spawned).
|
||||
/// regains focus, [`ButtonInput::just_pressed`] will be triggered.
|
||||
///
|
||||
/// `ButtonInput<GamepadButton>` is independent of window focus.
|
||||
///
|
||||
|
|
|
@ -134,7 +134,7 @@ pub struct KeyboardFocusLost;
|
|||
/// ## Differences
|
||||
///
|
||||
/// The main difference between the [`KeyboardInput`] event and the [`ButtonInput<KeyCode>`] resources is that
|
||||
/// the latter have convenient functions such as [`ButtonInput::pressed`], [`ButtonInput::just_pressed`] and [`ButtonInput::just_released`].
|
||||
/// the latter has convenient functions such as [`ButtonInput::pressed`], [`ButtonInput::just_pressed`] and [`ButtonInput::just_released`] and is window id agnostic.
|
||||
pub fn keyboard_input_system(
|
||||
mut key_input: ResMut<ButtonInput<KeyCode>>,
|
||||
mut keyboard_input_events: EventReader<KeyboardInput>,
|
||||
|
|
|
@ -27,7 +27,7 @@ use bevy_ecs::prelude::*;
|
|||
use bevy_window::{exit_on_all_closed, Window, WindowCreated};
|
||||
pub use converters::convert_system_cursor_icon;
|
||||
pub use state::{CursorSource, CustomCursorCache, CustomCursorCacheKey, PendingCursor};
|
||||
use system::{changed_windows, despawn_windows};
|
||||
use system::{changed_windows, check_keyboard_focus_lost, despawn_windows};
|
||||
pub use system::{create_monitors, create_windows};
|
||||
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
|
||||
pub use winit::platform::web::CustomCursorExtWebSys;
|
||||
|
@ -133,6 +133,7 @@ impl<T: Event> Plugin for WinitPlugin<T> {
|
|||
// so we don't need to care about its ordering relative to `changed_windows`
|
||||
changed_windows.ambiguous_with(exit_on_all_closed),
|
||||
despawn_windows,
|
||||
check_keyboard_focus_lost,
|
||||
)
|
||||
.chain(),
|
||||
);
|
||||
|
|
|
@ -10,7 +10,6 @@ use bevy_ecs::{
|
|||
};
|
||||
use bevy_input::{
|
||||
gestures::*,
|
||||
keyboard::KeyboardFocusLost,
|
||||
mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
|
||||
};
|
||||
use bevy_log::{error, trace, warn};
|
||||
|
@ -267,18 +266,14 @@ impl<T: Event> ApplicationHandler<T> for WinitAppRunnerState<T> {
|
|||
.send(WindowCloseRequested { window }),
|
||||
WindowEvent::KeyboardInput {
|
||||
ref event,
|
||||
is_synthetic,
|
||||
// On some platforms, winit sends "synthetic" key press events when the window
|
||||
// gains or loses focus. These should not be handled, so we only process key
|
||||
// events if they are not synthetic key presses.
|
||||
is_synthetic: false,
|
||||
..
|
||||
} => {
|
||||
// Winit sends "synthetic" key press events when the window gains focus. These
|
||||
// should not be handled, so we only process key events if they are not synthetic
|
||||
// key presses. "synthetic" key release events should still be handled though, for
|
||||
// properly releasing keys when the window loses focus.
|
||||
if !(is_synthetic && event.state.is_pressed()) {
|
||||
// Process the keyboard input event, as long as it's not a synthetic key press.
|
||||
self.bevy_window_events
|
||||
.send(converters::convert_keyboard_input(event, window));
|
||||
}
|
||||
self.bevy_window_events
|
||||
.send(converters::convert_keyboard_input(event, window));
|
||||
}
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
let physical_position = DVec2::new(position.x, position.y);
|
||||
|
@ -354,9 +349,6 @@ impl<T: Event> ApplicationHandler<T> for WinitAppRunnerState<T> {
|
|||
win.focused = focused;
|
||||
self.bevy_window_events
|
||||
.send(WindowFocused { window, focused });
|
||||
if !focused {
|
||||
self.bevy_window_events.send(KeyboardFocusLost);
|
||||
}
|
||||
}
|
||||
WindowEvent::Occluded(occluded) => {
|
||||
self.bevy_window_events
|
||||
|
|
|
@ -6,10 +6,11 @@ use bevy_ecs::{
|
|||
removal_detection::RemovedComponents,
|
||||
system::{Local, NonSendMut, Query, SystemParamItem},
|
||||
};
|
||||
use bevy_input::keyboard::KeyboardFocusLost;
|
||||
use bevy_utils::tracing::{error, info, warn};
|
||||
use bevy_window::{
|
||||
ClosingWindow, Monitor, PrimaryMonitor, RawHandleWrapper, VideoMode, Window, WindowClosed,
|
||||
WindowClosing, WindowCreated, WindowMode, WindowResized, WindowWrapper,
|
||||
WindowClosing, WindowCreated, WindowFocused, WindowMode, WindowResized, WindowWrapper,
|
||||
};
|
||||
|
||||
use winit::{
|
||||
|
@ -122,6 +123,26 @@ pub fn create_windows<F: QueryFilter + 'static>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Check whether keyboard focus was lost. This is different from window
|
||||
/// focus in that swapping between Bevy windows keeps window focus.
|
||||
pub(crate) fn check_keyboard_focus_lost(
|
||||
mut focus_events: EventReader<WindowFocused>,
|
||||
mut keyboard_focus: EventWriter<KeyboardFocusLost>,
|
||||
) {
|
||||
let mut focus_lost = false;
|
||||
let mut focus_gained = false;
|
||||
for e in focus_events.read() {
|
||||
if e.focused {
|
||||
focus_gained = true;
|
||||
} else {
|
||||
focus_lost = true;
|
||||
}
|
||||
}
|
||||
if focus_lost & !focus_gained {
|
||||
keyboard_focus.send(KeyboardFocusLost);
|
||||
}
|
||||
}
|
||||
|
||||
/// Synchronize available monitors as reported by [`winit`] with [`Monitor`] entities in the world.
|
||||
pub fn create_monitors(
|
||||
event_loop: &ActiveEventLoop,
|
||||
|
|
Loading…
Reference in a new issue