Search code examples
rustglut

Glutin on Rust: How do I passively track my mouse movement and position?


I want to track my cursor position as I work through my day to generate an artistic heat-map later.

To aggregate the data, I've pulled in glutin at version 0.29.1 and setup my loop with event matchers that tell me when I move my mouse and where.

The problem I have is that I want this aggregation to continue to work when I don't have the window focused. In the past, with other frameworks, I've been able to get around this kind of limitation by setting a maximized transparent window to always sit on top of all windows, but this hasn't worked for me.

How do I passively track my mouse movement and position with glutin (or another framework, preferably cross-platform so I don't have to dig into lower level apis with more obscure documentation)?

let event_loop = EventLoop::new();
let _window = WindowBuilder::new()
    .with_decorations(false)
    .with_maximized(true)
    .with_always_on_top(true)
    .with_transparent(true)
    .build(&event_loop);

event_loop.run(move |event, _, _control_flow| match event {
    Event::WindowEvent { event, .. } => match event {
        WindowEvent::CursorMoved {
            device_id,
            position,
            modifiers: _,
        } => {
            println!("{:?} {:?}", device_id, position);
        }
        WindowEvent::Focused(is_focused) => {
            println!("focused::{}", is_focused);
        }
        _ => {}
    },
    Event::DeviceEvent { device_id, event } => match event {
        DeviceEvent::MouseMotion { delta } => {
            println!("{:?} {:?}", device_id, delta);
        }
        _ => {}
    },
    _ => {}
});

Solution

  • I was trying to hammer a square-peg into a round hole by forcing my usage of glutin to learn more along the lines of game-development. This is made trivial by using a more appropriate tool.

    [dependencies]
    device_query = "1.1.1"
    
    use device_query::{DeviceState, DeviceEvents};
    
    fn main() {
        let device_state = DeviceState::new();
        loop {
            let mouse_state = device_state.get_mouse();
            println!("{:?}", mouse_state.coords);
        }
    }
    

    [Edit] or as recommended in the comments with a less resource intense callback, and an additional dependency on ctrlc = "3.2.3" to hold the application open indefinitely.

    use device_query::{DeviceState, DeviceEvents};
    use std::sync::mpsc::channel;
    use ctrlc;
    
    fn main() {
        let device_state = DeviceState::new();
        let _guard = device_state.on_mouse_move(|position| {
            println!("{:?}", position);
        });
    
        let (tx, rx) = channel();
        ctrlc::set_handler(move || tx.send(()).expect("Could not send signal on channel."))
            .expect("Error setting Ctrl-C handler");
        rx.recv().expect("Could not receive from channel.");
    }