static __inline void process_key_pressed(uint64_t timestamp, KBDLLHOOKSTRUCT *kbhook) { // Check and setup modifiers. if (kbhook->vkCode == VK_LSHIFT) { set_modifier_mask(MASK_SHIFT_L); } else if (kbhook->vkCode == VK_RSHIFT) { set_modifier_mask(MASK_SHIFT_R); } else if (kbhook->vkCode == VK_LCONTROL) { set_modifier_mask(MASK_CTRL_L); } else if (kbhook->vkCode == VK_RCONTROL) { set_modifier_mask(MASK_CTRL_R); } else if (kbhook->vkCode == VK_LMENU) { set_modifier_mask(MASK_ALT_L); } else if (kbhook->vkCode == VK_RMENU) { set_modifier_mask(MASK_ALT_R); } else if (kbhook->vkCode == VK_LWIN) { set_modifier_mask(MASK_META_L); } else if (kbhook->vkCode == VK_RWIN) { set_modifier_mask(MASK_META_R); } // Populate key pressed event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_KEY_PRESSED; event.mask = get_modifiers(); event.data.keyboard.keycode = keycode_to_scancode(kbhook->vkCode); event.data.keyboard.rawcode = kbhook->vkCode; 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); if (wants_to_hook_event(EVENT_KEY_PRESSED)){ // Populate key pressed event. dispatch_event(&event); } if (!wants_to_hook_event(EVENT_KEY_TYPED)) return; // 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 = timestamp; event.reserved = 0x00; event.type = EVENT_KEY_TYPED; event.mask = get_modifiers(); event.data.keyboard.keycode = keycode_to_scancode(kbhook->vkCode); event.data.keyboard.rawcode = kbhook->vkCode; event.data.keyboard.keychar = buffer[i]; logger(LOG_LEVEL_INFO, "%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); } } }
static __inline void process_button_released(uint64_t timestamp, MSLLHOOKSTRUCT *mshook, uint16_t button) { if (wants_to_hook_event(EVENT_MOUSE_RELEASED)){ // 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 = 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 (!wants_to_hook_event(EVENT_MOUSE_CLICKED)) return; // 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 = timestamp; 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); } }
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 void process_key_released(KBDLLHOOKSTRUCT *kbhook) { // Check and setup modifiers. if (kbhook->vkCode == VK_LSHIFT) { unset_modifier_mask(MASK_SHIFT_L); } else if (kbhook->vkCode == VK_RSHIFT) { unset_modifier_mask(MASK_SHIFT_R); } else if (kbhook->vkCode == VK_LCONTROL) { unset_modifier_mask(MASK_CTRL_L); } else if (kbhook->vkCode == VK_RCONTROL) { unset_modifier_mask(MASK_CTRL_R); } else if (kbhook->vkCode == VK_LMENU) { unset_modifier_mask(MASK_ALT_L); } else if (kbhook->vkCode == VK_RMENU) { unset_modifier_mask(MASK_ALT_R); } else if (kbhook->vkCode == VK_LWIN) { unset_modifier_mask(MASK_META_L); } else if (kbhook->vkCode == VK_RWIN) { unset_modifier_mask(MASK_META_R); } else if (kbhook->vkCode == VK_NUMLOCK) { unset_modifier_mask(MASK_NUM_LOCK); } else if (kbhook->vkCode == VK_CAPITAL) { unset_modifier_mask(MASK_CAPS_LOCK); } else if (kbhook->vkCode == VK_SCROLL) { unset_modifier_mask(MASK_SCROLL_LOCK); } // Populate key pressed event. event.time = kbhook->time; event.reserved = 0x00; event.type = EVENT_KEY_RELEASED; event.mask = get_modifiers(); event.data.keyboard.keycode = keycode_to_scancode(kbhook->vkCode, kbhook->flags); event.data.keyboard.rawcode = kbhook->vkCode; 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); }
void parse_result_modifiers(char *line, InstructionModifiers *modifiers) { char *p = strchr(line, '|'); int i = 0; char param[128]; char func[64]; char args[64]; memset(¶m,0,sizeof(param)); if(p != NULL) { *p = 0; p++; while(true) { find_nth(p, i++, param, sizeof(param)); memset(&func,0,sizeof(func)); memset(&args,0,sizeof(args)); if(strlen(param) == 0) break; char *x = strchr(param, '('); if(x == NULL) break; char *x1 = strchr(x,')'); strncpy(func,param,x-param); strncpy(args,x+1,x1-x-1); get_modifiers((char *)&func, (char *)&args, modifiers); //printf("%s %s\n",func, args); } } }
static __inline void process_key_released(uint64_t timestamp, KBDLLHOOKSTRUCT *kbhook) { // Check and setup modifiers. if (kbhook->vkCode == VK_LSHIFT) { unset_modifier_mask(MASK_SHIFT_L); } else if (kbhook->vkCode == VK_RSHIFT) { unset_modifier_mask(MASK_SHIFT_R); } else if (kbhook->vkCode == VK_LCONTROL) { unset_modifier_mask(MASK_CTRL_L); } else if (kbhook->vkCode == VK_RCONTROL) { unset_modifier_mask(MASK_CTRL_R); } else if (kbhook->vkCode == VK_LMENU) { unset_modifier_mask(MASK_ALT_L); } else if (kbhook->vkCode == VK_RMENU) { unset_modifier_mask(MASK_ALT_R); } else if (kbhook->vkCode == VK_LWIN) { unset_modifier_mask(MASK_META_L); } else if (kbhook->vkCode == VK_RWIN) { unset_modifier_mask(MASK_META_R); } if (!wants_to_hook_event(EVENT_KEY_RELEASED)) return; // Populate key released event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_KEY_RELEASED; event.mask = get_modifiers(); event.data.keyboard.keycode = keycode_to_scancode(kbhook->vkCode); event.data.keyboard.rawcode = kbhook->vkCode; 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); }
static inline void process_mouse_wheel(uint64_t timestamp, MSLLHOOKSTRUCT *mshook) { // Track the number of clicks. // Reset the click count and previous button. click_count = 1; click_button = MOUSE_NOBUTTON; // Populate mouse wheel event. event.time = timestamp; event.reserved = 0x00; event.type = EVENT_MOUSE_WHEEL; event.mask = get_modifiers(); event.data.wheel.clicks = click_count; event.data.wheel.x = mshook->pt.x; event.data.wheel.y = mshook->pt.y; event.data.wheel.type = get_scroll_wheel_type(); event.data.wheel.amount = get_scroll_wheel_amount(); /* Delta HIWORD(mshook->mouseData) * A positive value indicates that the wheel was rotated * forward, away from the user; a negative value indicates that * the wheel was rotated backward, toward the user. One wheel * click is defined as WHEEL_DELTA, which is 120. */ event.data.wheel.rotation = ((int16_t) HIWORD(mshook->mouseData) / WHEEL_DELTA) * -1; logger(LOG_LEVEL_INFO, "%s [%u]: Mouse wheel type %u, rotated %i units at %u, %u.\n", __FUNCTION__, __LINE__, event.data.wheel.type, event.data.wheel.amount * event.data.wheel.rotation, event.data.wheel.x, event.data.wheel.y); // Fire mouse wheel event. dispatch_event(&event); }
static void set_property_info(Array &ret, ClassInfo::PropertyInfo *info, const ClassInfo *cls) { ret.set("name", info->name); set_access(ret, info->attribute); ret.set("modifiers", get_modifiers(info->attribute, false)); ret.set("static", (bool)(info->attribute & ClassInfo::IsStatic)); ret.set("class", cls->getName()); set_doc_comment(ret, info->docComment); }
void GlutViewer::glut_keyboard(unsigned char key, int x, int y) { get_modifiers(); if (self->keyPress(key, x, y)) glutPostRedisplay(); if (self->quitProgram) { exit(0); } }
static void set_method_info(Array &ret, ClassInfo::MethodInfo *info, const ClassInfo *cls) { ret.set("name", info->name); set_access(ret, info->attribute); ret.set("modifiers", get_modifiers(info->attribute, false)); ret.set("static", (bool)(info->attribute & ClassInfo::IsStatic)); ret.set("final", (bool)(info->attribute & ClassInfo::IsFinal)); ret.set("abstract", (bool)(info->attribute & ClassInfo::IsAbstract)); ret.set("internal", (bool)(cls->getAttribute() & ClassInfo::IsSystem)); ret.set("class", cls->getName()); set_function_info(ret, info, cls->getName()); }
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); }
void input_manager::check_touch_bindings(int x, int y) { uint32_t mods = get_modifiers(); std::vector<touch_callback*> calls; for (auto& binding : bindings[WF_BINDING_TOUCH]) { if (binding->value->as_cached_key().matches({mods, 0}) && binding->output == core->get_active_output()) { calls.push_back(binding->call.touch); } } for (auto call : calls) (*call)(x, y); }
static int drm_atomic_get_modifiers(struct drm *drm) { unsigned int i, j, format_index = 0; for (i = 0; i < drm->plane->plane->count_formats; i++) { if (drm->plane->plane->formats[i] == DRM_FORMAT_XRGB8888) format_index = i; } for (i = 0; i < drm->plane->props->count_props; i++) { if (!strcmp(drm->plane->props_info[i]->name, "IN_FORMATS")) { struct drm_format_modifier *mods; drmModePropertyBlobPtr blob; unsigned int count; blob = drmModeGetPropertyBlob(drm->fd, drm->plane->props->prop_values[i]); if (!blob) { printf("failed to get blob for property %s\n", drm->plane->props_info[i]->name); return -ENOMEM; } count = get_modifiers(blob, &mods); for (j = 0; j < count; j++) { if (mods[j].formats & (1ULL << format_index)) drm->num_modifiers++; } drm->modifiers = calloc(drm->num_modifiers, sizeof(uint64_t)); if (!drm->modifiers) { printf("failed to allocate modifiers\n"); return -ENOMEM; } for (j = 0; j < count; j++) { if (mods[j].formats & (1ULL << format_index)) drm->modifiers[j] = mods[j].modifier; } } } return 0; }
void GlutViewer::glut_mouseclick(int btn, int state, int x, int y) { get_modifiers(); MouseButton button = MouseButton(btn+1); if (state == 0) { // XOR state of three mouse buttons to the mouseState variable if (button <= RightButton) self->mouseState ^= (int)pow(2,button+1); self->mousePress(button, true, x, y); } else { // Release self->mouseState = 0; self->mousePress(button, false, x, y); } glutPostRedisplay(); }
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); } }
void GlutViewer::glut_keyboard_ext(int code, int x, int y) { unsigned char key; get_modifiers(); switch (code) { case GLUT_KEY_LEFT: key = KEY_LEFT; break; case GLUT_KEY_RIGHT: key = KEY_RIGHT; break; case GLUT_KEY_DOWN: key = KEY_DOWN; break; case GLUT_KEY_UP: key = KEY_UP; break; case GLUT_KEY_PAGE_UP: key = KEY_PAGEUP; break; case GLUT_KEY_PAGE_DOWN: key = KEY_PAGEDOWN; break; case GLUT_KEY_HOME: key = KEY_HOME; break; case GLUT_KEY_END: key = KEY_END; break; default: return; } if (self->keyPress(key, x, y)) glutPostRedisplay(); }
static LRESULT CALLBACK window_procedure(HWND window, UINT message, WPARAM wParam, LPARAM lParam) { static int n_saved_key_events = 0; static struct event *saved_key_events[MAX_SAVED_KEY_EVENTS]; static WPARAM last_dead_character = '\0'; static int append_character_instead_of_replacing = 0; static utf8 character_buffer[13] = { '\0' }; static int click_button = -1; static uint64_t click_start_time = 0; static int click_count = 1; static struct drawable *mouse_drawable = NULL; struct drawable *drawable = NULL; for(size_t i = 0; i < n_drawables; i++) { if(all_drawables[i]->window == window) { drawable = all_drawables[i]; break; } } switch(message) { case WM_CREATE: return 0; case WM_CLOSE: if(drawable) { ef_drawable_delete((EF_Drawable) drawable); PostQuitMessage(0); } return 0; case WM_DESTROY: return 0; case WM_PAINT: { PAINTSTRUCT paint; BeginPaint(window, &paint); if(drawable) { if(drawable->draw_callback) { ef_drawable_make_current((EF_Drawable) drawable); drawable->draw_callback((EF_Drawable) drawable, drawable->draw_callback_context); } } EndPaint(window, &paint); return 0; } case WM_KEYDOWN: case WM_SYSKEYDOWN: if(!is_modifier_keycode(wParam)) { struct event *event = NULL; for(int i = 0; i < n_saved_key_events; i++) { if(saved_key_events[i]->data.key_event.keycode == wParam) { event = saved_key_events[i]; break; } } if(event) { event->timestamp = ef_time_unix_epoch(); event->modifiers = get_modifiers(); event->data.key_event.string = NULL; event->data.key_event.has_fired_for_key_down = 0; } else { event = malloc(sizeof(struct event)); event->timestamp = ef_time_unix_epoch(); event->modifiers = get_modifiers(); event->data.key_event.keycode = (EF_Keycode) wParam; //= (EF_Keycode) MapVirtualKey(wParam, MAPVK_VK_TO_VSC); event->data.key_event.string = NULL; event->data.key_event.has_fired_for_key_down = 0; if(n_saved_key_events < MAX_SAVED_KEY_EVENTS) { n_saved_key_events++; saved_key_events[n_saved_key_events-1] = event; } } if(is_noncharacter_keycode(wParam)) { event->data.key_event.has_fired_for_key_down = 1; if(drawable && drawable->key_down_callback) { drawable->key_down_callback(drawable, (EF_Event) event, drawable->key_down_callback_context); } } } if(message == WM_SYSKEYDOWN) { return DefWindowProc(window, message, wParam, lParam); } else { return 0; } case WM_KEYUP: case WM_SYSKEYUP: { struct event *saved_key_event = NULL; for(int i = 0; i < n_saved_key_events; i++) { if(saved_key_events[i]->data.key_event.keycode == wParam) { saved_key_event = saved_key_events[i]; break; } } if(saved_key_event && drawable && drawable->key_up_callback && !is_modifier_keycode(wParam) && !last_dead_character) { saved_key_event->timestamp = ef_time_unix_epoch(); saved_key_event->data.key_event.string = character_buffer; drawable->key_up_callback(drawable, (EF_Event) saved_key_event, drawable->key_up_callback_context); for(int i = 0; i < n_saved_key_events; i++) { if(saved_key_events[i] == saved_key_event) { for(int j = i; j < n_saved_key_events-1; j++) saved_key_events[j] = saved_key_events[j+1]; n_saved_key_events--; break; } } free(saved_key_event); } if(message == WM_SYSKEYUP) { return DefWindowProc(window, message, wParam, lParam); } else { return 0; } } case WM_CHAR: case WM_SYSCHAR: { utf8 *point = character_buffer; if(append_character_instead_of_replacing) { while(*point) point++; } utf16 temp16[2]; temp16[0] = wParam; temp16[1] = '\0'; utf8 *temp8 = utf16_to_utf8(temp16); utf8_cpy(point, temp8); free(temp8); } if(last_dead_character == wParam) { append_character_instead_of_replacing = 1; } else { append_character_instead_of_replacing = 0; struct event *saved_key_event = NULL; if(n_saved_key_events) { struct event *event = saved_key_events[n_saved_key_events-1]; if(!event->data.key_event.has_fired_for_key_down) saved_key_event = event; } if(saved_key_event) { saved_key_event->data.key_event.has_fired_for_key_down = 1; if(drawable && drawable->key_down_callback) { saved_key_event->data.key_event.string = character_buffer; drawable->key_down_callback(drawable, (EF_Event) saved_key_event, drawable->key_down_callback_context); } } } last_dead_character = '\0'; return 0; case WM_DEADCHAR: case WM_SYSDEADCHAR: last_dead_character = wParam; return 0; case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_XBUTTONDOWN: { SetCapture(window); struct event *event = malloc(sizeof(struct event)); event->timestamp = ef_time_unix_epoch(); event->modifiers = get_modifiers(); switch(message) { case WM_LBUTTONDOWN: event->data.mouse_event.button_number = 0; break; case WM_RBUTTONDOWN: event->data.mouse_event.button_number = 1; break; case WM_MBUTTONDOWN: event->data.mouse_event.button_number = 2; break; case WM_XBUTTONDOWN: switch((wParam >> 16) & 0xFFFF) { case XBUTTON1: event->data.mouse_event.button_number = 3; break; case XBUTTON2: event->data.mouse_event.button_number = 4; break; default: event->data.mouse_event.button_number = 5; break; } break; } int starts_a_click; if(click_button == -1) { starts_a_click = 1; click_button = event->data.mouse_event.button_number; } else { starts_a_click = 0; } if(event->timestamp - click_start_time < GetDoubleClickTime()) click_count++; else click_count = 1; click_start_time = event->timestamp; event->data.mouse_event.click_count = click_count; RECT client_rect; GetClientRect(window, &client_rect); event->data.mouse_event.x = (lParam & 0xFFFF); event->data.mouse_event.y = client_rect.bottom - ((lParam >> 16) & 0xFFFF); if(starts_a_click && drawable && drawable->mouse_down_callback) { drawable->mouse_down_callback(drawable, (EF_Event) event, drawable->mouse_down_callback_context); } free(event); } return 0; case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_XBUTTONUP: { ReleaseCapture(); struct event *event = malloc(sizeof(struct event)); event->timestamp = ef_time_unix_epoch(); event->modifiers = get_modifiers(); switch(message) { case WM_LBUTTONUP: event->data.mouse_event.button_number = 0; break; case WM_RBUTTONUP: event->data.mouse_event.button_number = 1; break; case WM_MBUTTONUP: event->data.mouse_event.button_number = 2; break; case WM_XBUTTONUP: switch((wParam >> 16) & 0xFFFF) { case XBUTTON1: event->data.mouse_event.button_number = 3; break; case XBUTTON2: event->data.mouse_event.button_number = 4; break; default: event->data.mouse_event.button_number = 5; break; } break; } int ends_a_click; if(click_button == event->data.mouse_event.button_number) { ends_a_click = 1; click_button = -1; } else { ends_a_click = 0; } event->data.mouse_event.click_count = click_count; RECT client_rect; GetClientRect(window, &client_rect); event->data.mouse_event.x = (lParam & 0xFFFF); event->data.mouse_event.y = client_rect.bottom - ((lParam >> 16) & 0xFFFF); if(ends_a_click && drawable && drawable->mouse_up_callback) { drawable->mouse_up_callback(drawable, (EF_Event) event, drawable->mouse_up_callback_context); } free(event); } return 0; case WM_MOUSEMOVE: { click_start_time = 0; struct event *event = malloc(sizeof(struct event)); event->timestamp = ef_time_unix_epoch(); event->modifiers = get_modifiers(); event->data.mouse_event.button_number = 0; event->data.mouse_event.click_count = 0; RECT client_rect; GetClientRect(window, &client_rect); event->data.mouse_event.x = (lParam & 0xFFFF); event->data.mouse_event.y = client_rect.bottom - ((lParam >> 16) & 0xFFFF); if(mouse_drawable != drawable) { TRACKMOUSEEVENT trackmouseevent; trackmouseevent.cbSize = sizeof(trackmouseevent); trackmouseevent.dwFlags = TME_LEAVE; trackmouseevent.hwndTrack = drawable->window; trackmouseevent.dwHoverTime = 0; TrackMouseEvent(&trackmouseevent); if(drawable && drawable->mouse_enter_callback) { drawable->mouse_enter_callback(drawable, (EF_Event) event, drawable->mouse_enter_callback_context); } mouse_drawable = drawable; } if(drawable && drawable->mouse_move_callback) { drawable->mouse_move_callback(drawable, (EF_Event) event, drawable->mouse_move_callback_context); } free(event); } return 0; case WM_MOUSELEAVE: if(drawable && drawable->mouse_exit_callback) { struct event *event = malloc(sizeof(struct event)); event->timestamp = ef_time_unix_epoch(); event->modifiers = get_modifiers(); event->data.mouse_event.button_number = 0; event->data.mouse_event.click_count = 0; event->data.mouse_event.x = 0; event->data.mouse_event.y = 0; drawable->mouse_exit_callback(drawable, (EF_Event) event, drawable->mouse_exit_callback_context); free(event); } mouse_drawable = NULL; return 0; default: return DefWindowProc(window, message, wParam, lParam); } }
/* @brief Processes an entered key by: * * 1) Adding the key to the query buffer (backspace will remove a character). * 2) Drawing the updated query to the screen if necessary. * 3) Writing the updated query to the child process if necessary. * * @param query_buffer The string of the current query (what is typed). * @param query_index A reference to the current length of the query. * @param query_cursor_index A reference to the current index of the cursor in the query. * @param key The key enetered. * @param connection A connection to the Xorg server. * @param cairo_context A cairo context for drawing to the screen. * @param cairo_surface A cairo surface for drawing to the screen. * @param to_write A descriptor to write to the child process. * @return 0 on success and 1 on failure. */ static inline int32_t process_key_stroke(xcb_window_t window, char *query_buffer, uint32_t *query_index, uint32_t *query_cursor_index, xcb_keysym_t key, uint16_t modifier_mask, xcb_connection_t *connection, cairo_t *cairo_context, cairo_surface_t *cairo_surface, FILE *to_write) { pthread_mutex_lock(&global.result_mutex); /* Check when we should update. */ int32_t redraw = 0; int32_t resend = 0; uint8_t mod_key = get_modifiers(modifier_mask); debug("key: %u, modifier: %u\n", key, mod_key); uint32_t highlight = global.result_highlight; uint32_t old_pos; if (global.result_count && key == 100 && mod_key == 3) { /* CTRL-D * GO down to the next title */ next_title(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); } else if (global.result_count && key == 117 && mod_key == 3) { /* CTRL-U * GO up to the next title */ previous_title(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); } else { switch (key) { case 65293: /* Enter. */ if (global.results && global.result_highlight < global.result_count) { char *title = global.results[global.result_highlight].text; char *action = global.results[global.result_highlight].action; char command[255] = "echo '"; strcat(command, query_buffer); strcat(command, " {"); char titleParsed[255]; str_replace(strcpy(titleParsed, title), "'", "'\\''"); strcat(command, titleParsed); strcat(command, " | "); char actionParsed[255]; str_replace(strcpy(actionParsed, action), "'", "'\\''"); strcat(command, actionParsed); strcat(command, "}"); strcat(command, "' >> /home/olli/.local/share/lighthouse_queries && "); printf("%s", command); printf("%s", action); goto cleanup; } break; case 65471: /* F2 */ next_title(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); break; case 65472: /* F3 */ previous_title(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); break; case 65361: /* Left. */ if (*query_cursor_index > 0) { (*query_cursor_index)--; redraw = 1; } break; case 65363: /* Right. */ if (*query_cursor_index < *query_index) { (*query_cursor_index)++; redraw = 1; } break; case 65362: /* Up. */ if (!global.result_count) break; if (highlight) { /* Avoid segfault when highlight on the top. */ old_pos = highlight; get_previous_non_title(&highlight); if (!global.results[highlight].action) { /* If it's a title it mean the get_previous_non_title function * found nothing and hit the top. */ highlight = old_pos; /* To not let the highlight point on a title. */ if (global.result_offset) global.result_offset--; } global.result_highlight = highlight; draw_result_text(connection, window, cairo_context, cairo_surface, global.results); } break; case 65364: /* Down. */ if (!global.result_count) break; if (highlight < global.result_count - 1) { old_pos = highlight; get_next_non_title(&highlight); if (highlight == global.result_count) { /* If no other result with an action can be found, it just inc the * the offset so it can show the hidden title and make the highlight to the * previous non_title. * NB: If the offset limit is exceed, it's handled by the draw_result_text function. */ highlight = old_pos; global.result_offset++; } global.result_highlight = highlight; draw_result_text(connection, window, cairo_context, cairo_surface, global.results); } break; case 65289: /* Tab. */ if (!global.result_count) break; get_next_line(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); break; case 65056: /* Shift Tab */ if (!global.result_count) break; get_previous_line(&highlight); draw_result_text(connection, window, cairo_context, cairo_surface, global.results); break; case 65307: /* Escape. */ goto cleanup; case 65288: /* Backspace. */ if (*query_index > 0 && *query_cursor_index > 0) { memmove(&query_buffer[(*query_cursor_index) - 1], &query_buffer[*query_cursor_index], *query_index - *query_cursor_index + 1); (*query_cursor_index)--; (*query_index)--; query_buffer[(*query_index)] = 0; redraw = 1; resend = 1; } else if (*query_index == 0 && settings.backspace_exit) { /* Backspace with nothing */ goto cleanup; } break; default: if (isprint((char)key) && *query_index < MAX_QUERY) { memmove(&query_buffer[(*query_cursor_index) + 1], &query_buffer[*query_cursor_index], *query_index - *query_cursor_index + 1); query_buffer[(*query_cursor_index)++] = key; (*query_index)++; redraw = 1; resend = 1; } break; } } if (redraw) { draw_query_text(cairo_context, cairo_surface, query_buffer, *query_cursor_index); xcb_flush(connection); } if (resend) { if (write_to_remote(to_write, "%s\n", query_buffer)) { fprintf(stderr, "Failed to write.\n"); } } pthread_mutex_unlock(&global.result_mutex); return 1; cleanup: pthread_mutex_unlock(&global.result_mutex); return 0; }
bool Window_mac::handleEvent(const SDL_Event& event) { switch (event.type) { case SDL_WINDOWEVENT: if (SDL_WINDOWEVENT_EXPOSED == event.window.event) { this->onPaint(); } else if (SDL_WINDOWEVENT_RESIZED == event.window.event) { this->onResize(event.window.data1, event.window.data2); } break; case SDL_MOUSEBUTTONDOWN: if (event.button.button == SDL_BUTTON_LEFT) { this->onMouse(event.button.x, event.button.y, Window::kDown_InputState, get_modifiers(event)); } break; case SDL_MOUSEBUTTONUP: if (event.button.button == SDL_BUTTON_LEFT) { this->onMouse(event.button.x, event.button.y, Window::kUp_InputState, get_modifiers(event)); } break; case SDL_MOUSEMOTION: this->onMouse(event.motion.x, event.motion.y, Window::kMove_InputState, get_modifiers(event)); break; case SDL_MOUSEWHEEL: this->onMouseWheel(event.wheel.y, get_modifiers(event)); break; case SDL_KEYDOWN: { Window::Key key = get_key(event.key.keysym); if (key != Window::Key::kNONE) { if (!this->onKey(key, Window::kDown_InputState, get_modifiers(event))) { if (event.key.keysym.sym == SDLK_ESCAPE) { return true; } } } } break; case SDL_KEYUP: { Window::Key key = get_key(event.key.keysym); if (key != Window::Key::kNONE) { (void) this->onKey(key, Window::kUp_InputState, get_modifiers(event)); } } break; case SDL_TEXTINPUT: { const char* textIter = &event.text.text[0]; while (SkUnichar c = SkUTF8_NextUnichar(&textIter)) { (void) this->onChar(c, get_modifiers(event)); } } break; default: break; } return false; }
void setup_modifiers(){ for(int i=0;i<sizeof(keybindings)/sizeof(event_t);i++){ keybindings[i].modifiers=get_modifiers(keybindings[i].keycode); } }
bool Window_mac::handleEvent(const XEvent& event) { switch (event.type) { case MapNotify: if (!fGC) { fGC = XCreateGC(fDisplay, fWindow, 0, nullptr); } break; case ClientMessage: if ((Atom)event.xclient.data.l[0] == fWmDeleteMessage && gWindowMap.count() == 1) { return true; } break; case ButtonPress: if (event.xbutton.button == Button1) { this->onMouse(event.xbutton.x, event.xbutton.y, Window::kDown_InputState, get_modifiers(event)); } break; case ButtonRelease: if (event.xbutton.button == Button1) { this->onMouse(event.xbutton.x, event.xbutton.y, Window::kUp_InputState, get_modifiers(event)); } break; case MotionNotify: // only track if left button is down if (event.xmotion.state & Button1Mask) { this->onMouse(event.xmotion.x, event.xmotion.y, Window::kMove_InputState, get_modifiers(event)); } break; case KeyPress: { int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0; KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode, 0, shiftLevel); if (keysym == XK_Escape) { return true; } Window::Key key = get_key(keysym); if (key != Window::Key::kNONE) { (void) this->onKey(key, Window::kDown_InputState, get_modifiers(event)); } else { long uni = keysym2ucs(keysym); if (uni != -1) { (void) this->onChar((SkUnichar) uni, get_modifiers(event)); } } } break; case KeyRelease: { int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0; KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode, 0, shiftLevel); Window::Key key = get_key(keysym); (void) this->onKey(key, Window::kUp_InputState, get_modifiers(event)); } break; default: // these events should be handled in the main event loop SkASSERT(event.type != Expose && event.type != ConfigureNotify); break; } return false; }
Array f_hphp_get_class_info(CVarRef name) { String className; if (name.isObject()) { className = name.toObject()->o_getClassName(); } else { className = name.toString(); } const ClassInfo *cls = ClassInfo::FindClass(className); if (cls == NULL) { cls = ClassInfo::FindInterface(className); } if (cls == NULL) { cls = ClassInfo::FindTrait(className); } Array ret; if (cls == NULL) { return ret; } ret.set("name", cls->getName()); ret.set("extension", ""); ret.set("parent", cls->getParentClass()); // interfaces { Array arr = Array::Create(); const ClassInfo::InterfaceVec &interfaces = cls->getInterfacesVec(); for (ClassInfo::InterfaceVec::const_iterator iter = interfaces.begin(); iter != interfaces.end(); ++iter) { arr.set(*iter, 1); } ret.set("interfaces", arr); } // traits { Array arr = Array::Create(); const ClassInfo::TraitVec &traits = cls->getTraitsVec(); for (ClassInfo::TraitVec::const_iterator iter = traits.begin(); iter != traits.end(); ++iter) { arr.set(*iter, 1); } ret.set("traits", arr); } // trait aliases { Array arr = Array::Create(); const ClassInfo::TraitAliasVec &aliases = cls->getTraitAliasesVec(); for (ClassInfo::TraitAliasVec::const_iterator iter = aliases.begin(); iter != aliases.end(); ++iter) { arr.set(iter->first, iter->second); } ret.set("trait_aliases", arr); } // attributes { int attribute = cls->getAttribute(); ret.set("internal", (bool)(attribute & ClassInfo::IsSystem)); ret.set("hphp", (bool)(attribute & ClassInfo::HipHopSpecific)); ret.set("abstract", (bool)(attribute & ClassInfo::IsAbstract)); ret.set("interface", (bool)(attribute & ClassInfo::IsInterface)); ret.set("final", (bool)(attribute & ClassInfo::IsFinal)); ret.set("trait", (bool)(attribute & ClassInfo::IsTrait)); ret.set("modifiers", get_modifiers(attribute, true)); } // methods { Array arr = Array::Create(); const ClassInfo::MethodVec &methods = cls->getMethodsVec(); for (ClassInfo::MethodVec::const_iterator iter = methods.begin(); iter != methods.end(); ++iter) { ClassInfo::MethodInfo *m = *iter; if ((m->attribute & ClassInfo::IsInherited) == 0) { Array info = Array::Create(); set_method_info(info, m, cls); arr.set(StringUtil::ToLower(m->name), info); } } ret.set("methods", arr); } // properties { Array arr = Array::Create(); const ClassInfo::PropertyVec &properties = cls->getPropertiesVec(); for (ClassInfo::PropertyVec::const_iterator iter = properties.begin(); iter != properties.end(); ++iter) { ClassInfo::PropertyInfo *prop = *iter; Array info = Array::Create(); set_property_info(info, prop, cls); arr.set(prop->name, info); } ret.set("properties", arr); } // constants { Array arr = Array::Create(); const ClassInfo::ConstantVec &constants = cls->getConstantsVec(); for (ClassInfo::ConstantVec::const_iterator iter = constants.begin(); iter != constants.end(); ++iter) { ClassInfo::ConstantInfo *info = *iter; if (info->valueText && *info->valueText) { arr.set(info->name, info->getValue()); } else { arr.set(info->name, get_class_constant(className, info->name)); } } ret.set("constants", arr); } { // source info if (!set_source_info(ret, cls->getFile(), cls->getLine1(), cls->getLine2())) { int line = 0; const char *file = SourceInfo::TheSourceInfo. getClassDeclaringFile(className, &line); set_source_info(ret, file, line, line); } set_doc_comment(ret, cls->getDocComment()); } return ret; }
Array f_hphp_get_class_info(CVarRef name) { String className; if (name.isObject()) { className = name.toObject()->o_getClassName(); } else { className = name.toString(); } const ClassInfo *cls = ClassInfo::FindClass(className.data()); if (cls == NULL) { cls = ClassInfo::FindInterface(className.data()); } Array ret; if (cls == NULL) { return ret; } ret.set("name", cls->getName()); ret.set("extension", ""); ret.set("parent", cls->getParentClass()); // interfaces { Array arr = Array::Create(); const ClassInfo::InterfaceMap &interfaces = cls->getInterfaces(); for (ClassInfo::InterfaceMap::const_iterator iter = interfaces.begin(); iter != interfaces.end(); ++iter) { arr.set(*iter, 1); } ret.set("interfaces", arr); } // attributes { int attribute = cls->getAttribute(); ret.set("internal", (bool)(attribute & ClassInfo::IsSystem)); ret.set("abstract", (bool)(attribute & ClassInfo::IsAbstract)); ret.set("interface", (bool)(attribute & ClassInfo::IsInterface)); ret.set("final", (bool)(attribute & ClassInfo::IsFinal)); ret.set("modifiers", get_modifiers(attribute, true)); } // methods { Array arr = Array::Create(); const ClassInfo::MethodVec &methods = cls->getMethodsVec(); for (ClassInfo::MethodVec::const_iterator iter = methods.begin(); iter != methods.end(); ++iter) { ClassInfo::MethodInfo *m = *iter; if ((m->attribute & ClassInfo::IsInherited) == 0) { Array info = Array::Create(); set_method_info(info, m, cls); arr.set(StringUtil::ToLower(m->name), info); } } ret.set("methods", arr); } // properties { Array arr = Array::Create(); const ClassInfo::PropertyMap &properties = cls->getProperties(); for (ClassInfo::PropertyMap::const_iterator iter = properties.begin(); iter != properties.end(); ++iter) { Array info = Array::Create(); set_property_info(info, iter->second, cls); arr.set(iter->first, info); } ret.set("properties", arr); } // constants { Array arr = Array::Create(); const ClassInfo::ConstantMap &constants = cls->getConstants(); for (ClassInfo::ConstantMap::const_iterator iter = constants.begin(); iter != constants.end(); ++iter) { if (iter->second->valueText && *iter->second->valueText) { arr.set(iter->second->name, iter->second->value); } else { arr.set(iter->second->name, get_class_constant(className.data(), iter->second->name)); } } ret.set("constants", arr); } { // source info const char *file = SourceInfo::TheSourceInfo.getClassDeclaringFile(className.data()); if (!file) file = ""; if (file[0] != '/') { ret.set("file", String(RuntimeOption::SourceRoot + file)); } else { ret.set("file", file); } ret.set("line1", 0); ret.set("line2", 0); const char *dc = cls->getDocComment(); if (dc) { ret.set("doc", dc); } else { ret.set("doc", false); } } return ret; }
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 {