mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
# Objective Fixes #13299 On Linux/X11, changing focus into a winit window will produce winit KeyboardInput events with a "is_synthetic=true" flag that are not intended to be used. Bevy erroneously passes them on to the user, resulting in phantom key presses. ## Solution This patch properly filters out winit KeyboardInput events with "is_synthetic=true". For example, pressing Alt+Tab to focus a bevy winit window results in a permanently stuck Tab key until the user presses Tab once again to produce a winit KeyboardInput release event. The Tab key press event that causes this problem is "synthetic", should not be used according to the winit devs, and simply ignoring it fixes this problem. Synthetic key **releases** are still evaluated though, as they are essential for correct release key handling. For example, if the user binds the key combination Alt+1 to the action "move the window to workspace 1", places the bevy game in workspace 2, focuses the game and presses Alt+1, then the key release event for the "1" key will be synthetic. If we would filter out all synthetic keys, the bevy game would think that the 1 key remains pressed forever, until the user manually presses+releases the key again inside bevy. Reference: https://docs.rs/winit/0.30.0/winit/event/enum.WindowEvent.html#variant.KeyboardInput.field.is_synthetic Relevant discussion: https://github.com/rust-windowing/winit/issues/3543 ## Testing Tested with the "keyboard_input_events" example. Entering/exiting the window with various keys, as well as changing its workspace, produces the correct press/release events.
This commit is contained in:
parent
13f9b6993d
commit
92ac77867d
1 changed files with 19 additions and 8 deletions
|
@ -223,16 +223,27 @@ impl<T: Event> ApplicationHandler<T> for WinitAppRunnerState<T> {
|
|||
);
|
||||
}
|
||||
WindowEvent::CloseRequested => self.winit_events.send(WindowCloseRequested { window }),
|
||||
WindowEvent::KeyboardInput { ref event, .. } => {
|
||||
if event.state.is_pressed() {
|
||||
if let Some(char) = &event.text {
|
||||
let char = char.clone();
|
||||
#[allow(deprecated)]
|
||||
self.winit_events.send(ReceivedCharacter { window, char });
|
||||
WindowEvent::KeyboardInput {
|
||||
ref event,
|
||||
is_synthetic,
|
||||
..
|
||||
} => {
|
||||
// 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.
|
||||
if event.state.is_pressed() {
|
||||
if let Some(char) = &event.text {
|
||||
let char = char.clone();
|
||||
#[allow(deprecated)]
|
||||
self.winit_events.send(ReceivedCharacter { window, char });
|
||||
}
|
||||
}
|
||||
self.winit_events
|
||||
.send(converters::convert_keyboard_input(event, window));
|
||||
}
|
||||
self.winit_events
|
||||
.send(converters::convert_keyboard_input(event, window));
|
||||
}
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
let physical_position = DVec2::new(position.x, position.y);
|
||||
|
|
Loading…
Reference in a new issue