Bevy does not report `.just_pressed` in this edge case involving windows focus and cursor grab
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## Bevy version
0.14.0
## Relevant system information
Ubuntu 20.04.6 LTS
## What you did
I'm using bevy system which grabs cursor on click and releases grab on click release and when window looses focus, code example provided below, here is an output of `log_just_pressed_flag_issue` with my comments and video demonstration:
```
# click in bevy window
MouseButtonInput { button: Left, state: Pressed, window: Entity { index: 0, generation: 1 } } .just_pressed is true, .just_released is false
grab cursor
# I switched to another window by pressing Alt+Tab, while holding mouse button,
# and released button under ANOTHER window (if release under bevy window it will work Ok)
release cursor on focus lost
# !!! NO release event reported
# now I clicked on bevy window, event "Pressed" is reported, !!! BUT .just_pressed is false
MouseButtonInput { button: Left, state: Pressed, window: Entity { index: 0, generation: 1 } } .just_pressed is false, .just_released is false
MouseButtonInput { button: Left, state: Released, window: Entity { index: 0, generation: 1 } } .just_pressed is false, .just_released is true
release cursor
```
https://github.com/user-attachments/assets/68249be5-366f-4a7b-947d-ee2c876afc31
## What went wrong
Here is what I expect it is similar example, but without cursor grab, it provided in code example in `log_just_pressed_flag_this_is_ok` system:
```
# click in bevy window
MouseButtonInput { button: Left, state: Pressed, window: Entity { index: 0, generation: 1 } } .just_pressed is true, .just_released is false
# alt+tab, release button under another window, events reported, flag set
MouseButtonInput { button: Left, state: Released, window: Entity { index: 0, generation: 1 } } .just_pressed is false, .just_released is true
# click in bevy window again, event reported, flag set
MouseButtonInput { button: Left, state: Pressed, window: Entity { index: 0, generation: 1 } } .just_pressed is true, .just_released is false
MouseButtonInput { button: Left, state: Released, window: Entity { index: 0, generation: 1 } } .just_pressed is false, .just_released is true
```
## Code used in tests
```rust
use bevy::{
color::palettes::tailwind,
input::mouse::MouseButtonInput,
prelude::*,
window::{CursorGrabMode, PresentMode, PrimaryWindow, WindowFocused},
};
fn main() {
App::new()
.insert_resource(ClearColor(tailwind::AMBER_900.into()))
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
present_mode: PresentMode::Immediate,
..default()
}),
..default()
}))
.add_systems(Startup, setup)
.add_systems(Update, log_just_pressed_flag_issue)
// .add_systems(Update, log_just_pressed_flag_this_is_ok)
.run();
}
fn setup(mut cmd: Commands) {
cmd.spawn(Camera2dBundle::default());
}
fn log_just_pressed_flag_issue(
mut window_q: Query<&mut Window, With>,
mouse: Res>,
mut buttons: EventReader,
mut focus: EventReader,
) {
for e in buttons.read() {
println!(
"{:?} .just_pressed is {}, .just_released is {}",
e,
mouse.just_pressed(MouseButton::Left),
mouse.just_released(MouseButton::Left)
);
}
let mut window = window_q.single_mut();
for e in focus.read() {
if !e.focused {
println!("release cursor on focus lost");
window.cursor.grab_mode = CursorGrabMode::None;
return;
}
}
if mouse.just_pressed(MouseButton::Left) {
println!("grab cursor");
window.cursor.grab_mode = CursorGrabMode::Confined;
}
if mouse.just_released(MouseButton::Left) {
println!("release cursor");
window.cursor.grab_mode = CursorGrabMode::None;
}
}
fn log_just_pressed_flag_this_is_ok(
mouse: Res>,
mut buttons: EventReader,
) {
for e in buttons.read() {
println!(
"{:?} .just_pressed is {}, .just_released is {}",
e,
mouse.just_pressed(MouseButton::Left),
mouse.just_released(MouseButton::Left)
);
}
}
```
Contributor guide
Assessment
This issue has not been assessed yet.