winit icon indicating copy to clipboard operation
winit copied to clipboard

Add cursor locking support for X11

Open Imberflur opened this issue 2 years ago • 8 comments

As noted in https://github.com/rust-windowing/winit/issues/1677 locking the cursor (rather than just confining to the window) can be useful for cases like camera control. winit does not currently provide cursor locking for Windows and X11 but the information in that issue indicates that it should be possible for Windows and is maybe(?) possible for X11.

Imberflur avatar Sep 10 '23 21:09 Imberflur

Hacking around it isn't too bad. This is what I've been using on a recent project of mine. Haven't tested windows yet but x11(XWayland) seems to work.

#[derive(Default)]
struct MouseGrabber {
	last_pos: PhysicalPosition<f64>,
	manual_lock: bool,
}

impl MouseGrabber {
	// Call this on every WindowEvent::CursorMoved to update the last known position
	fn cursor_moved(&mut self, window: &Window, pos: PhysicalPosition<f64>) {
		if self.manual_lock {
			window.set_cursor_position(self.last_pos).unwrap();
		} else {
			self.last_pos = pos;
		}
	}
	// Call this with true to lock and false to unlock
	fn grab(&mut self, window: &Window, grab: bool) {
		if grab {
			if window.set_cursor_grab(CursorGrabMode::Locked).is_err() {
				window.set_cursor_grab(CursorGrabMode::Confined).unwrap();
				self.manual_lock = true;
			}
		} else {
			self.manual_lock = false;
			window.set_cursor_grab(CursorGrabMode::None).unwrap();
		}
		window.set_cursor_visible(!grab);
	}
}

This puts the mouse back to its last unlocked position, but it could probably be made simpler if you just wanted to lock to the center of the window.

GiantBlargg avatar Sep 25 '23 06:09 GiantBlargg

@GiantBlargg thanks for sharing a workaround!

Imberflur avatar Sep 26 '23 15:09 Imberflur

You can also submit this upstream, just saying. It's not like it'll be any different....

kchibisov avatar Sep 26 '23 15:09 kchibisov

Is there any reason or hurdles to implementing cursor locking in winit itself, rather than using this workaround?

ten3roberts avatar May 21 '24 22:05 ten3roberts

I'd also like to know if there is a reason why this is not implemented on Windows?

It seems very easy to implement by just taking the current cursor position and setting the cursor clipping window to just this position: https://github.com/dbartussek/winit/commit/dbd7cbdfc09252a7bfb1fda95e6607b2040c1ba7 Is there some hidden pitfall here I'm not seeing?

dbartussek avatar May 27 '24 13:05 dbartussek

Windows part done.

kchibisov avatar Apr 25 '25 10:04 kchibisov

When will the X11 part be implemented?

gavrix32 avatar Jul 22 '25 20:07 gavrix32

When someone implements it.

kchibisov avatar Jul 23 '25 00:07 kchibisov