Robotjs: typeString() and keyTap() slow even with 1ms delay

Created on 10 Dec 2019  路  22Comments  路  Source: octalmage/robotjs

robot.setKeyboardDelay(1); robot.typeString('*cough');

is much slower than having *cough set in the clipboard and doing

robot.keyToggle('control','down') robot.keyTap('v');

I think it could be the blocking nature of the module, and the fact that my PC is very slow.

Most helpful comment

https://github.com/octalmage/robotjs/blob/master/src/keypress.c#L17

#if defined(IS_WINDOWS)
    #define WIN32_KEY_EVENT_WAIT(key, flags) \
        (win32KeyEvent(key, flags), Sleep(DEADBEEF_RANDRANGE(63, 125)))
#elif defined(USE_X11)
    #define X_KEY_EVENT(display, key, is_press) \
        (XTestFakeKeyEvent(display, \
                           XKeysymToKeycode(display, key), \
                           is_press, CurrentTime), \
         XSync(display, false))
    #define X_KEY_EVENT_WAIT(display, key, is_press) \
        (X_KEY_EVENT(display, key, is_press), \
         microsleep(DEADBEEF_UNIFORM(62.5, 125.0)))
#endif

tapKey uses toggleKeyCode which calls WIN32_KEY_EVENT_WAIT once for a key and twice for a key with modifiers and therefore it can generate an additional delay of max 250ms.
i dunno why there is a extra sleep call. i forked the repository and removed it and it works fine.
< 2ms per call instead of 300ms +

All 22 comments

I'm having the same issue too. I also notice I'm getting Invalid MIT-MAGIC-COOKIE-1 key in the terminal as soon as the typing occurs.

I am seeing the same thing. Typing 'Hello World' takes around 2.4 seconds where I would expect it to take around 11ms with a 1ms delay set with setKeyboardDelay.

// test.js
var robot = require("robotjs");
robot.setKeyboardDelay(1)
robot.typeString("Hello World");
$ time node test.js 
Hello World
real    0m2.429s
user    0m0.025s
sys     0m0.017s

I am on Linux if that makes a difference.

https://github.com/octalmage/robotjs/blob/master/src/keypress.c#L17

#if defined(IS_WINDOWS)
    #define WIN32_KEY_EVENT_WAIT(key, flags) \
        (win32KeyEvent(key, flags), Sleep(DEADBEEF_RANDRANGE(63, 125)))
#elif defined(USE_X11)
    #define X_KEY_EVENT(display, key, is_press) \
        (XTestFakeKeyEvent(display, \
                           XKeysymToKeycode(display, key), \
                           is_press, CurrentTime), \
         XSync(display, false))
    #define X_KEY_EVENT_WAIT(display, key, is_press) \
        (X_KEY_EVENT(display, key, is_press), \
         microsleep(DEADBEEF_UNIFORM(62.5, 125.0)))
#endif

tapKey uses toggleKeyCode which calls WIN32_KEY_EVENT_WAIT once for a key and twice for a key with modifiers and therefore it can generate an additional delay of max 250ms.
i dunno why there is a extra sleep call. i forked the repository and removed it and it works fine.
< 2ms per call instead of 300ms +

Interesting, that doesn't explain the delays on Linux though, which I would expect to correspond to the block under defined(USE_X11) . Could it be the XSync line?

It uses X_KEY_EVENT_WAIT on linux and therefore the sleep is the same as on windows.

ah gotcha, looking at the file now. this seems deliberate -- i wonder what its trying to achieve?

i suppose a next step would be for me to fork and compile the repo with that code edited out and see what effect it has. i will give that a shot when i can.

Just edited out the delay and recompiled; everything seems to work as expected again.

@Kyusung4698 would you make a PR with this change?
Thank you!!!!

A problem arises when you remove the delay on windows is that button presses on same button can get lost. Example you send 11-222-333 with typestring and only see 1-2-3 on screen.

