diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index 13fb4b8592..4e6fffef8d 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -202,3 +202,4 @@ changelog entry. - On macOS, fixed the scancode conversion for `IntlBackslash`. - On macOS, fixed redundant `SurfaceResized` event at window creation. - On Windows, fixed the event loop not waking on accessibility requests. +- On X11, fixed cursor grab mode state tracking on error. diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index e3a72ad228..16c1089ee1 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -1827,6 +1827,11 @@ impl UnownedWindow { #[inline] pub fn set_cursor_grab(&self, mode: CursorGrabMode) -> Result<(), RequestError> { + // We don't support the locked cursor yet, so ignore it early on. + if mode == CursorGrabMode::Locked { + return Err(NotSupportedError::new("locked cursor is not implemented on X11").into()); + } + let mut grabbed_lock = self.cursor_grabbed_mode.lock().unwrap(); if mode == *grabbed_lock { return Ok(()); @@ -1838,6 +1843,7 @@ impl UnownedWindow { .xcb_connection() .ungrab_pointer(x11rb::CURRENT_TIME) .expect_then_ignore_error("Failed to call `xcb_ungrab_pointer`"); + *grabbed_lock = CursorGrabMode::None; let result = match mode { CursorGrabMode::None => self @@ -1845,34 +1851,33 @@ impl UnownedWindow { .flush_requests() .map_err(|err| RequestError::Os(os_error!(X11Error::Xlib(err)))), CursorGrabMode::Confined => { - let result = { - self.xconn - .xcb_connection() - .grab_pointer( - true as _, - self.xwindow, - xproto::EventMask::BUTTON_PRESS - | xproto::EventMask::BUTTON_RELEASE - | xproto::EventMask::ENTER_WINDOW - | xproto::EventMask::LEAVE_WINDOW - | xproto::EventMask::POINTER_MOTION - | xproto::EventMask::POINTER_MOTION_HINT - | xproto::EventMask::BUTTON1_MOTION - | xproto::EventMask::BUTTON2_MOTION - | xproto::EventMask::BUTTON3_MOTION - | xproto::EventMask::BUTTON4_MOTION - | xproto::EventMask::BUTTON5_MOTION - | xproto::EventMask::KEYMAP_STATE, - xproto::GrabMode::ASYNC, - xproto::GrabMode::ASYNC, - self.xwindow, - 0u32, - x11rb::CURRENT_TIME, - ) - .expect("Failed to call `grab_pointer`") - .reply() - .expect("Failed to receive reply from `grab_pointer`") - }; + let result = self + .xconn + .xcb_connection() + .grab_pointer( + true as _, + self.xwindow, + xproto::EventMask::BUTTON_PRESS + | xproto::EventMask::BUTTON_RELEASE + | xproto::EventMask::ENTER_WINDOW + | xproto::EventMask::LEAVE_WINDOW + | xproto::EventMask::POINTER_MOTION + | xproto::EventMask::POINTER_MOTION_HINT + | xproto::EventMask::BUTTON1_MOTION + | xproto::EventMask::BUTTON2_MOTION + | xproto::EventMask::BUTTON3_MOTION + | xproto::EventMask::BUTTON4_MOTION + | xproto::EventMask::BUTTON5_MOTION + | xproto::EventMask::KEYMAP_STATE, + xproto::GrabMode::ASYNC, + xproto::GrabMode::ASYNC, + self.xwindow, + 0u32, + x11rb::CURRENT_TIME, + ) + .expect("Failed to call `grab_pointer`") + .reply() + .expect("Failed to receive reply from `grab_pointer`"); match result.status { xproto::GrabStatus::SUCCESS => Ok(()), @@ -1892,11 +1897,7 @@ impl UnownedWindow { } .map_err(|err| RequestError::Os(os_error!(err))) }, - CursorGrabMode::Locked => { - return Err( - NotSupportedError::new("locked cursor is not implemented on X11").into() - ); - }, + CursorGrabMode::Locked => return Ok(()), }; if result.is_ok() {