bevyengine / bevyengine/bevy

Bevy does not report `.just_pressed` in this edge case involving windows focus and cursor grab

Open
#14,342 1 comment 0 reactions 0 assignees View on GitHub
A-Input A-Windowing C-Bug
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.