enigo-rs / enigo

Cross platform input simulation in Rust
MIT License
1.08k stars 107 forks source link

Inconsitency in number handling between Linux and Windows (or lacks of documentation to this behavior) #308

Open rgiot opened 2 months ago

rgiot commented 2 months ago

Describe the bug Windows does not seem to be able to generate key events for numbers (but also for other chars).

To Reproduce This minimal example illustrates the issue.

#!/usr/bin/env rust-script

//! ```cargo
//! [dependencies]
//! enigo = "0.2.1"
//! ```

use std::time::Duration;

use enigo::{Enigo, Key, Keyboard, Settings};

fn main() {
    std::thread::sleep(Duration::from_millis(1000));
    let mut enigo = Enigo::new(&Settings::default()).unwrap();
    enigo.key(Key::Unicode('#'), enigo::Direction::Click).unwrap();
    enigo.key(Key::Unicode('0'), enigo::Direction::Click).unwrap();
    enigo.key(Key::Return, enigo::Direction::Click).unwrap();
}

Expected behavior When launched with Linux, the following output is obtained:

$ rust-script test_enigo.rs 
#0

Obtained behavior When launched with Windows, the following output is obtained:

> rust-script.exe .\test_enigo.rs
thread 'main' panicked at XXX\test_enigo.rs:16:59:
called `Result::unwrap()` on an `Err` value: Mapping("Could not translate the character to the corresponding virtual-key code and shift state for the current keyboard")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

The problem comes at least from enigo.key(Key::Unicode('0'), enigo::Direction::Click).unwrap();, but in this example # is problematic too (hence the line 16 reported).

Environment (please complete the following information):

Additional context

I do not understand why there is this faulty behavior on Windows. Either there is a bug in the library, either this is a known limitation. In that case, what are the workarounds ?

rgiot commented 2 months ago

Note that replacing the two lines

    enigo.key(Key::Unicode('#'), enigo::Direction::Click).unwrap();
    enigo.key(Key::Unicode('0'), enigo::Direction::Click).unwrap();

by

 enigo.text("#0").unwrap();

solves the issue

UE2020 commented 2 months ago

Is this new in 0.2.1? This worked fine for me under 0.2.0, haven't tested on 0.2.1 yet.

rgiot commented 2 months ago

I have slightly modified the script to use enigo 0.2.0 and do not try to press # anymore.

That still provides the issue. Here is the full compilation/Execution log

rust-script.exe -c -f --clear-cache .\test_enigo.rs
    Updating crates.io index
     Locking 39 packages to latest compatible versions
      Adding bitflags v1.3.2 (latest: v2.6.0)
      Adding block2 v0.4.0 (latest: v0.5.1)
      Adding core-foundation v0.9.4 (latest: v0.10.0)
      Adding core-graphics v0.23.2 (latest: v0.24.0)
      Adding core-graphics-types v0.1.3 (latest: v0.2.0)
      Adding enigo v0.2.0 (latest: v0.2.1)
      Adding memmap2 v0.8.0 (latest: v0.9.4)
      Adding windows v0.56.0 (latest: v0.58.0)
      Adding windows-core v0.56.0 (latest: v0.58.0)
      Adding windows-implement v0.56.0 (latest: v0.58.0)
      Adding windows-interface v0.56.0 (latest: v0.58.0)
      Adding windows-result v0.1.2 (latest: v0.2.0)
      Adding xkbcommon v0.7.0 (latest: v0.8.0)
   Compiling proc-macro2 v1.0.86
   Compiling unicode-ident v1.0.12
   Compiling windows_x86_64_msvc v0.52.6
   Compiling log v0.4.22
   Compiling windows-targets v0.52.6
   Compiling windows-result v0.1.2
   Compiling quote v1.0.36
   Compiling syn v2.0.75
   Compiling windows-interface v0.56.0
   Compiling windows-implement v0.56.0
   Compiling windows-core v0.56.0
   Compiling windows v0.56.0
   Compiling enigo v0.2.0
   Compiling test_enigo_8500f6e26eb785e853a9c968 v0.1.0 (C:\Users\giotr\AppData\Local\rust-script\projects\8500f6e26eb785e853a9c968)
    Finished `release` profile [optimized] target(s) in 10.90s
thread 'main' panicked at C:\Users\giotr\Perso\CPC\rust.cpcdemotools\cpclib-emucontrol\tests\.\test_enigo.rs:17:59:
called `Result::unwrap()` on an `Err` value: Mapping("Could not translate the character to the corresponding virtual-key code and shift state for the current keyboard")
stack backtrace:
   0: std::panicking::begin_panic_handler
             at /rustc/fda509e817abeeecb5b76bc1de844f355675c81e/library\std\src\panicking.rs:661
   1: core::panicking::panic_fmt
             at /rustc/fda509e817abeeecb5b76bc1de844f355675c81e/library\core\src\panicking.rs:74
   2: core::result::unwrap_failed
             at /rustc/fda509e817abeeecb5b76bc1de844f355675c81e/library\core\src\result.rs:1679
   3: __ImageBase
   4: __ImageBase
   5: __ImageBase
   6: std::rt::lang_start_internal
             at /rustc/fda509e817abeeecb5b76bc1de844f355675c81e/library\std\src\rt.rs:141
   7: main
   8: invoke_main
             at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
   9: __scrt_common_main_seh
             at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
  10: BaseThreadInitThunk
  11: RtlUserThreadStart
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
pentamassiv commented 2 months ago

This is related to the PR https://github.com/enigo-rs/enigo/pull/285. When you want to enter text, you should always use the text() method. It is also faster in some platforms than entering individual keys, because some of the protocols allow entering strings.

That said, I definitely need to improve the behavior of Key::Unicode and improve it's documentation. Right now it is confusing and inconsistent

rgiot commented 2 months ago

Thanks for the feedback. My use case is not trivial, as I am trying to control the emulator of an oldschool machine; so text typing may not be always the solution. I'll follow the updates of the library to see how to handle that use case properly on windows in the future

pentamassiv commented 2 months ago

👍 Interesting project!