From a887cde82b3670e6ec54d6d3ff167903988a67af Mon Sep 17 00:00:00 2001 From: Alexander Barker Date: Sun, 20 Mar 2022 01:58:08 -0700 Subject: [PATCH] Require XTest extension and remove support for XSendEvent. Fixes #123 --- CMakeLists.txt | 6 -- README.md | 1 - src/x11/post_event.c | 247 +------------------------------------------ 3 files changed, 2 insertions(+), 252 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae470f67..8a1ed49b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -210,12 +210,6 @@ if(UNIX AND NOT APPLE) add_compile_definitions(uiohook PRIVATE USE_XRECORD_ASYNC) endif() - option(USE_XTEST "XTest API (default: ON)" ON) - if(USE_XTEST) - # XTest API is provided by Xtst - add_compile_definitions(uiohook PRIVATE USE_XTEST) - endif() - if(CMAKE_SYSTEM_NAME STREQUAL "Linux") option(USE_EVDEV "Generic Linux input driver (default: ON)" ON) if(USE_EVDEV) diff --git a/README.md b/README.md index 601895d7..12d578f9 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,6 @@ $ cmake --build . --parallel 2 --target install | | USE_XRANDR:BOOL | xrandt extension | OFF | | | USE_XRECORD_ASYNC:BOOL | xrecord async api | OFF | | | USE_XT:BOOL | x toolkit extension | ON | -| | USE_XTEST:BOOL | xtest extension | ON | ## Usage * [Hook Demo](demo/demo_hook.c) diff --git a/src/x11/post_event.c b/src/x11/post_event.c index 43b2fbee..92aa2fa0 100644 --- a/src/x11/post_event.c +++ b/src/x11/post_event.c @@ -22,16 +22,11 @@ #include #include #include -#ifdef USE_XTEST #include -#endif #include "input_helper.h" #include "logger.h" -#ifndef USE_XTEST -static long current_modifier_mask = NoEventMask; -#endif static int post_key_event(uiohook_event * const event) { KeyCode keycode = scancode_to_keycode(event->data.keyboard.keycode); @@ -41,114 +36,22 @@ static int post_key_event(uiohook_event * const event) { return UIOHOOK_FAILURE; } - #ifdef USE_XTEST Bool is_pressed; - #else - long event_mask; - - XKeyEvent key_event = { - .serial = 0x00, - .time = CurrentTime, - .same_screen = True, - .send_event = False, - .display = helper_disp, - - .root = XDefaultRootWindow(helper_disp), - .window = None, - .subwindow = None, - - .x_root = 0, - .y_root = 0, - .x = 0, - .y = 0, - - .state = current_modifier_mask, - .keycode = keycode - }; - - int revert; - XGetInputFocus(helper_disp, &(key_event.window), &revert); - #endif - if (event->type == EVENT_KEY_PRESSED) { - #ifdef USE_XTEST is_pressed = True; - #else - key_event.type = KeyPress; - event_mask = KeyPressMask; - - switch (event->data.keyboard.keycode) { - case VC_SHIFT_L: - case VC_SHIFT_R: - current_modifier_mask |= ShiftMask; - break; - - case VC_CONTROL_L: - case VC_CONTROL_R: - current_modifier_mask |= ControlMask; - break; - - case VC_META_L: - case VC_META_R: - current_modifier_mask |= Mod4Mask; - break; - - case VC_ALT_L: - case VC_ALT_R: - current_modifier_mask |= Mod1Mask; - break; - } - #endif - } else if (event->type == EVENT_KEY_RELEASED) { - #ifdef USE_XTEST is_pressed = False; - #else - key_event.type = KeyRelease; - event_mask = KeyReleaseMask; - - switch (event->data.keyboard.keycode) { - case VC_SHIFT_L: - case VC_SHIFT_R: - current_modifier_mask &= ~ShiftMask; - break; - - case VC_CONTROL_L: - case VC_CONTROL_R: - current_modifier_mask &= ~ControlMask; - break; - - case VC_META_L: - case VC_META_R: - current_modifier_mask &= ~Mod4Mask; - break; - - case VC_ALT_L: - case VC_ALT_R: - current_modifier_mask &= ~Mod1Mask; - break; - } - #endif } else { logger(LOG_LEVEL_DEBUG, "%s [%u]: Invalid event for keyboard post event: %#X.\n", __FUNCTION__, __LINE__, event->type); return UIOHOOK_FAILURE; } - #ifdef USE_XTEST if (XTestFakeKeyEvent(helper_disp, keycode, is_pressed, 0) != Success) { logger(LOG_LEVEL_ERROR, "%s [%u]: XTestFakeKeyEvent() failed!\n", __FUNCTION__, __LINE__, event->type); return UIOHOOK_FAILURE; } - #else - XSelectInput(helper_disp, key_event.window, KeyPressMask | KeyReleaseMask); - if (XSendEvent(helper_disp, key_event.window, False, event_mask, (XEvent *) &key_event) == 0) { - logger(LOG_LEVEL_ERROR, "%s [%u]: XSendEvent() failed!\n", - __FUNCTION__, __LINE__, event->type); - return UIOHOOK_FAILURE; - } - #endif return UIOHOOK_SUCCESS; } @@ -176,36 +79,11 @@ static int post_mouse_button_event(uiohook_event * const event) { }; // Move the pointer to the specified position. - #ifdef USE_XTEST XTestFakeMotionEvent(btn_event.display, -1, btn_event.x, btn_event.y, 0); - #else - XWarpPointer(btn_event.display, None, btn_event.subwindow, 0, 0, 0, 0, btn_event.x, btn_event.y); - XFlush(btn_event.display); - #endif - - #ifndef USE_XTEST - // FIXME This is still not working correctly, clicking on other windows does not yield focus. - while (btn_event.subwindow != None) - { - btn_event.window = btn_event.subwindow; - XQueryPointer ( - btn_event.display, - btn_event.window, - &btn_event.root, - &btn_event.subwindow, - &btn_event.x_root, - &btn_event.y_root, - &btn_event.x, - &btn_event.y, - &btn_event.state - ); - } - #endif int status = UIOHOOK_FAILURE; switch (event->type) { case EVENT_MOUSE_PRESSED: - #ifdef USE_XTEST if (event->data.mouse.button < MOUSE_BUTTON1 || event->data.mouse.button > MOUSE_BUTTON5) { logger(LOG_LEVEL_WARN, "%s [%u]: Invalid button specified for mouse pressed event! (%u)\n", __FUNCTION__, __LINE__, event->data.mouse.button); @@ -215,34 +93,9 @@ static int post_mouse_button_event(uiohook_event * const event) { if (XTestFakeButtonEvent(helper_disp, event->data.mouse.button, True, 0) != 0) { status = UIOHOOK_SUCCESS; } - #else - if (event->data.mouse.button == MOUSE_BUTTON1) { - current_modifier_mask |= Button1MotionMask; - } else if (event->data.mouse.button == MOUSE_BUTTON2) { - current_modifier_mask |= Button2MotionMask; - } else if (event->data.mouse.button == MOUSE_BUTTON3) { - current_modifier_mask |= Button3MotionMask; - } else if (event->data.mouse.button == MOUSE_BUTTON4) { - current_modifier_mask |= Button4MotionMask; - } else if (event->data.mouse.button == MOUSE_BUTTON5) { - current_modifier_mask |= Button5MotionMask; - } else { - logger(LOG_LEVEL_WARN, "%s [%u]: Invalid button specified for mouse pressed event! (%u)\n", - __FUNCTION__, __LINE__, event->data.mouse.button); - return UIOHOOK_FAILURE; - } - - btn_event.type = ButtonPress; - btn_event.button = event->data.mouse.button; - btn_event.state = current_modifier_mask; - if (XSendEvent(helper_disp, btn_event.window, False, ButtonPressMask, (XEvent *) &btn_event) != 0) { - status = UIOHOOK_SUCCESS; - } - #endif break; case EVENT_MOUSE_RELEASED: - #ifdef USE_XTEST if (event->data.mouse.button < MOUSE_BUTTON1 || event->data.mouse.button > MOUSE_BUTTON5) { logger(LOG_LEVEL_WARN, "%s [%u]: Invalid button specified for mouse released event! (%u)\n", __FUNCTION__, __LINE__, event->data.mouse.button); @@ -252,30 +105,6 @@ static int post_mouse_button_event(uiohook_event * const event) { if (XTestFakeButtonEvent(helper_disp, event->data.mouse.button, False, 0) != 0) { status = UIOHOOK_SUCCESS; } - #else - if (event->data.mouse.button == MOUSE_BUTTON1) { - current_modifier_mask &= ~Button1MotionMask; - } else if (event->data.mouse.button == MOUSE_BUTTON2) { - current_modifier_mask &= ~Button2MotionMask; - } else if (event->data.mouse.button == MOUSE_BUTTON3) { - current_modifier_mask &= ~Button3MotionMask; - } else if (event->data.mouse.button == MOUSE_BUTTON4) { - current_modifier_mask &= ~Button4MotionMask; - } else if (event->data.mouse.button == MOUSE_BUTTON5) { - current_modifier_mask &= ~Button5MotionMask; - } else { - logger(LOG_LEVEL_WARN, "%s [%u]: Invalid button specified for mouse released event! (%u)\n", - __FUNCTION__, __LINE__, event->data.mouse.button); - return UIOHOOK_FAILURE; - } - - btn_event.type = ButtonRelease; - btn_event.button = event->data.mouse.button; - btn_event.state = current_modifier_mask; - if (XSendEvent(helper_disp, btn_event.window, False, ButtonReleaseMask, (XEvent *) &btn_event) != 0) { - status = UIOHOOK_SUCCESS; - } - #endif break; default: @@ -311,55 +140,16 @@ static int post_mouse_wheel_event(uiohook_event * const event) { .same_screen = True }; - #ifndef USE_XTEST - // FIXME This is still not working correctly, clicking on other windows does not yield focus. - while (btn_event.subwindow != None) - { - btn_event.window = btn_event.subwindow; - XQueryPointer ( - btn_event.display, - btn_event.window, - &btn_event.root, - &btn_event.subwindow, - &btn_event.x_root, - &btn_event.y_root, - &btn_event.x, - &btn_event.y, - &btn_event.state - ); - } - #endif - // Wheel events should be the same as click events on X11. // type, amount and rotation unsigned int button = button_map_lookup(event->data.wheel.rotation < 0 ? WheelUp : WheelDown); - #ifdef USE_XTEST if (XTestFakeButtonEvent(helper_disp, button, True, 0) != 0) { status = UIOHOOK_SUCCESS; } - #else - btn_event.type = ButtonPress; - btn_event.button = button; - btn_event.state = current_modifier_mask; - if (XSendEvent(helper_disp, btn_event.window, False, ButtonPressMask, (XEvent *) &btn_event) != 0) { - status = UIOHOOK_SUCCESS; - } - #endif - if (status == UIOHOOK_SUCCESS) { - #ifdef USE_XTEST - if (XTestFakeButtonEvent(helper_disp, button, False, 0) == 0) { - status = UIOHOOK_FAILURE; - } - #else - btn_event.type = ButtonRelease; - btn_event.button = button; - btn_event.state = current_modifier_mask; - if (XSendEvent(helper_disp, btn_event.window, False, ButtonReleaseMask, (XEvent *) &btn_event) == 0) { - status = UIOHOOK_FAILURE; - } - #endif + if (status == UIOHOOK_SUCCESS && XTestFakeButtonEvent(helper_disp, button, False, 0) == 0) { + status = UIOHOOK_FAILURE; } return UIOHOOK_SUCCESS; @@ -368,42 +158,9 @@ static int post_mouse_wheel_event(uiohook_event * const event) { static int post_mouse_motion_event(uiohook_event * const event) { int status = UIOHOOK_FAILURE; - #ifdef USE_XTEST if (XTestFakeMotionEvent(helper_disp, -1, event->data.mouse.x, event->data.mouse.y, 0) != 0) { status = UIOHOOK_SUCCESS; } - #else - XMotionEvent mov_event = { - .type = MotionNotify, - .serial = 0, - .send_event = False, - .display = helper_disp, - - .window = None, /* “event” window it is reported relative to */ - .root = XDefaultRootWindow(helper_disp), /* root window that the event occurred on */ - .subwindow = None, /* child window */ - - .time = CurrentTime, - - .x = event->data.mouse.x, /* pointer x, y coordinates in event window */ - .y = event->data.mouse.y, - - .x_root = event->data.mouse.x, /* coordinates relative to root */ - .y_root = event->data.mouse.x, - - .state = current_modifier_mask | MotionNotify, /* key or button mask */ - - .is_hint = NotifyNormal, - .same_screen = True - }; - - int revert; - XGetInputFocus(helper_disp, &(mov_event.window), &revert); - - if (XSendEvent(helper_disp, mov_event.window, False, mov_event.state, (XEvent *) &mov_event) != 0) { - status = UIOHOOK_SUCCESS; - } - #endif return status; }