bevyengine / bevyengine/bevy

Wayland `Locked` `CursorMode` causes error with `window.set_cursor_position` claiming the position mode is not `Locked`

Open
#19,815 1 comment 3 reactions 0 assignees View on GitHub
A-Windowing C-Bug O-Linux S-Blocked
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## Bevy version

16.0 to main

## Relevant system information

Linux kernel 6.15.2 on Wayland (built with `wayland` feature)

## What you did

Assume a standard Linux setup under wayland with the following code. In `Setup`, it sets the cursor mode to `Locked`, and in every `update`, the cursor position is set with `window.set_cursor_position`.

This results in an error:

```
2025-06-25T21:13:38.781498Z ERROR bevy_winit::system: could not set cursor position: os error at /home/doomy/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/winit-0.30.11/src/platform_impl/linux/wayland/window/state.rs:901: cursor position can be set only for locked cursor.
```

This is confusing, as the cursor position is set to locked.

```rs
use bevy::{prelude::*, window::CursorGrabMode, window::CursorOptions};

fn main() {
App::new().add_plugins(ClientPlugin).run();
}

pub struct ClientPlugin;

impl Plugin for ClientPlugin {
fn build(&self, app: &mut App) {
// ...
app.add_plugins(DefaultPlugins);
app.add_systems(Startup, setup_cursor);
app.add_systems(Update, recenter_cursor);
}
}

fn setup_cursor(mut windows: Query<(&mut Window, &mut CursorOptions)>) {
let Ok((mut window, mut cursor_options)) = windows.single_mut() else {
panic!();
};
cursor_options.visible = true;
cursor_options.grab_mode = CursorGrabMode::Locked;
let center = Vec2::new(window.width() / 2., window.height() / 2.);
window.set_cursor_position(Some(center));
}

fn recenter_cursor(mut windows: Query<&mut Window>) {
let Ok(mut window) = windows.single_mut() else {
panic!();
};
let center = Vec2::new(window.width() / 2., window.height() / 2.);
window.set_cursor_position(Some(center));
}
```

## What went wrong

Expectation: The cursor should be locked and allowed to be set to a specific position, in this case, the center of the screen.

Actual: The cursor is locked in place, but is not placed in the center, and an error is emitted.

## Additional information

It was suggested that the system [ordering here](https://github.com/bevyengine/bevy/blob/97dcb279fb2a96902bc04286238326b0fa6081ad/crates/bevy_winit/src/lib.rs#L145) may be at fault, as the cursor mode is set after window properties. However, after reordering the systems locally, the same issue persisted.

Contributor guide

Open the contributing guide

Research direction

Start with the cursor-related system ordering in crates/bevy_winit/src/lib.rs, then reproduce the example on Linux with Wayland and the wayland feature enabled. Trace how CursorOptions.grab_mode and set_cursor_position are applied; done means Locked mode permits the requested center position without emitting the reported error.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
desktop-dev, game-dev, operating-systems
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.