int main() { // Disable the logger. hook_set_logger_proc(&logger_proc); // Retrieves the keyboard auto repeat rate. long int repeat_rate = hook_get_auto_repeat_rate(); if (repeat_rate >= 0) { fprintf(stdout, "Auto Repeat Rate:\t%ld\n", repeat_rate); } else { fprintf(stderr, "Failed to aquire keyboard auto repeat rate!\n"); } // Retrieves the keyboard auto repeat delay. long int repeat_delay = hook_get_auto_repeat_delay(); if (repeat_delay >= 0) { fprintf(stdout, "Auto Repeat Delay:\t%ld\n", repeat_delay); } else { fprintf(stderr, "Failed to acquire keyboard auto repeat delay!\n"); } // Retrieves the mouse acceleration multiplier. long int acceleration_multiplier = hook_get_pointer_acceleration_multiplier(); if (acceleration_multiplier >= 0) { fprintf(stdout, "Mouse Acceleration Multiplier:\t%ld\n", acceleration_multiplier); } else { fprintf(stderr, "Failed to acquire mouse acceleration multiplier!\n"); } // Retrieves the mouse acceleration threshold. long int acceleration_threshold = hook_get_pointer_acceleration_threshold(); if (acceleration_threshold >= 0) { fprintf(stdout, "Mouse Acceleration Threshold:\t%ld\n", acceleration_threshold); } else { fprintf(stderr, "Failed to acquire mouse acceleration threshold!\n"); } // Retrieves the mouse sensitivity. long int sensitivity = hook_get_pointer_sensitivity(); if (sensitivity >= 0) { fprintf(stdout, "Mouse Sensitivity:\t%ld\n", sensitivity); } else { fprintf(stderr, "Failed to acquire keyboard auto repeat rate!\n"); } // Retrieves the double/triple click interval. long int click_time = hook_get_multi_click_time(); if (click_time >= 0) { fprintf(stdout, "Multi-Click Time:\t%ld\n", click_time); } else { fprintf(stderr, "Failed to acquire keyboard auto repeat rate!\n"); } return EXIT_SUCCESS; }
static char * test_multi_click_time() { long int i = hook_get_multi_click_time(); fprintf(stdout, "Multi click time: %li\n", i); mu_assert("error, could not determine multi click time", i >= 0); return NULL; }
static void process_button_released(MSLLHOOKSTRUCT *mshook, uint16_t button) { // Populate mouse released event. event.time = GetMessageTime(); event.reserved = 0x00; event.type = EVENT_MOUSE_RELEASED; event.mask = get_modifiers(); event.data.mouse.button = button; event.data.mouse.clicks = click_count; event.data.mouse.x = mshook->pt.x; event.data.mouse.y = mshook->pt.y; logger(LOG_LEVEL_INFO, "%s [%u]: Button %u released %u time(s). (%u, %u)\n", __FUNCTION__, __LINE__, event.data.mouse.button, event.data.mouse.clicks, event.data.mouse.x, event.data.mouse.y); // Fire mouse released event. dispatch_event(&event); // If the pressed event was not consumed... if (event.reserved ^ 0x01 && last_click.x == mshook->pt.x && last_click.y == mshook->pt.y) { // Populate mouse clicked event. event.time = GetMessageTime(); event.reserved = 0x00; event.type = EVENT_MOUSE_CLICKED; event.mask = get_modifiers(); event.data.mouse.button = button; event.data.mouse.clicks = click_count; event.data.mouse.x = mshook->pt.x; event.data.mouse.y = mshook->pt.y; logger(LOG_LEVEL_INFO, "%s [%u]: Button %u clicked %u time(s). (%u, %u)\n", __FUNCTION__, __LINE__, event.data.mouse.button, event.data.mouse.clicks, event.data.mouse.x, event.data.mouse.y); // Fire mouse clicked event. dispatch_event(&event); } // Reset the number of clicks. if (button == click_button && (long int) (event.time - click_time) > hook_get_multi_click_time()) { // Reset the click count. click_count = 0; } }
static __inline void process_button_pressed(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint16_t button) { if (!wants_to_hook_event(EVENT_MOUSE_PRESSED)) return; // Track the number of clicks, the button must match the previous button. if (button == click_button && (long int) (timestamp - click_time) <= hook_get_multi_click_time()) { if (click_count < USHRT_MAX) { click_count++; } else { logger(LOG_LEVEL_WARN, "%s [%u]: Click count overflow detected!\n", __FUNCTION__, __LINE__); } } else { // Reset the click count. click_count = 1; // Set the previous button. click_button = button; } // Save this events time to calculate the click_count. click_time = timestamp; // Store the last click point. last_click.x = mshook->pt.x; last_click.y = mshook->pt.y; // Populate mouse pressed event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_MOUSE_PRESSED; event.mask = get_modifiers(); event.data.mouse.button = button; event.data.mouse.clicks = click_count; event.data.mouse.x = mshook->pt.x; event.data.mouse.y = mshook->pt.y; logger(LOG_LEVEL_INFO, "%s [%u]: Button %u pressed %u time(s). (%u, %u)\n", __FUNCTION__, __LINE__, event.data.mouse.button, event.data.mouse.clicks, event.data.mouse.x, event.data.mouse.y); // Fire mouse pressed event. dispatch_event(&event); }
static __inline void process_mouse_moved(uint64_t timestamp, MSLLHOOKSTRUCT *mshook) { // Reset the click count. if (click_count != 0 && (long) (event.time - click_time) > hook_get_multi_click_time()) { click_count = 0; } // We received a mouse move event with the mouse actually moving. // This verifies that the mouse was moved after being depressed. if (last_click.x != mshook->pt.x || last_click.y != mshook->pt.y) { // Populate mouse move event. event.time = timestamp; event.reserved = 0x00; event.mask = get_modifiers(); // Check the modifier mask range for MASK_BUTTON1 - 5. bool mouse_dragged = event.mask & (MASK_BUTTON1 | MASK_BUTTON2 | MASK_BUTTON3 | MASK_BUTTON4 | MASK_BUTTON5); if (mouse_dragged) { // Create Mouse Dragged event. event.type = EVENT_MOUSE_DRAGGED; } else { // Create a Mouse Moved event. event.type = EVENT_MOUSE_MOVED; } if (!wants_to_hook_event(event.type)) return; event.data.mouse.button = MOUSE_NOBUTTON; event.data.mouse.clicks = click_count; event.data.mouse.x = mshook->pt.x; event.data.mouse.y = mshook->pt.y; logger(LOG_LEVEL_INFO, "%s [%u]: Mouse %s to %u, %u.\n", __FUNCTION__, __LINE__, mouse_dragged ? "dragged" : "moved", event.data.mouse.x, event.data.mouse.y); // Fire mouse move event. dispatch_event(&event); } }
int main() { // Disable the logger. hook_set_logger_proc(&logger_proc); // Retrieves an array of screen data for each available monitor. uint8_t count = 0; screen_data *screens = hook_create_screen_info(&count); if (screens != NULL) { fprintf(stdout, "Found %d Monitors:\n", count); for (int i = 0; i < count; i++) { fprintf(stdout, "\tNumber:\t\t%d\n", screens[i].number); fprintf(stdout, "\tOffset X:\t%d\n", screens[i].x); fprintf(stdout, "\tOffset Y:\t%d\n", screens[i].y); fprintf(stdout, "\tWidth:\t\t%d\n", screens[i].width); fprintf(stdout, "\tHeight:\t\t%d\n", screens[i].height); fprintf(stdout, "\n"); } // You are responsible for freeing the memory returned by hook_create_screen_info. free(screens); } else { fprintf(stderr, "Failed to aquire screen information!\n"); } // Retrieves the keyboard auto repeat rate. long int repeat_rate = hook_get_auto_repeat_rate(); if (repeat_rate >= 0) { fprintf(stdout, "Auto Repeat Rate:\t%ld\n", repeat_rate); } else { fprintf(stderr, "Failed to aquire keyboard auto repeat rate!\n"); } // Retrieves the keyboard auto repeat delay. long int repeat_delay = hook_get_auto_repeat_delay(); if (repeat_delay >= 0) { fprintf(stdout, "Auto Repeat Delay:\t%ld\n", repeat_delay); } else { fprintf(stderr, "Failed to aquire keyboard auto repeat delay!\n"); } // Retrieves the mouse acceleration multiplier. long int acceleration_multiplier = hook_get_pointer_acceleration_multiplier(); if (acceleration_multiplier >= 0) { fprintf(stdout, "Mouse Acceleration Multiplier:\t%ld\n", acceleration_multiplier); } else { fprintf(stderr, "Failed to aquire mouse acceleration multiplier!\n"); } // Retrieves the mouse acceleration threshold. long int acceleration_threshold = hook_get_pointer_acceleration_threshold(); if (acceleration_threshold >= 0) { fprintf(stdout, "Mouse Acceleration Threshold:\t%ld\n", acceleration_threshold); } else { fprintf(stderr, "Failed to aquire mouse acceleration threshold!\n"); } // Retrieves the mouse sensitivity. long int sensitivity = hook_get_pointer_sensitivity(); if (sensitivity >= 0) { fprintf(stdout, "Mouse Sensitivity:\t%ld\n", sensitivity); } else { fprintf(stderr, "Failed to aquire keyboard auto repeat rate!\n"); } // Retrieves the double/triple click interval. long int click_time = hook_get_multi_click_time(); if (click_time >= 0) { fprintf(stdout, "Multi-Click Time:\t%ld\n", click_time); } else { fprintf(stderr, "Failed to aquire keyboard auto repeat rate!\n"); } return EXIT_SUCCESS; }
void hook_event_proc(XPointer closeure, XRecordInterceptData *recorded_data) { uint64_t timestamp = (uint64_t) recorded_data->server_time; if (recorded_data->category == XRecordStartOfData) { // Populate the hook start event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_HOOK_ENABLED; event.mask = 0x00; // Fire the hook start event. dispatch_event(&event); } else if (recorded_data->category == XRecordEndOfData) { // Populate the hook stop event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_HOOK_DISABLED; event.mask = 0x00; // Fire the hook stop event. dispatch_event(&event); } else if (recorded_data->category == XRecordFromServer || recorded_data->category == XRecordFromClient) { // Get XRecord data. XRecordDatum *data = (XRecordDatum *) recorded_data->data; if (data->type == KeyPress) { // The X11 KeyCode associated with this event. KeyCode keycode = (KeyCode) data->event.u.u.detail; KeySym keysym = 0x00; #if defined(USE_XKBCOMMON) if (state != NULL) { keysym = xkb_state_key_get_one_sym(state, keycode); } #else keysym = keycode_to_keysym(keycode, data->event.u.keyButtonPointer.state); #endif unsigned short int scancode = keycode_to_scancode(keycode); // TODO If you have a better suggestion for this ugly, let me know. if (scancode == VC_SHIFT_L) { set_modifier_mask(MASK_SHIFT_L); } else if (scancode == VC_SHIFT_R) { set_modifier_mask(MASK_SHIFT_R); } else if (scancode == VC_CONTROL_L) { set_modifier_mask(MASK_CTRL_L); } else if (scancode == VC_CONTROL_R) { set_modifier_mask(MASK_CTRL_R); } else if (scancode == VC_ALT_L) { set_modifier_mask(MASK_ALT_L); } else if (scancode == VC_ALT_R) { set_modifier_mask(MASK_ALT_R); } else if (scancode == VC_META_L) { set_modifier_mask(MASK_META_L); } else if (scancode == VC_META_R) { set_modifier_mask(MASK_META_R); } xkb_state_update_key(state, keycode, XKB_KEY_DOWN); initialize_locks(); if ((get_modifiers() & MASK_NUM_LOCK) == 0) { switch (scancode) { case VC_KP_SEPARATOR: case VC_KP_1: case VC_KP_2: case VC_KP_3: case VC_KP_4: case VC_KP_5: case VC_KP_6: case VC_KP_7: case VC_KP_8: case VC_KP_0: case VC_KP_9: scancode |= 0xEE00; break; } } // Populate key pressed event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_KEY_PRESSED; event.mask = get_modifiers(); event.data.keyboard.keycode = scancode; event.data.keyboard.rawcode = keysym; event.data.keyboard.keychar = CHAR_UNDEFINED; logger(LOG_LEVEL_INFO, "%s [%u]: Key %#X pressed. (%#X)\n", __FUNCTION__, __LINE__, event.data.keyboard.keycode, event.data.keyboard.rawcode); // Fire key pressed event. dispatch_event(&event); // If the pressed event was not consumed... if (event.reserved ^ 0x01) { uint16_t buffer[2]; size_t count = 0; // Check to make sure the key is printable. #ifdef USE_XKBCOMMON if (state != NULL) { count = keycode_to_unicode(state, keycode, buffer, sizeof(buffer) / sizeof(uint16_t)); } #else count = keysym_to_unicode(keysym, buffer, sizeof(buffer) / sizeof(uint16_t)); #endif for (unsigned int i = 0; i < count; i++) { // Populate key typed event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_KEY_TYPED; event.mask = get_modifiers(); event.data.keyboard.keycode = VC_UNDEFINED; event.data.keyboard.rawcode = keysym; event.data.keyboard.keychar = buffer[i]; logger(LOG_LEVEL_INFO, "%s [%u]: Key %#X typed. (%lc)\n", __FUNCTION__, __LINE__, event.data.keyboard.keycode, (uint16_t) event.data.keyboard.keychar); // Fire key typed event. dispatch_event(&event); } } } else if (data->type == KeyRelease) { // The X11 KeyCode associated with this event. KeyCode keycode = (KeyCode) data->event.u.u.detail; KeySym keysym = 0x00; #ifdef USE_XKBCOMMON if (state != NULL) { keysym = xkb_state_key_get_one_sym(state, keycode); } #else keysym = keycode_to_keysym(keycode, data->event.u.keyButtonPointer.state); #endif unsigned short int scancode = keycode_to_scancode(keycode); // TODO If you have a better suggestion for this ugly, let me know. if (scancode == VC_SHIFT_L) { unset_modifier_mask(MASK_SHIFT_L); } else if (scancode == VC_SHIFT_R) { unset_modifier_mask(MASK_SHIFT_R); } else if (scancode == VC_CONTROL_L) { unset_modifier_mask(MASK_CTRL_L); } else if (scancode == VC_CONTROL_R) { unset_modifier_mask(MASK_CTRL_R); } else if (scancode == VC_ALT_L) { unset_modifier_mask(MASK_ALT_L); } else if (scancode == VC_ALT_R) { unset_modifier_mask(MASK_ALT_R); } else if (scancode == VC_META_L) { unset_modifier_mask(MASK_META_L); } else if (scancode == VC_META_R) { unset_modifier_mask(MASK_META_R); } xkb_state_update_key(state, keycode, XKB_KEY_UP); initialize_locks(); if ((get_modifiers() & MASK_NUM_LOCK) == 0) { switch (scancode) { case VC_KP_SEPARATOR: case VC_KP_1: case VC_KP_2: case VC_KP_3: case VC_KP_4: case VC_KP_5: case VC_KP_6: case VC_KP_7: case VC_KP_8: case VC_KP_0: case VC_KP_9: scancode |= 0xEE00; break; } } // Populate key released event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_KEY_RELEASED; event.mask = get_modifiers(); event.data.keyboard.keycode = scancode; event.data.keyboard.rawcode = keysym; event.data.keyboard.keychar = CHAR_UNDEFINED; logger(LOG_LEVEL_INFO, "%s [%u]: Key %#X released. (%#X)\n", __FUNCTION__, __LINE__, event.data.keyboard.keycode, event.data.keyboard.rawcode); // Fire key released event. dispatch_event(&event); } else if (data->type == ButtonPress) { // X11 handles wheel events as button events. if (data->event.u.u.detail == WheelUp || data->event.u.u.detail == WheelDown || data->event.u.u.detail == WheelLeft || data->event.u.u.detail == WheelRight) { // Reset the click count and previous button. hook->input.mouse.click.count = 1; hook->input.mouse.click.button = MOUSE_NOBUTTON; /* Scroll wheel release events. * Scroll type: WHEEL_UNIT_SCROLL * Scroll amount: 3 unit increments per notch * Units to scroll: 3 unit increments * Vertical unit increment: 15 pixels */ // Populate mouse wheel event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_MOUSE_WHEEL; event.mask = get_modifiers(); event.data.wheel.clicks = hook->input.mouse.click.count; event.data.wheel.x = data->event.u.keyButtonPointer.rootX; event.data.wheel.y = data->event.u.keyButtonPointer.rootY; #if defined(USE_XINERAMA) || defined(USE_XRANDR) uint8_t count; screen_data *screens = hook_create_screen_info(&count); if (count > 1) { event.data.wheel.x -= screens[0].x; event.data.wheel.y -= screens[0].y; } if (screens != NULL) { free(screens); } #endif /* X11 does not have an API call for acquiring the mouse scroll type. This * maybe part of the XInput2 (XI2) extention but I will wont know until it * is available on my platform. For the time being we will just use the * unit scroll value. */ event.data.wheel.type = WHEEL_UNIT_SCROLL; /* Some scroll wheel properties are available via the new XInput2 (XI2) * extension. Unfortunately the extension is not available on my * development platform at this time. For the time being we will just * use the Windows default value of 3. */ event.data.wheel.amount = 3; if (data->event.u.u.detail == WheelUp || data->event.u.u.detail == WheelLeft) { // Wheel Rotated Up and Away. event.data.wheel.rotation = -1; } else { // data->event.u.u.detail == WheelDown // Wheel Rotated Down and Towards. event.data.wheel.rotation = 1; } if (data->event.u.u.detail == WheelUp || data->event.u.u.detail == WheelDown) { // Wheel Rotated Up or Down. event.data.wheel.direction = WHEEL_VERTICAL_DIRECTION; } else { // data->event.u.u.detail == WheelLeft || data->event.u.u.detail == WheelRight // Wheel Rotated Left or Right. event.data.wheel.direction = WHEEL_HORIZONTAL_DIRECTION; } logger(LOG_LEVEL_INFO, "%s [%u]: Mouse wheel type %u, rotated %i units in the %u direction at %u, %u.\n", __FUNCTION__, __LINE__, event.data.wheel.type, event.data.wheel.amount * event.data.wheel.rotation, event.data.wheel.direction, event.data.wheel.x, event.data.wheel.y); // Fire mouse wheel event. dispatch_event(&event); } else { /* This information is all static for X11, its up to the WM to * decide how to interpret the wheel events. */ uint16_t button = MOUSE_NOBUTTON; switch (data->event.u.u.detail) { // FIXME This should use a lookup table to handle button remapping. case Button1: button = MOUSE_BUTTON1; set_modifier_mask(MASK_BUTTON1); break; case Button2: button = MOUSE_BUTTON2; set_modifier_mask(MASK_BUTTON2); break; case Button3: button = MOUSE_BUTTON3; set_modifier_mask(MASK_BUTTON3); break; case XButton1: button = MOUSE_BUTTON4; set_modifier_mask(MASK_BUTTON5); break; case XButton2: button = MOUSE_BUTTON5; set_modifier_mask(MASK_BUTTON5); break; default: // Do not set modifier masks past button MASK_BUTTON5. break; } // Track the number of clicks, the button must match the previous button. if (button == hook->input.mouse.click.button && (long int) (timestamp - hook->input.mouse.click.time) <= hook_get_multi_click_time()) { if (hook->input.mouse.click.count < USHRT_MAX) { hook->input.mouse.click.count++; } else { logger(LOG_LEVEL_WARN, "%s [%u]: Click count overflow detected!\n", __FUNCTION__, __LINE__); } } else { // Reset the click count. hook->input.mouse.click.count = 1; // Set the previous button. hook->input.mouse.click.button = button; } // Save this events time to calculate the hook->input.mouse.click.count. hook->input.mouse.click.time = timestamp; // Populate mouse pressed event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_MOUSE_PRESSED; event.mask = get_modifiers(); event.data.mouse.button = button; event.data.mouse.clicks = hook->input.mouse.click.count; event.data.mouse.x = data->event.u.keyButtonPointer.rootX; event.data.mouse.y = data->event.u.keyButtonPointer.rootY; #if defined(USE_XINERAMA) || defined(USE_XRANDR) uint8_t count; screen_data *screens = hook_create_screen_info(&count); if (count > 1) { event.data.mouse.x -= screens[0].x; event.data.mouse.y -= screens[0].y; } if (screens != NULL) { free(screens); } #endif logger(LOG_LEVEL_INFO, "%s [%u]: Button %u pressed %u time(s). (%u, %u)\n", __FUNCTION__, __LINE__, event.data.mouse.button, event.data.mouse.clicks, event.data.mouse.x, event.data.mouse.y); // Fire mouse pressed event. dispatch_event(&event); } } else if (data->type == ButtonRelease) { // X11 handles wheel events as button events. if (data->event.u.u.detail != WheelUp && data->event.u.u.detail != WheelDown) { /* This information is all static for X11, its up to the WM to * decide how to interpret the wheel events. */ uint16_t button = MOUSE_NOBUTTON; switch (data->event.u.u.detail) { // FIXME This should use a lookup table to handle button remapping. case Button1: button = MOUSE_BUTTON1; unset_modifier_mask(MASK_BUTTON1); break; case Button2: button = MOUSE_BUTTON2; unset_modifier_mask(MASK_BUTTON2); break; case Button3: button = MOUSE_BUTTON3; unset_modifier_mask(MASK_BUTTON3); break; case XButton1: button = MOUSE_BUTTON4; unset_modifier_mask(MASK_BUTTON5); break; case XButton2: button = MOUSE_BUTTON5; unset_modifier_mask(MASK_BUTTON5); break; default: // Do not set modifier masks past button MASK_BUTTON5. break; } // Populate mouse released event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_MOUSE_RELEASED; event.mask = get_modifiers(); event.data.mouse.button = button; event.data.mouse.clicks = hook->input.mouse.click.count; event.data.mouse.x = data->event.u.keyButtonPointer.rootX; event.data.mouse.y = data->event.u.keyButtonPointer.rootY; #if defined(USE_XINERAMA) || defined(USE_XRANDR) uint8_t count; screen_data *screens = hook_create_screen_info(&count); if (count > 1) { event.data.mouse.x -= screens[0].x; event.data.mouse.y -= screens[0].y; } if (screens != NULL) { free(screens); } #endif logger(LOG_LEVEL_INFO, "%s [%u]: Button %u released %u time(s). (%u, %u)\n", __FUNCTION__, __LINE__, event.data.mouse.button, event.data.mouse.clicks, event.data.mouse.x, event.data.mouse.y); // Fire mouse released event. dispatch_event(&event); // If the pressed event was not consumed... if (event.reserved ^ 0x01 && hook->input.mouse.is_dragged != true) { // Populate mouse clicked event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_MOUSE_CLICKED; event.mask = get_modifiers(); event.data.mouse.button = button; event.data.mouse.clicks = hook->input.mouse.click.count; event.data.mouse.x = data->event.u.keyButtonPointer.rootX; event.data.mouse.y = data->event.u.keyButtonPointer.rootY; #if defined(USE_XINERAMA) || defined(USE_XRANDR) uint8_t count; screen_data *screens = hook_create_screen_info(&count); if (count > 1) { event.data.mouse.x -= screens[0].x; event.data.mouse.y -= screens[0].y; } if (screens != NULL) { free(screens); } #endif logger(LOG_LEVEL_INFO, "%s [%u]: Button %u clicked %u time(s). (%u, %u)\n", __FUNCTION__, __LINE__, event.data.mouse.button, event.data.mouse.clicks, event.data.mouse.x, event.data.mouse.y); // Fire mouse clicked event. dispatch_event(&event); } // Reset the number of clicks. if (button == hook->input.mouse.click.button && (long int) (event.time - hook->input.mouse.click.time) > hook_get_multi_click_time()) { // Reset the click count. hook->input.mouse.click.count = 0; } } } else if (data->type == MotionNotify) { // Reset the click count. if (hook->input.mouse.click.count != 0 && (long int) (timestamp - hook->input.mouse.click.time) > hook_get_multi_click_time()) { hook->input.mouse.click.count = 0; } // Populate mouse move event. event.time = timestamp; event.reserved = 0x00; event.mask = get_modifiers(); // Check the upper half of virtual modifiers for non-zero // values and set the mouse dragged flag. hook->input.mouse.is_dragged = (event.mask >> 8 > 0); if (hook->input.mouse.is_dragged) { // Create Mouse Dragged event. event.type = EVENT_MOUSE_DRAGGED; } else { // Create a Mouse Moved event. event.type = EVENT_MOUSE_MOVED; } event.data.mouse.button = MOUSE_NOBUTTON; event.data.mouse.clicks = hook->input.mouse.click.count; event.data.mouse.x = data->event.u.keyButtonPointer.rootX; event.data.mouse.y = data->event.u.keyButtonPointer.rootY; #if defined(USE_XINERAMA) || defined(USE_XRANDR) uint8_t count; screen_data *screens = hook_create_screen_info(&count); if (count > 1) { event.data.mouse.x -= screens[0].x; event.data.mouse.y -= screens[0].y; } if (screens != NULL) { free(screens); } #endif logger(LOG_LEVEL_INFO, "%s [%u]: Mouse %s to %i, %i. (%#X)\n", __FUNCTION__, __LINE__, hook->input.mouse.is_dragged ? "dragged" : "moved", event.data.mouse.x, event.data.mouse.y, event.mask); // Fire mouse move event. dispatch_event(&event); } else {
void jni_SetProperties(JNIEnv *env) { // Create a buffer for converting numbers to strings. char buffer[16]; // Set the native keyboard auto repeat rate. long rate = hook_get_auto_repeat_rate(); if (rate >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_auto_repeat_rate(): successful. (%li)\n", __FUNCTION__, __LINE__, rate); if (snprintf(buffer, sizeof(buffer), "%li", rate) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.autoRepeatRate"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert auto repeat rate to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_auto_repeat_rate()!\n", __FUNCTION__, __LINE__); } long delay = hook_get_auto_repeat_delay(); if (delay >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_auto_repeat_delay(): successful. (%li)\n", __FUNCTION__, __LINE__, delay); if (snprintf(buffer, sizeof(buffer), "%li", delay) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.autoRepeatDelay"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert auto repeat delay to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_auto_repeat_delay()!\n", __FUNCTION__, __LINE__); } // 0-Threshold X, 1-Threshold Y and 2-Speed. long multiplier = hook_get_pointer_acceleration_multiplier(); if (multiplier >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_pointer_acceleration_multiplier(): successful. (%li)\n", __FUNCTION__, __LINE__, multiplier); if (snprintf(buffer, sizeof(buffer), "%li", multiplier) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.pointerAccelerationMultiplier"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert pointer acceleration multiplier to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_pointer_acceleration_multiplier()!\n", __FUNCTION__, __LINE__); } // 0-Threshold X, 1-Threshold Y and 2-Speed. long threshold = hook_get_pointer_acceleration_threshold(); if (threshold >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_pointer_acceleration_threshold(): successful. (%li)\n", __FUNCTION__, __LINE__, threshold); if (snprintf(buffer, sizeof(buffer), "%li", threshold) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.pointerAccelerationThreshold"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert pointer acceleration threshold to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_pointer_acceleration_threshold()!\n", __FUNCTION__, __LINE__); } long sensitivity = hook_get_pointer_sensitivity(); if (sensitivity >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_pointer_sensitivity(): successful. (%li)\n", __FUNCTION__, __LINE__, sensitivity); if (snprintf(buffer, sizeof(buffer), "%li", sensitivity) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.pointerSensitivity"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert pointer sensitivity to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_pointer_sensitivity()!\n", __FUNCTION__, __LINE__); } long clicktime = hook_get_multi_click_time(); if (clicktime >= 0) { jni_Logger(LOG_LEVEL_DEBUG, "%s [%u]: hook_get_multi_click_time(): successful. (%li)\n", __FUNCTION__, __LINE__, clicktime); if (snprintf(buffer, sizeof(buffer), "%li", clicktime) >= 0) { jstring name = (*env)->NewStringUTF(env, "jnativehook.multiClickInterval"); jstring value = (*env)->NewStringUTF(env, buffer); (*env)->CallStaticObjectMethod( env, java_lang_System->cls, java_lang_System->setProperty, name, value); (*env)->DeleteLocalRef(env, name); (*env)->DeleteLocalRef(env, value); } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Failed to convert multi click time to string!\n", __FUNCTION__, __LINE__); } } else { jni_Logger(LOG_LEVEL_WARN, "%s [%u]: Invalid result returned from hook_get_multi_click_time()!\n", __FUNCTION__, __LINE__); } }