Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crashes when RUST_LOG=info with env_logger, and window.set_grub_cursor(true) is called on Linux #2080

Open
PizzasBear opened this issue Dec 2, 2021 · 5 comments
Labels
B - bug Dang, that shouldn't have happened C - needs investigation Issue must be confirmed and researched DS - x11

Comments

@PizzasBear
Copy link

PizzasBear commented Dec 2, 2021

This code, when run with RUST_LOG=info environment variable on Debian 11 crashes. It doesn't crash when ran with RUST_LOG=warn.

use winit::{
    event::*,
    event_loop::{ControlFlow, EventLoop},
    window::Window,
};

fn main() {
    env_logger::init();

    let event_loop = EventLoop::new();
    let window = Window::new(&event_loop).unwrap();
    window.set_cursor_grab(true).unwrap();

    event_loop.run(|event, _, control_flow| match event {
        Event::WindowEvent {
            event:
                WindowEvent::KeyboardInput {
                    input:
                        KeyboardInput {
                            virtual_keycode: Some(VirtualKeyCode::Escape),
                            ..
                        },
                    ..
                },
            ..
        }
        | Event::WindowEvent {
            event: WindowEvent::CloseRequested,
            ..
        } => {
            *control_flow = ControlFlow::Exit;
        }
        _ => {}
    });
}

message:

[2021-12-02T07:42:59Z INFO  winit::platform_impl::platform::x11::window] Guessed window scale factor: 1
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os(OsError { line: 1292, file: "/home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/winit-0.26.0/src/platform_impl/linux/x11/window.rs", error: XMisc("Cursor could not be grabbed: grab location not viewable") })', src/main.rs:12:34
stack backtrace:
   0: rust_begin_unwind
             at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/std/src/panicking.rs:517:5
   1: core::panicking::panic_fmt
             at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/core/src/panicking.rs:101:14
   2: core::result::unwrap_failed
             at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/core/src/result.rs:1617:5
   3: core::result::Result<T,E>::unwrap
             at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/core/src/result.rs:1299:23
   4: winit_issue::main
             at ./src/main.rs:12:5
   5: core::ops::function::FnOnce::call_once
             at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

winit's version is 0.26.0 and env_logger's version is 0.9.0.

@maroider maroider added DS - x11 C - needs investigation Issue must be confirmed and researched B - bug Dang, that shouldn't have happened labels Dec 2, 2021
@mahkoh
Copy link
Contributor

mahkoh commented Dec 2, 2021

Grabbing the cursor requires the window to be mapped. Mapping is performed by the window manager asynchronously.

@parasyte
Copy link

parasyte commented Dec 5, 2021

I tried grabbing the cursor in Event::NewEvents(StartCause::Init) and it still fails in the same way. There doesn't seem to be an event for "window was just created and is ready to be used". To avoid the Wisdom of the Ancients, how are users expected to deal with this asynchronous window manager behavior?

The most awful naive hack you can imagine works, but ... there has got to be a better way!

let mut grabbed_cursor = false;
let start = Instant::now();

event_loop.run(move |event, _, control_flow| match event {
    Event::NewEvents(StartCause::Init) => {
        println!("StartCause::Init received in {:?}", Instant::now().duration_since(start));
    }
    Event::MainEventsCleared => {
        if !grabbed_cursor && window.set_cursor_grab(true).is_ok() {
            grabbed_cursor = true;
            println!("Grabbed cursor in {:?}", Instant::now().duration_since(start));
        }
    }

    // ...
});

Example output:

StartCause::Init received in 610ns
Grabbed cursor in 57.24222ms

@mahkoh
Copy link
Contributor

mahkoh commented Dec 5, 2021

To avoid the Wisdom of the Ancients, how are users expected to deal with this asynchronous window manager behavior?

I believe there is no way to do this at the moment.

@maroider
Copy link
Member

maroider commented Dec 5, 2021

I tried grabbing the cursor in Event::NewEvents(StartCause::Init)

Grabbing the cursor upon application startup without any user interaction sounds a bit iffy to me in general (ie. I wouldn't want an application to do that).

If I'm reading the protocol spec correctly, then you can't grab the pointer until the cursor enters the region you're trying to confine the cursor to. I'd recommend grabbing the cursor in response to WindowEvent::CursorEntered, WindowEvent::CursorMoved, or WindowEvent::MouseInput, since you should (to my knowledge) only receive these when the cursor is on top of your window (which should also mean that the window is mapped). WindowEvent::Focused(true) might also work, but I wouldn't count on it working universally.

@parasyte
Copy link

parasyte commented Dec 5, 2021

I agree in general. The reason I started looking into this is that the error was mentioned in the Rust discord, and I got curious.

It seems like this should really only be a concern for prototyping. A real game is expected to have a main menu and stuff that the user will interact with before the cursor is captured.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B - bug Dang, that shouldn't have happened C - needs investigation Issue must be confirmed and researched DS - x11
Development

No branches or pull requests

4 participants