rdev icon indicating copy to clipboard operation
rdev copied to clipboard

`grab` simulates Enter keypresses on linux x11

Open JakeSaphhire opened this issue 2 years ago • 4 comments

Running grab correctly captures KeyEvents globally but it also simulates Enter keypresses globally despite no instructions to do so. Here's the minimum example to reproduce this.

use rdev::{grab, Event, EventType, Key};
use std::process;


fn main() {
    println!("Hello, world!");
    if let Err(error) = grab(callback) {
        println!("Error: {:?}", error)
    }
    
}

fn callback(event: Event) -> Option<Event> {
    match event.event_type {
        EventType::KeyPress(Key::Escape) => {process::exit(1); None},
        EventType::KeyPress(key) => {println!("Keypressed: {:?}", key); None},
        _ => Some(event),
    }
}

With Linux 6.1.12-arch1-1 rustc 1.60.0 (7737e0b5c 2022-04-04)

JakeSaphhire avatar Feb 18 '23 17:02 JakeSaphhire

Not sure I understand. You mean the Enter keypress is not ignored ? (Your code is capturing Escape, not Enter, is that it ?)

Narsil avatar Feb 18 '23 18:02 Narsil

Hello and thanks for the speedy response :)

The problem is that basically the grab function works and it correctly captures and registers keyboard events (including pressing the Esc key to close the program) but everytime the grab function runs and matches an Event, it sends an Enter keypress. You can see side effects of that Enter in this video (terminal scrolling, google searching again, firefox reloading etc.)

2023-02-18 15-12-21

JakeSaphhire avatar Feb 18 '23 20:02 JakeSaphhire

The problem is that you're using std::process::exit which kills the process without letting it clean up, meaning the end state is most likely UB.

One solution would be something like that:

use rdev::{grab, Event, EventType, Key};
use std::process;

fn main() {
    println!("Hello, world!");
    if let Err(error) = grab(callback) {
        println!("Error: {:?}", error)
    }
}

static mut STOP: bool = true;

fn callback(event: Event) -> Option<Event> {
    unsafe {
        println!("Stop {:?}", STOP);
        match (STOP, event.event_type) {
            (false, key) => {
                println!("Keypressed through: {:?}", key);
                Some(event)
            }
            (true, EventType::KeyPress(Key::Escape)) => {
                // process::exit(1);
                STOP = false;
                None
            }
            (true, EventType::KeyPress(key)) => {
                println!("Keypressed: {:?}", key);
                None
            }
            _ => Some(event),
        }
    }
}

If you want to actualy kill the process you need to find a way to do a proper keyboard interrupt or similar.

Narsil avatar Feb 19 '23 12:02 Narsil

I had the same problem: the state of the devices is kept at startup (or something like that). A workaround is to wait until the Enter key is released before starting the grab. An easy check :

sleep 0.5 ; sudo ./target/debug/psylle

I use this workaround here : https://github.com/jersou/mouse-actions/blob/7bd717d32408d1b836e031531f1d051b51957e04/src/main.rs#L33

jersou avatar Apr 07 '23 22:04 jersou