From 0e34a4591fbb963ec92a359b0a0864fcc847704b Mon Sep 17 00:00:00 2001 From: Alexander Barker Date: Tue, 11 Jul 2023 22:45:11 -0700 Subject: [PATCH] Distinguish emulated input and user input. Fixes #110 --- demo/demo_hook.c | 2 +- include/uiohook.h | 6 ++-- src/darwin/dispatch_event.c | 68 +++++++++++++++++++----------------- src/windows/dispatch_event.c | 20 +++++------ src/x11/dispatch_event.c | 64 +++++++++++++++++---------------- 5 files changed, 85 insertions(+), 75 deletions(-) diff --git a/demo/demo_hook.c b/demo/demo_hook.c index 128ebf68..c852c2a4 100644 --- a/demo/demo_hook.c +++ b/demo/demo_hook.c @@ -59,7 +59,7 @@ static void logger(unsigned int level, const char *format, ...) { void dispatch_proc(uiohook_event * const event, void *user_data) { char buffer[256] = { 0 }; size_t length = snprintf(buffer, sizeof(buffer), - "id=%i,when=%" PRIu64 ",mask=0x%X", + "id=%i,when=%" PRIu64 ",mask=0x%X", event->type, event->time, event->mask); switch (event->type) { diff --git a/include/uiohook.h b/include/uiohook.h index ccd90027..49856805 100644 --- a/include/uiohook.h +++ b/include/uiohook.h @@ -117,8 +117,7 @@ typedef struct _mouse_wheel_event_data { typedef struct _uiohook_event { event_type type; uint64_t time; - uint16_t mask; - uint16_t reserved; + uint32_t mask; union { keyboard_event_data keyboard; mouse_event_data mouse; @@ -453,6 +452,9 @@ typedef void (*dispatcher_t)(uiohook_event * const, void *); #define MASK_NUM_LOCK 1 << 13 #define MASK_CAPS_LOCK 1 << 14 #define MASK_SCROLL_LOCK 1 << 15 + +#define MASK_EMULATED 1 << 30 +#define MASK_CONSUMED 1 << 31 /* End Virtual Modifier Masks */ diff --git a/src/darwin/dispatch_event.c b/src/darwin/dispatch_event.c index 3851d35c..f7f5c015 100644 --- a/src/darwin/dispatch_event.c +++ b/src/darwin/dispatch_event.c @@ -74,14 +74,12 @@ bool dispatch_hook_enabled(uint64_t timestamp) { // Populate the hook start event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - uio_event.type = EVENT_HOOK_ENABLED; uio_event.mask = 0x00; // Fire the hook start event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -91,8 +89,6 @@ bool dispatch_hook_disabled(uint64_t timestamp) { // Populate the hook stop event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - uio_event.type = EVENT_HOOK_DISABLED; uio_event.mask = 0x00; @@ -101,7 +97,7 @@ bool dispatch_hook_disabled(uint64_t timestamp) { // Deinitialize native input helper functions. unload_input_helper(); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -113,10 +109,11 @@ bool dispatch_key_press(uint64_t timestamp, CGEventRef event_ref) { // Populate key pressed event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - uio_event.type = EVENT_KEY_PRESSED; uio_event.mask = get_modifiers(); + if (CGEventGetIntegerValueField(event_ref, kCGEventSourceUnixProcessID)) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.keyboard.keycode = keycode_to_scancode(keycode); uio_event.data.keyboard.rawcode = keycode; @@ -128,7 +125,7 @@ bool dispatch_key_press(uint64_t timestamp, CGEventRef event_ref) { // Fire key pressed event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; // If the pressed event was not consumed... if (!consumed) { @@ -138,10 +135,11 @@ bool dispatch_key_press(uint64_t timestamp, CGEventRef event_ref) { for (unsigned int i = 0; i < length; i++) { // Populate key typed event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - uio_event.type = EVENT_KEY_TYPED; uio_event.mask = get_modifiers(); + if (CGEventGetIntegerValueField(event_ref, kCGEventSourceUnixProcessID)) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.keyboard.keycode = VC_UNDEFINED; uio_event.data.keyboard.rawcode = keycode; @@ -154,7 +152,7 @@ bool dispatch_key_press(uint64_t timestamp, CGEventRef event_ref) { // Populate key typed event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; } } @@ -168,10 +166,11 @@ bool dispatch_key_release(uint64_t timestamp, CGEventRef event_ref) { // Populate key released event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - uio_event.type = EVENT_KEY_RELEASED; uio_event.mask = get_modifiers(); + if (CGEventGetIntegerValueField(event_ref, kCGEventSourceUnixProcessID)) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.keyboard.keycode = keycode_to_scancode(keycode); uio_event.data.keyboard.rawcode = keycode; @@ -183,7 +182,7 @@ bool dispatch_key_release(uint64_t timestamp, CGEventRef event_ref) { // Fire key released event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -466,10 +465,11 @@ bool dispatch_button_press(uint64_t timestamp, CGEventRef event_ref, uint16_t bu // Populate mouse pressed event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - uio_event.type = EVENT_MOUSE_PRESSED; uio_event.mask = get_modifiers(); + if (CGEventGetIntegerValueField(event_ref, kCGEventSourceUnixProcessID)) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.mouse.button = button; uio_event.data.mouse.clicks = click_count; @@ -483,7 +483,7 @@ bool dispatch_button_press(uint64_t timestamp, CGEventRef event_ref, uint16_t bu // Fire mouse pressed event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -495,10 +495,11 @@ bool dispatch_button_release(uint64_t timestamp, CGEventRef event_ref, uint16_t // Populate mouse released event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - uio_event.type = EVENT_MOUSE_RELEASED; uio_event.mask = get_modifiers(); + if (CGEventGetIntegerValueField(event_ref, kCGEventSourceUnixProcessID)) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.mouse.button = button; uio_event.data.mouse.clicks = click_count; @@ -512,16 +513,17 @@ bool dispatch_button_release(uint64_t timestamp, CGEventRef event_ref, uint16_t // Fire mouse released event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; // If the pressed event was not consumed... - if (uio_event.reserved ^ 0x01 && !is_mouse_dragged()) { + if (!consumed && !is_mouse_dragged()) { // Populate mouse clicked event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - uio_event.type = EVENT_MOUSE_CLICKED; uio_event.mask = get_modifiers(); + if (CGEventGetIntegerValueField(event_ref, kCGEventSourceUnixProcessID)) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.mouse.button = button; uio_event.data.mouse.clicks = click_count; @@ -535,7 +537,7 @@ bool dispatch_button_release(uint64_t timestamp, CGEventRef event_ref, uint16_t // Fire mouse clicked event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; // TODO Should we track this flag for consumed events? + consumed = uio_event.mask & MASK_CONSUMED; } // Reset the number of clicks. @@ -559,8 +561,6 @@ bool dispatch_mouse_move(uint64_t timestamp, CGEventRef event_ref) { // Populate mouse motion event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - if (is_mouse_dragged()) { uio_event.type = EVENT_MOUSE_DRAGGED; } @@ -568,6 +568,9 @@ bool dispatch_mouse_move(uint64_t timestamp, CGEventRef event_ref) { uio_event.type = EVENT_MOUSE_MOVED; } uio_event.mask = get_modifiers(); + if (CGEventGetIntegerValueField(event_ref, kCGEventSourceUnixProcessID)) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.mouse.button = MOUSE_NOBUTTON; uio_event.data.mouse.clicks = click_count; @@ -580,14 +583,14 @@ bool dispatch_mouse_move(uint64_t timestamp, CGEventRef event_ref) { // Fire mouse motion event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } bool dispatch_mouse_wheel(uint64_t timestamp, CGEventRef event_ref) { bool consumed = false; - + // Reset the click count and previous button. click_count = 0; click_button = MOUSE_NOBUTTON; @@ -600,10 +603,11 @@ bool dispatch_mouse_wheel(uint64_t timestamp, CGEventRef event_ref) { // Populate mouse wheel event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - uio_event.type = EVENT_MOUSE_WHEEL; uio_event.mask = get_modifiers(); + if (CGEventGetIntegerValueField(event_ref, kCGEventSourceUnixProcessID)) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.wheel.x = event_point.x; uio_event.data.wheel.y = event_point.y; @@ -662,7 +666,7 @@ bool dispatch_mouse_wheel(uint64_t timestamp, CGEventRef event_ref) { // Fire mouse wheel event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; } return consumed; diff --git a/src/windows/dispatch_event.c b/src/windows/dispatch_event.c index c2385732..399dfecc 100644 --- a/src/windows/dispatch_event.c +++ b/src/windows/dispatch_event.c @@ -85,7 +85,7 @@ bool dispatch_hook_enable(uint64_t timestamp) { // Fire the hook start event. dispatch_event(&uio_event); - consumed = uio_event.mask & MASK_CONSUME; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -100,7 +100,7 @@ bool dispatch_hook_disable(uint64_t timestamp) { // Fire the hook stop event. dispatch_event(&uio_event); - consumed = uio_event.mask & MASK_CONSUME; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -139,7 +139,7 @@ bool dispatch_key_press(uint64_t timestamp, KBDLLHOOKSTRUCT *kbhook) { // Populate key pressed event. dispatch_event(&uio_event); - consumed = uio_event.mask & MASK_CONSUME; + consumed = uio_event.mask & MASK_CONSUMED; // If the pressed event was not consumed... if (!consumed) { @@ -167,7 +167,7 @@ bool dispatch_key_press(uint64_t timestamp, KBDLLHOOKSTRUCT *kbhook) { // Fire key typed event. dispatch_event(&uio_event); - consumed = uio_event.mask & MASK_CONSUME; + consumed = uio_event.mask & MASK_CONSUMED; } } @@ -208,7 +208,7 @@ bool dispatch_key_release(uint64_t timestamp, KBDLLHOOKSTRUCT *kbhook) { // Fire key released event. dispatch_event(&uio_event); - consumed = uio_event.mask & MASK_CONSUME; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -260,7 +260,7 @@ bool dispatch_button_press(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint16_t // Fire mouse pressed event. dispatch_event(&uio_event); - consumed = uio_event.mask & MASK_CONSUME; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -289,7 +289,7 @@ bool dispatch_button_release(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint16_ // Fire mouse released event. dispatch_event(&uio_event); - consumed = uio_event.mask & MASK_CONSUME; + consumed = uio_event.mask & MASK_CONSUMED; // If the pressed event was not consumed... if (!consumed && last_click.x == mshook->pt.x && last_click.y == mshook->pt.y) { @@ -313,7 +313,7 @@ bool dispatch_button_release(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint16_ // Fire mouse clicked event. dispatch_event(&uio_event); - consumed = uio_event.mask & MASK_CONSUME; + consumed = uio_event.mask & MASK_CONSUMED; } // Reset the number of clicks. @@ -366,7 +366,7 @@ bool dispatch_mouse_move(uint64_t timestamp, MSLLHOOKSTRUCT *mshook) { // Fire mouse move event. dispatch_event(&uio_event); - consumed = uio_event.mask & MASK_CONSUME; + consumed = uio_event.mask & MASK_CONSUMED; } return consumed; @@ -432,7 +432,7 @@ bool dispatch_mouse_wheel(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint8_t di // Fire mouse wheel event. dispatch_event(&uio_event); - consumed = uio_event.mask & MASK_CONSUME; + consumed = uio_event.mask & MASK_CONSUMED; } else { logger(LOG_LEVEL_WARN, "%s [%u]: SystemParametersInfo() failed, event will be consumed.\n", __FUNCTION__, __LINE__); diff --git a/src/x11/dispatch_event.c b/src/x11/dispatch_event.c index c98ad3dd..7ff49313 100644 --- a/src/x11/dispatch_event.c +++ b/src/x11/dispatch_event.c @@ -70,14 +70,12 @@ bool dispatch_hook_enabled(uint64_t timestamp) { // Populate the hook start event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - uio_event.type = EVENT_HOOK_ENABLED; uio_event.mask = 0x00; // Fire the hook start event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -87,14 +85,12 @@ bool dispatch_hook_disabled(uint64_t timestamp) { // Populate the hook stop event. uio_event.time = timestamp; - uio_event.reserved = 0x00; - uio_event.type = EVENT_HOOK_DISABLED; uio_event.mask = 0x00; // Fire the hook stop event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -124,10 +120,11 @@ bool dispatch_key_press(uint64_t timestamp, XKeyPressedEvent * const x_event) { // Populate key pressed event. uio_event.time = x_event->serial; - uio_event.reserved = 0x00; - uio_event.type = EVENT_KEY_PRESSED; uio_event.mask = get_modifiers(); + if (x_event->send_event) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.keyboard.keycode = uiocode; uio_event.data.keyboard.rawcode = keysym; @@ -139,17 +136,18 @@ bool dispatch_key_press(uint64_t timestamp, XKeyPressedEvent * const x_event) { // Fire key pressed event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; // If the pressed event was not consumed and we got a char in the buffer. if (!consumed) { for (unsigned int i = 0; i < count; i++) { // Populate key typed event. uio_event.time = x_event->serial; - uio_event.reserved = 0x00; - uio_event.type = EVENT_KEY_TYPED; uio_event.mask = get_modifiers(); + if (x_event->send_event) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.keyboard.keycode = VC_UNDEFINED; uio_event.data.keyboard.rawcode = keysym; @@ -162,7 +160,7 @@ bool dispatch_key_press(uint64_t timestamp, XKeyPressedEvent * const x_event) { // Fire key typed event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; } } @@ -193,10 +191,11 @@ bool dispatch_key_release(uint64_t timestamp, XKeyReleasedEvent * const x_event) // Populate key released event. uio_event.time = x_event->serial; - uio_event.reserved = 0x00; - uio_event.type = EVENT_KEY_RELEASED; uio_event.mask = get_modifiers(); + if (x_event->send_event) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.keyboard.keycode = uiocode; uio_event.data.keyboard.rawcode = keysym; @@ -208,7 +207,7 @@ bool dispatch_key_release(uint64_t timestamp, XKeyReleasedEvent * const x_event) // Fire key released event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -222,10 +221,11 @@ static bool dispatch_mouse_wheel_rotated(XButtonEvent * const x_event) { // Populate mouse wheel event. uio_event.time = x_event->serial; - uio_event.reserved = 0x00; - uio_event.type = EVENT_MOUSE_WHEEL; uio_event.mask = get_modifiers(); + if (x_event->send_event) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.wheel.x = x_event->x_root; uio_event.data.wheel.y = x_event->y_root; @@ -276,7 +276,7 @@ static bool dispatch_mouse_wheel_rotated(XButtonEvent * const x_event) { // Fire mouse wheel event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -341,10 +341,11 @@ static bool dispatch_mouse_button_pressed(XButtonPressedEvent * const x_event) { // Populate mouse pressed event. uio_event.time = x_event->serial; - uio_event.reserved = 0x00; - uio_event.type = EVENT_MOUSE_PRESSED; uio_event.mask = get_modifiers(); + if (x_event->send_event) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.mouse.button = x_event->button; uio_event.data.mouse.clicks = click.count; @@ -372,7 +373,7 @@ static bool dispatch_mouse_button_pressed(XButtonPressedEvent * const x_event) { // Fire mouse pressed event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -438,10 +439,11 @@ static bool dispatch_mouse_button_released(XButtonReleasedEvent * const x_event) // Populate mouse released event. uio_event.time = x_event->serial; - uio_event.reserved = 0x00; - uio_event.type = EVENT_MOUSE_RELEASED; uio_event.mask = get_modifiers(); + if (x_event->send_event) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.mouse.button = x_event->button; uio_event.data.mouse.clicks = click.count; @@ -468,7 +470,7 @@ static bool dispatch_mouse_button_released(XButtonReleasedEvent * const x_event) // Fire mouse released event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -478,10 +480,11 @@ static bool dispatch_mouse_button_clicked(XButtonEvent * const x_event) { // Populate mouse clicked event. uio_event.time = x_event->serial; - uio_event.reserved = 0x00; - uio_event.type = EVENT_MOUSE_CLICKED; uio_event.mask = get_modifiers(); + if (x_event->send_event) { + uio_event.mask |= MASK_EMULATED; + } uio_event.data.mouse.button = x_event->button; uio_event.data.mouse.clicks = click.count; @@ -508,7 +511,7 @@ static bool dispatch_mouse_button_clicked(XButtonEvent * const x_event) { // Fire mouse clicked event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_CONSUMED; return consumed; } @@ -553,9 +556,10 @@ bool dispatch_mouse_move(uint64_t timestamp, XMotionEvent * const x_event) { // Populate mouse move event. uio_event.time = x_event->serial; - uio_event.reserved = 0x00; - uio_event.mask = get_modifiers(); + if (x_event->send_event) { + uio_event.mask |= MASK_EMULATED; + } // Check the upper half of virtual modifiers for non-zero values and set the mouse // dragged flag. The last 3 bits are reserved for lock masks. @@ -593,7 +597,7 @@ bool dispatch_mouse_move(uint64_t timestamp, XMotionEvent * const x_event) { // Fire mouse move event. dispatch_event(&uio_event); - consumed = uio_event.reserved & 0x01; + consumed = uio_event.mask & MASK_EMULATED; return consumed; }