Solution is quite simple (Just send a keyup event as well): https://github.com/tillbaks/robotjs/commit/0ac7be2878b887e25485311846dbe2b3411f384a

  • Anybody know what the MIT-MAGIC-COOKIE-1 thing is?
  • The title should be changed to "Linux/Windows"... Im having the issue in Ubuntu LTS
  • The master branch silently breaks typing on linux all together! :(
  • #530 should be closed. duplicate
  • #559 should be closed as it doesn't address the root cause. That said, removing deadbeef is a quick fix for linux... it does break the sleep option and makes it type super fast.

@rayfoss do you think typing super fast is a downside?
In our case we are creating a remote desktop application and using robotjs for automate the user interaction, so typing as fast as possible (as similar to remote endpoint) is crucial for us.

@ricardopolo sometimes I want to hide the fact that I'm using a bot. Typing impossibly fast is a dead giveaway. That said, typeString isn't designed to be slow... typeStringDelayed is. Everything looks great with #560 ...

```javascript

// 杈撳叆瀛楃
async function string(str) {
await copyString(str);
await tap('v', 'control');
await sleep(20);
}

https://github.com/octalmage/robotjs/blob/master/src/keypress.c#L17

#if defined(IS_WINDOWS)
  #define WIN32_KEY_EVENT_WAIT(key, flags) \
      (win32KeyEvent(key, flags), Sleep(DEADBEEF_RANDRANGE(63, 125)))
#elif defined(USE_X11)
  #define X_KEY_EVENT(display, key, is_press) \
      (XTestFakeKeyEvent(display, \
                         XKeysymToKeycode(display, key), \
                         is_press, CurrentTime), \
       XSync(display, false))
  #define X_KEY_EVENT_WAIT(display, key, is_press) \
      (X_KEY_EVENT(display, key, is_press), \
       microsleep(DEADBEEF_UNIFORM(62.5, 125.0)))
#endif

tapKey uses toggleKeyCode which calls WIN32_KEY_EVENT_WAIT once for a key and twice for a key with modifiers and therefore it can generate an additional delay of max 250ms.
i dunno why there is a extra sleep call. i forked the repository and removed it and it works fine.
< 2ms per call instead of 300ms +

Is there any way I can make this locally? I'm using the latest version (0.6.0) but it still occurs.

@lucasguaru You could always try to patch it with patch-package if you need to have it fixed locally.

@octalmage would you accept a PR that made this configurable? E.g.:

robot.setUseRandomDelay(false);  // New option; defaults to true (backwards compat)

The implementation being something like

    #define WIN32_KEY_EVENT_WAIT(key, flags) \
        (win32KeyEvent(key, flags), Sleep(useRandomDelay ? DEADBEEF_RANDRANGE(63, 125) : 0))

If so I can work on it.

It's worth noting that this "random delay" behavior is not present/implemented on macOS/OSX. It's only present on Windows and Linux, from the looks of the code (and comments above).

Oh! I see this is actually fixed on master (via https://github.com/octalmage/robotjs/pull/560). But @octalmage @oktapodia it's not updated on npm?

Is this project still active? Why is this not fixed in the final version?

Note to others with this issue, installing directly from git seems to work:

npm install git+https://github.com/octalmage/robotjs.git

(This is undesirable because, in general, the git source is not necessarily the same as the npm package contents. Also because it doesn't specify a version constraint. But it's better than nothing and in this case seems to work ...)

Hey guys,

Thanks for the workaround, I tried on my end to install from GH but I get an error I didn't get with the NPM version:

 The module robotjs.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION 83. This version of Node.js requires
NODE_MODULE_VERSION 85

I did try npm rebuild, npm rebuild --build-from-source and npm rebuild robotjs --update-binary but same thing.

Any idea what I'm doing wrong?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vnsharma-systango picture vnsharma-systango  路  9Comments

tms1337 picture tms1337  路  4Comments

piyushpatil027 picture piyushpatil027  路  3Comments

Glutch picture Glutch  路  6Comments

saghul picture saghul  路  6Comments