Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cursor lock no longer locks the cursor in place, only confines it to the window #2645

Closed
neo97dev opened this issue Aug 13, 2021 · 9 comments
Labels
A-Input Player input via keyboard, mouse, gamepad, and more A-Windowing Platform-agnostic interface layer to run your app in C-Bug An unexpected or incorrect behavior

Comments

@neo97dev
Copy link

neo97dev commented Aug 13, 2021

Bevy version

main#b13472d

Operating system & version

X11 on Arch Linux 5.13.7-arch1-1

What you did

window.set_cursor_lock_mode(true);

What you expected to happen

The cursor should be locked in place, allowing cursor movement events to work as normal, but keeping the actual mouse cursor from moving or leaving the window. This is important for first-person and third-person camera movement.

What actually happened

The cursor is confined to the bounds of the window, but not locked in place. For example, when moving a first-person camera controller, you can only move the mouse as far as the window bounds go, preventing you from rotating 360 degrees with the mouse.

Additional information

This issue did not occur in Bevy 0.5, only in the main branch. It looks like winit was bumped from 0.24 to 0.25 since Bevy 0.5, but after downgrading winit manually in my fork, the issue still remained. It does not look like winit has changed this behavior on their end since 0.24, so it must be something in bevy, unless I missed something.

Cursor lock does seem to work correctly in fullscreen.

@neo97dev neo97dev added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Aug 13, 2021
@neo97dev neo97dev changed the title Cursor lock does not lock the cursor Cursor lock no longer locks the cursor in place, only confines it to the window Aug 13, 2021
@neo97dev
Copy link
Author

As mentioned by @DJMcNab in this message, my expected behavior does not align with winit's expected behavior for the underlying set_cursor_grab function. There is an open issue for this behavior in winit.

I was able to implement it myself in my Bevy app by adding the following system:

fn lock_cursor_position(mut windows: ResMut<Windows>) {
	if let Some(window) = windows.get_primary_mut() {
		window.set_cursor_position(Vec2::new(window.width() / 2., window.height() / 2.));
	}
}
bevy.cursor.lock.mp4

The question now is, should this locking functionality be provided by bevy? It's not a difficult system to write, but it will be needed by any first-person game, and by many third-person games as well. It feels like setting the cursor lock mode in Window should provide this behavior out of the box, as this is what it means to "lock" the cursor.

@mockersf
Copy link
Member

In most case where you "lock" (with Bevy's lock) the cursor, wouldn't you want to also make it invisible, which would make this issue invisible?

I think it would make more sense to let winit handles it properly as described in the issue you linked. The current behaviour is platform dependent which is not fun...

@neo97dev
Copy link
Author

neo97dev commented Aug 13, 2021

In most case where you "lock" (with Bevy's lock) the cursor, wouldn't you want to also make it invisible, which would make this issue invisible?

Yes, I kept it visible for demonstration, but unfortunately making it invisible does not resolve the issue. Its more than a visual issue - when the cursor hits the edge of the window, it stops moving and stops generating movement events, so anything tracking mouse movement (such as rotation in my case) will stop working.

Now that I think of it, that could be a possible cause of the issue since bevy 0.5, if mouse movement events were changed to not fire at the edge of the window. While it is different than actually locking the cursor, if mouse events fired regardless of the window boundaries, that would solve the main use case for this.

@alice-i-cecile alice-i-cecile added A-Windowing Platform-agnostic interface layer to run your app in and removed S-Needs-Triage This issue needs to be labelled labels Aug 16, 2021
@yottapanda
Copy link

I was able to get your video example working on main branch using EventReader<MouseMotion>.

EventReader<CursorMotion> as you've found appears to stop reading events when the cursor reaches the edge of the window while MouseMotion keeps receiving events.

@Shfty
Copy link
Contributor

Shfty commented May 21, 2022

It's worth noting that @neo97dev's solution doesn't work under Wayland due to a missing implementation for set_cursor_position in winit.

It does work under xwayland, so evidently the requisite low-level machinery exists, but there are other issues (ex. #839) to consider with that option.

@Metadorius
Copy link

It seems that winit now supports, at least partially, cursor locking: rust-windowing/winit@9e6f666

@VitalyAnkh
Copy link
Contributor

With recent bevy we could set cursor be confined. Is this issue resolved by this?

@alice-i-cecile alice-i-cecile added the A-Input Player input via keyboard, mouse, gamepad, and more label Aug 17, 2023
@MentaalAchtergesteld
Copy link

I have this issue too with Bevy 0.11 and Windows 11

@mockersf
Copy link
Member

as the doc says, Locked is not supported on Windows

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Input Player input via keyboard, mouse, gamepad, and more A-Windowing Platform-agnostic interface layer to run your app in C-Bug An unexpected or incorrect behavior
Projects
None yet
Development

No branches or pull requests

8 participants