void SDL_EVDEV_Poll(void) { struct input_event events[32]; int i, j, len; SDL_evdevlist_item *item; SDL_Scancode scan_code; int mouse_button; SDL_Mouse *mouse; float norm_x, norm_y; if (!_this) { return; } #if SDL_USE_LIBUDEV SDL_UDEV_Poll(); #endif mouse = SDL_GetMouse(); for (item = _this->first; item != NULL; item = item->next) { while ((len = read(item->fd, events, (sizeof events))) > 0) { len /= sizeof(events[0]); for (i = 0; i < len; ++i) { /* special handling for touchscreen, that should eventually be used for all devices */ if (item->out_of_sync && item->is_touchscreen && events[i].type == EV_SYN && events[i].code != SYN_REPORT) { break; } switch (events[i].type) { case EV_KEY: if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) { mouse_button = events[i].code - BTN_MOUSE; if (events[i].value == 0) { SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]); } else if (events[i].value == 1) { SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]); } break; } /* Probably keyboard */ scan_code = SDL_EVDEV_translate_keycode(events[i].code); if (scan_code != SDL_SCANCODE_UNKNOWN) { if (events[i].value == 0) { SDL_SendKeyboardKey(SDL_RELEASED, scan_code); } else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) { SDL_SendKeyboardKey(SDL_PRESSED, scan_code); #ifdef SDL_INPUT_LINUXKD SDL_EVDEV_do_text_input(events[i].code); #endif /* SDL_INPUT_LINUXKD */ } } break; case EV_ABS: switch(events[i].code) { case ABS_MT_SLOT: if (!item->is_touchscreen) /* FIXME: temp hack */ break; item->touchscreen_data->current_slot = events[i].value; break; case ABS_MT_TRACKING_ID: if (!item->is_touchscreen) /* FIXME: temp hack */ break; if (events[i].value >= 0) { item->touchscreen_data->slots[item->touchscreen_data->current_slot].tracking_id = events[i].value; item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_DOWN; } else { item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_UP; } break; case ABS_MT_POSITION_X: if (!item->is_touchscreen) /* FIXME: temp hack */ break; item->touchscreen_data->slots[item->touchscreen_data->current_slot].x = events[i].value; if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) { item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE; } break; case ABS_MT_POSITION_Y: if (!item->is_touchscreen) /* FIXME: temp hack */ break; item->touchscreen_data->slots[item->touchscreen_data->current_slot].y = events[i].value; if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) { item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE; } break; case ABS_X: if (item->is_touchscreen) /* FIXME: temp hack */ break; SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y); break; case ABS_Y: if (item->is_touchscreen) /* FIXME: temp hack */ break; SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value); break; default: break; } break; case EV_REL: switch(events[i].code) { case REL_X: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, events[i].value, 0); break; case REL_Y: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value); break; case REL_WHEEL: SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value, SDL_MOUSEWHEEL_NORMAL); break; case REL_HWHEEL: SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL); break; default: break; } break; case EV_SYN: switch (events[i].code) { case SYN_REPORT: if (!item->is_touchscreen) /* FIXME: temp hack */ break; for(j = 0; j < item->touchscreen_data->max_slots; j++) { norm_x = (float)(item->touchscreen_data->slots[j].x - item->touchscreen_data->min_x) / (float)item->touchscreen_data->range_x; norm_y = (float)(item->touchscreen_data->slots[j].y - item->touchscreen_data->min_y) / (float)item->touchscreen_data->range_y; switch(item->touchscreen_data->slots[j].delta) { case EVDEV_TOUCH_SLOTDELTA_DOWN: SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_TRUE, norm_x, norm_y, 1.0f); item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE; break; case EVDEV_TOUCH_SLOTDELTA_UP: SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_FALSE, norm_x, norm_y, 1.0f); item->touchscreen_data->slots[j].tracking_id = -1; item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE; break; case EVDEV_TOUCH_SLOTDELTA_MOVE: SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, norm_x, norm_y, 1.0f); item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE; break; default: break; } } if (item->out_of_sync) item->out_of_sync = 0; break; case SYN_DROPPED: if (item->is_touchscreen) item->out_of_sync = 1; SDL_EVDEV_sync_device(item); break; default: break; } break; } } } } }
void SDL_EVDEV_Poll(void) { struct input_event events[32]; int i, len; SDL_evdevlist_item *item; SDL_Scancode scan_code; int mouse_button; SDL_Mouse *mouse; #ifdef SDL_INPUT_LINUXKD Uint16 modstate; struct kbentry kbe; static char keysym[8]; char *end; Uint32 kval; #endif #if SDL_USE_LIBUDEV SDL_UDEV_Poll(); #endif mouse = SDL_GetMouse(); for (item = _this->first; item != NULL; item = item->next) { while ((len = read(item->fd, events, (sizeof events))) > 0) { len /= sizeof(events[0]); for (i = 0; i < len; ++i) { switch (events[i].type) { case EV_KEY: if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) { mouse_button = events[i].code - BTN_MOUSE; if (events[i].value == 0) { SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]); } else if (events[i].value == 1) { SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]); } break; } /* Probably keyboard */ scan_code = SDL_EVDEV_translate_keycode(events[i].code); if (scan_code != SDL_SCANCODE_UNKNOWN) { if (events[i].value == 0) { SDL_SendKeyboardKey(SDL_RELEASED, scan_code); } else if (events[i].value == 1 || events[i].value == 2 /* Key repeated */ ) { SDL_SendKeyboardKey(SDL_PRESSED, scan_code); #ifdef SDL_INPUT_LINUXKD if (_this->console_fd >= 0) { kbe.kb_index = events[i].code; /* Convert the key to an UTF-8 char */ /* Ref: http://www.linuxjournal.com/article/2783 */ modstate = SDL_GetModState(); kbe.kb_table = 0; /* Ref: http://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching */ kbe.kb_table |= -( (modstate & KMOD_LCTRL) != 0) & (1 << KG_CTRLL | 1 << KG_CTRL); kbe.kb_table |= -( (modstate & KMOD_RCTRL) != 0) & (1 << KG_CTRLR | 1 << KG_CTRL); kbe.kb_table |= -( (modstate & KMOD_LSHIFT) != 0) & (1 << KG_SHIFTL | 1 << KG_SHIFT); kbe.kb_table |= -( (modstate & KMOD_RSHIFT) != 0) & (1 << KG_SHIFTR | 1 << KG_SHIFT); kbe.kb_table |= -( (modstate & KMOD_LALT) != 0) & (1 << KG_ALT); kbe.kb_table |= -( (modstate & KMOD_RALT) != 0) & (1 << KG_ALTGR); if (ioctl(_this->console_fd, KDGKBENT, (unsigned long)&kbe) == 0 && ((KTYP(kbe.kb_value) == KT_LATIN) || (KTYP(kbe.kb_value) == KT_ASCII) || (KTYP(kbe.kb_value) == KT_LETTER))) { kval = KVAL(kbe.kb_value); /* While there's a KG_CAPSSHIFT symbol, it's not useful to build the table index with it * because 1 << KG_CAPSSHIFT overflows the 8 bits of kb_table * So, we do the CAPS LOCK logic here. Note that isalpha depends on the locale! */ if ( modstate & KMOD_CAPS && isalpha(kval) ) { if ( isupper(kval) ) { kval = tolower(kval); } else { kval = toupper(kval); } } /* Convert to UTF-8 and send */ end = SDL_UCS4ToUTF8( kval, keysym); *end = '\0'; SDL_SendKeyboardText(keysym); } } #endif /* SDL_INPUT_LINUXKD */ } } break; case EV_ABS: switch(events[i].code) { case ABS_X: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y); break; case ABS_Y: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value); break; default: break; } break; case EV_REL: switch(events[i].code) { case REL_X: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, events[i].value, 0); break; case REL_Y: SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value); break; case REL_WHEEL: SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value); break; case REL_HWHEEL: SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0); break; default: break; } break; case EV_SYN: switch (events[i].code) { case SYN_DROPPED: SDL_EVDEV_sync_device(item); break; default: break; } break; } } } } }