winit icon indicating copy to clipboard operation
winit copied to clipboard

Retry XGrabPointer a couple of times (up to 500ms) if it failes

Open Visse opened this issue 4 years ago • 5 comments

If you try to grab the cursor right after you created the window you get the error:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os(OsError { line: 1266, file: "/home/visse/repos/winit/src/platform_impl/linux/x11/window.rs", error: XMisc("Cursor could not be grabbed: grab location not viewable") })', src/main.rs:11:34

Minimal repro:

use winit::{event_loop::EventLoop, window::WindowBuilder};

fn main() {
    let event_loop = EventLoop::new();

    let window = WindowBuilder::new()
        .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
        .build(&event_loop)
        .unwrap();

    window.set_cursor_grab(true).unwrap();
}

Checking the sdl implementation, it looks like they are solving it by retrying it a couple of times: https://github.com/libsdl-org/SDL/blob/e65a6583201ee1a9a3bc3064655b186fc16ef719/src/video/x11/SDL_x11window.c#L1611-L1619

This PR simply implements the same scheme and retries XGrabPointer up to 10 times with a slight delay between each, for a total delay up to 500ms.

  • [X] Tested on all platforms changed
  • [X] Compilation warnings were addressed
  • [X] cargo fmt has been run on this branch
  • [X] cargo doc builds successfully
  • [X] Added an entry to CHANGELOG.md if knowledge of this change could be valuable to users
  • [ ] Updated documentation to reflect any user-facing changes, including notes of platform-specific behavior
  • [ ] Created or updated an example program if it would help users understand this functionality
  • [ ] Updated feature matrix, if new features were added or implemented

Visse avatar Jun 12 '21 13:06 Visse

Is there something I can do to speed up merging? Or is something missing? I'm not too familiar with the process.

Visse avatar Jul 31 '21 11:07 Visse

Would a viable alternative be to wait until the first cursor event is received and then request the cursor grab? It shouldn't make any difference to the user except that if the cursor isn't initially over the window it won't be captured until it is (which seems fine?). That way you're never blocking.

dhardy avatar Aug 23 '21 09:08 dhardy

Related: #2080

parasyte avatar Dec 10 '21 09:12 parasyte

The SDL solution to this looks like a hack really. The X11 backend could be updated to track the 'mapped' state of the window to account for the asynchronous nature of creating X windows. The code for cursor grabs would then need to have a "pending" state that's used in case the window is not currently mapped. Whenever winit gets notified of a window being mapped then it would check for any pending grabs an then apply them, which should then succeed.

rib avatar May 29 '22 02:05 rib

Once #3122 is merged, I can update this PR to wait for events using the new userspace event queue introduced in that PR.

notgull avatar Nov 14 '23 03:11 notgull