Skip to content

CursorState::Grab doesn't receive cursor positions that lie outside of the window. #133

@MaikKlein

Description

@MaikKlein
extern crate winit;

use winit::{Event, ElementState};

fn main() {
    let window = winit::WindowBuilder::new().build().unwrap();
    window.set_title("winit - Cursor grabbing test");

    let mut grabbed = false;

    for event in window.wait_events() {
        match event {
            Event::KeyboardInput(ElementState::Pressed, _, _) => {
                if grabbed {
                    grabbed = false;
                    window.set_cursor(winit::MouseCursor::Default);
                    window.set_cursor_state(winit::CursorState::Normal)
                          .ok().expect("could not ungrab mouse cursor");
                } else {
                    grabbed = true;
                    window.set_cursor(winit::MouseCursor::NoneCursor);
                    window.set_cursor_state(winit::CursorState::Grab)
                          .ok().expect("could not grab mouse cursor");
                }
            },

            Event::Closed => break,

            a @ Event::MouseMoved(_, _) => {
                println!("{:?}", a);
            },

            _ => (),
        }
    }
}

This will confine the mouse cursor within the window border. I am on Ubuntu 16.10 with X11.

Grab
[−]
Grabs the mouse cursor. The cursor's motion will be confined to this window and the window has exclusive access to further events regarding the cursor.
This is useful for first-person cameras for example.

I don't get position values that would lie outside of the window, is that expected?

Why would I want that? For a first person camera for example. You only care about the MouseDelta, so that you can rotate the camera accordingly. But if the mouse is at position (0, 0) and you move the mouse even further to the left, then it would still be at (0, 0) .

A hack would be to always reset the mouse cursor to the center of the screen after every update. The problem with this approach is that if the user moves the mouse really fast the values might get clamped.

Glfw allows this with

GLFW_CURSOR_DISABLED hides and grabs the cursor, providing virtual and unlimited cursor movement. This is useful for implementing for example 3D camera controls.

And SDL2 with https://wiki.libsdl.org/SDL_SetRelativeMouseMode Also SDL2 uses raw input ( bypasses the OS mouse speed).

Metadata

Metadata

Assignees

No one assigned

    Labels

    D - averageLikely as difficult as most tasks hereH - help wantedSomeone please save usP - normalGreat to haveS - apiDesign and usabilityS - enhancementWouldn't this be the coolest?

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions