bevy
bevy copied to clipboard
Cursor lock no longer locks the cursor in place, only confines it to the window
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.
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.));
}
}
https://user-images.githubusercontent.com/87893492/129318600-53d28f0d-342a-4b31-b513-8508788bdd96.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.
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...
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.
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.
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.
It seems that winit now supports, at least partially, cursor locking: https://github.com/rust-windowing/winit/commit/9e6f666616341ddd76fc61c6a0ed8dcbf3392a28
With recent bevy we could set cursor be confined. Is this issue resolved by this?
I have this issue too with Bevy 0.11 and Windows 11
as the doc says, Locked is not supported on Windows