SnosMe/uiohook-napi

Missing keypress

michelvermeulen opened this issue · 11 comments

Hi!

Thanks for working on this. One thing I'm missing from the original iohook implementation is the keypress event which contains a "keychar" property that allows to transform a keycode into its matching key. I tried using the UiohookKey import but it doesn't work with the / key for instance (52 vs 53).

Do you have any insight on this?

I intentionally don't expose this in events, interpreting keycodes into actual characters according to KB layout is gray area of keyloggers. Adding them back is really trivial, you can do it in fork.

Hi Snos. Thanks for your reply. Still struggling with that, and I have no idea how to add them back although it looks really trivial. Could you help me out here?

Here I'm exposing only keycode

napi_value e_keycode;
status = napi_create_uint32(env, event->data.keyboard.keycode, &e_keycode);

But you can add another js property with keychar

https://github.com/kwhat/libuiohook/blob/d60dc93e510c35cac8c09dcc982bbb55aad59222/include/uiohook.h#L91

You may also need to uncomment this

// case EVENT_KEY_TYPED:

Thanks a lot! I'll try to get by with that info, I'm really not familiar with C so I'll fiddle around. Thanks again, I'll reach back if I can't work this out, happy to sponsor you at a personal level if I need more help :)

I guess I'll have to rebuild it to see changes after I change the source files?

Alright @SnosMe, I'm almost there. I added the keychar, but the value is different from what ioHook sends (ioHook sends 113 for q on my keyboard while uiohook always sends 65535.

This is what I added:

napi_value e_keychar;
status = napi_create_uint32(env, event->data.keyboard.keychar, &e_keychar);
NAPI_FATAL_IF_FAILED(status, "uiohook_to_js_event", "napi_create_uint32");

If you uncommented line I've mentioned,
and added new if block with that event type, then idk

if (event->type == EVENT_KEY_PRESSED || event->type == EVENT_KEY_RELEASED) {

Oh, also if you apply my patch I remove that code for some reason 😅

// If the pressed event was not consumed...
if (event.reserved ^ 0x01) {
- // Buffer for unicode typed chars. No more than 2 needed.
- WCHAR buffer[2]; // = { WCH_NONE };
-
- // If the pressed event was not consumed and a unicode char exists...
- SIZE_T count = keycode_to_unicode(kbhook->vkCode, buffer, sizeof(buffer));
- for (unsigned int i = 0; i < count; i++) {
- // Populate key typed event.
- event.time = kbhook->time;
- event.reserved = 0x00;
-
- event.type = EVENT_KEY_TYPED;
- event.mask = get_modifiers();
-
- event.data.keyboard.keycode = VC_UNDEFINED;
- event.data.keyboard.rawcode = (uint16_t) kbhook->vkCode;
- event.data.keyboard.keychar = buffer[i];
-
- logger(LOG_LEVEL_DEBUG, "%s [%u]: Key %#X typed. (%lc)\n",
- __FUNCTION__, __LINE__, event.data.keyboard.keycode, (wint_t) event.data.keyboard.keychar);
-
- // Fire key typed event.
- dispatch_event(&event);
- }
}
}

I actually don't have the patch. I did everything yes, I do have warnings when doing node-gyp build:

  CC(target) Release/obj.target/uiohook_napi/src/lib/addon.o
../src/lib/addon.c:305:53: warning: passing 'int32_t *' (aka 'int *') to parameter of type 'uint32_t *' (aka 'unsigned int *') converts between pointers to integer types with different sign [-Wpointer-sign]
  status = napi_get_value_uint32(env, info_argv[1], (int32_t*)&tap_type);
                                                    ^~~~~~~~~~~~~~~~~~~
/Users/michel/Library/Caches/node-gyp/18.12.1/include/node/js_native_api.h:140:68: note: passing argument to parameter 'result' here
                                                         uint32_t* result);

What's weird is the keychar is always the same value no matter which key I press: 65535

Alright, trying to help here, but I saw CHAR_UNDEFINED in some of the source files:

CleanShot 2022-12-05 at 21 58 17

If I change this value to a fixed number, it works, BUT I don't know how to get the keychar there :|

from this code it looks like keycode and keychar are swapped on macOS in uiohook 😄
or is it you changing code to debug it