/** Get KeySymbol from a KeyCode according to its state */ xcb_keysym_t get_keysym(xcb_keycode_t keycode, uint16_t state) { xcb_keysym_t k0, k1; /* Mode_Switch is ON */ if (state & nil_.mask_modeswitch) { k0 = xcb_key_symbols_get_keysym(nil_.key_syms, keycode, 2); k1 = xcb_key_symbols_get_keysym(nil_.key_syms, keycode, 3); } else { k0 = xcb_key_symbols_get_keysym(nil_.key_syms, keycode, 0); k1 = xcb_key_symbols_get_keysym(nil_.key_syms, keycode, 1); } if (k1 == XCB_NO_SYMBOL) { k1 = k0; } /* NUM on and is from keypad */ if ((state & nil_.mask_numlock) && xcb_is_keypad_key(k1)) { if ((state & XCB_MOD_MASK_SHIFT) || ((state & XCB_MOD_MASK_LOCK) && (state & nil_.mask_shiftlock))) { return k0; } else { return k1; } } if (!(state & XCB_MOD_MASK_SHIFT)) { if (!(state & XCB_MOD_MASK_LOCK)) { /* SHIFT off, CAPS off */ return k0; } else if (state & nil_.mask_capslock) { /* SHIFT off, CAPS on */ return k1; } } else { return k1; } NIL_ERR("no symbol: state=0x%x keycode=0x%x", state, keycode); return XCB_NO_SYMBOL; }
chord_t *make_chord(xcb_keysym_t keysym, xcb_button_t button, uint16_t modfield, uint8_t event_type, bool replay_event, bool lock_chain) { chord_t *chord; if (button == XCB_NONE) { chord_t *prev = NULL; chord_t *orig = NULL; xcb_keycode_t *keycodes = keycodes_from_keysym(keysym); if (keycodes != NULL) for (xcb_keycode_t *kc = keycodes; *kc != XCB_NO_SYMBOL; kc++) { xcb_keysym_t natural_keysym = xcb_key_symbols_get_keysym(symbols, *kc, 0); for (unsigned char col = 0; col < KEYSYMS_PER_KEYCODE; col++) { xcb_keysym_t ks = xcb_key_symbols_get_keysym(symbols, *kc, col); if (ks == keysym) { uint16_t implicit_modfield = (col & 1 ? XCB_MOD_MASK_SHIFT : 0) | (col & 2 ? modfield_from_keysym(Mode_switch) : 0); uint16_t explicit_modfield = modfield | implicit_modfield; chord = malloc(sizeof(chord_t)); bool unique = true; for (chord_t *c = orig; unique && c != NULL; c = c->more) if (c->modfield == explicit_modfield && c->keysym == natural_keysym) unique = false; if (!unique) { free(chord); break; } chord->keysym = natural_keysym; chord->button = button; chord->modfield = explicit_modfield; chord->next = chord->more = NULL; chord->event_type = event_type; chord->replay_event = replay_event; chord->lock_chain = lock_chain; if (prev != NULL) prev->more = chord; else orig = chord; prev = chord; PRINTF("key chord %u %u\n", natural_keysym, explicit_modfield); break; } } } free(keycodes); chord = orig; } else { chord = malloc(sizeof(chord_t)); chord->keysym = keysym; chord->button = button; chord->modfield = modfield; chord->event_type = event_type; chord->replay_event = replay_event; chord->lock_chain = lock_chain; chord->next = chord->more = NULL; PRINTF("button chord %u %u\n", button, modfield); } return chord; }
xcb_keysym_t xcb_key_release_lookup_keysym (xcb_key_symbols_t *syms, xcb_key_release_event_t *event, int col) { return xcb_key_symbols_get_keysym (syms, event->detail, col); }
/** The key press event handler. * \param ev The event. */ static void event_handle_key(xcb_key_press_event_t *ev) { lua_State *L = globalconf_get_lua_State(); globalconf.timestamp = ev->time; if(globalconf.keygrabber != LUA_REFNIL) { if(keygrabber_handlekpress(L, ev)) { lua_rawgeti(L, LUA_REGISTRYINDEX, globalconf.keygrabber); if(!luaA_dofunction(L, 3, 0)) { warn("Stopping keygrabber."); luaA_keygrabber_stop(L); } } } else { /* get keysym ignoring all modifiers */ xcb_keysym_t keysym = xcb_key_symbols_get_keysym(globalconf.keysyms, ev->detail, 0); client_t *c; if((c = client_getbywin(ev->event)) || (c = client_getbynofocuswin(ev->event))) { luaA_object_push(L, c); event_key_callback(ev, &c->keys, L, -1, 1, &keysym); } else event_key_callback(ev, &globalconf.keys, L, 0, 0, &keysym); } }
/** Handle keypress event. * \param L Lua stack to push the key pressed. * \param e Received XKeyEvent. * \return True if a key was successfully retrieved, false otherwise. */ bool keygrabber_handlekpress(lua_State *L, xcb_key_press_event_t *e) { /* convert keysym to string */ char buf[MAX(MB_LEN_MAX, 32)]; /* snprintf-like return value could be used here, but that should not be * necessary, as we have buffer big enough */ xkb_state_key_get_utf8(globalconf.xkb_state, e->detail, buf, countof(buf) ); if (is_control(buf)) { /* Use text names for control characters, ignoring all modifiers. */ xcb_keysym_t keysym = xcb_key_symbols_get_keysym(globalconf.keysyms, e->detail, 0); xkb_keysym_get_name(keysym, buf, countof(buf)); } luaA_pushmodifiers(L, e->state); lua_pushstring(L, buf); switch(e->response_type) { case XCB_KEY_PRESS: lua_pushliteral(L, "press"); break; case XCB_KEY_RELEASE: lua_pushliteral(L, "release"); break; } return true; }
xcb_keysym_t XcbIn::keysym(xcb_keycode_t code) const { xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(connection); // xcb_keysym_t sym = xcb_key_press_lookup_keysym(symbols, kpe, kpe->state); xcb_keysym_t sym = xcb_key_symbols_get_keysym(symbols, code, 0); xcb_key_symbols_free(symbols); return sym; }
static void handle_key_press(xcb_key_press_event_t *e) { xcb_keysym_t sym; NIL_LOG("event: key press %d %d", e->state, e->detail); sym = xcb_key_symbols_get_keysym(nil_.key_syms, e->detail, 0); /* find key with *LOCK state removed */ if (check_key(MOD_MASK_(e->state), sym)) { xcb_flush(nil_.con); return; } }
static xcb_keysym_t xcb_get_keysym (xcb_keysym_t keycode) { xcb_key_symbols_t *keysyms; xcb_keysym_t keysym; if (!(keysyms = xcb_key_symbols_alloc(conn))) return 0; keysym = xcb_key_symbols_get_keysym(keysyms, (unsigned char)keycode, 0); xcb_key_symbols_free(keysyms); return keysym; }
void grab_chord(chord_t *chord) { for (chord_t *c = chord; c != NULL; c = c->more) { if (c->button == XCB_NONE) { xcb_keycode_t *keycodes = keycodes_from_keysym(c->keysym); if (keycodes != NULL) for (xcb_keycode_t *kc = keycodes; *kc != XCB_NO_SYMBOL; kc++) if (c->keysym == xcb_key_symbols_get_keysym(symbols, *kc, 0)) grab_key_button(*kc, c->button, c->modfield); free(keycodes); } else { grab_key_button(XCB_NONE, c->button, c->modfield); } } }
xcb_keysym_t keyboard::get_keysym( xcb_keycode_t code, uint16_t state ) { xcb_keysym_t k0, k1; if ( state & _modeswitch ) { k0 = xcb_key_symbols_get_keysym( _keysyms, code, 2 ); k1 = xcb_key_symbols_get_keysym( _keysyms, code, 3 ); } else { k0 = xcb_key_symbols_get_keysym( _keysyms, code, 0 ); k1 = xcb_key_symbols_get_keysym( _keysyms, code, 1 ); } if ( k1 == XCB_NO_SYMBOL ) k1 = k0; if ( ( state & _numlock ) && xcb_is_keypad_key( k1 ) ) { if( ( state & XCB_MOD_MASK_SHIFT ) || (state & XCB_MOD_MASK_LOCK && ( state & _shiftlock ) ) ) return k0; else return k1; } else if ( ! ( state & XCB_MOD_MASK_SHIFT ) && ! ( state & XCB_MOD_MASK_LOCK ) ) return k0; else if ( ! ( state & XCB_MOD_MASK_SHIFT ) && ( state & XCB_MOD_MASK_LOCK && ( state & _capslock ) ) ) return k1; else if ( ( state & XCB_MOD_MASK_SHIFT ) && ( state & XCB_MOD_MASK_LOCK && ( state & _capslock ) ) ) return k1; else if ( ( state & XCB_MOD_MASK_SHIFT ) || ( state & XCB_MOD_MASK_LOCK && ( state & _shiftlock ) ) ) return k1; return XCB_NO_SYMBOL; }
void event_keypress( xcb_generic_event_t* e ) { xcb_key_press_event_t * ev = (xcb_key_press_event_t*)e; timestamp = ev->time; xcb_keysym_t keysym = xcb_key_symbols_get_keysym( symbols, ev->detail, 0 ); printf( "yawn: keypress %i %i %i\n", ev->detail, keysym, ev->state ); int i = 0; printf( "keybinding count: %i\n", bindingsCount ); for ( i = 0; i < bindingsCount; ++i ) { struct keybinding_t k = keybindings[ i ]; printf( "key sym: %i state: %i\n", k.key, k.state ); if ( k.key == keysym && ev->state & k.state ) { printf( "found key binding! calling callback! %i %s\n", k.argc, k.argv[ 0 ] ); k.callback( k.argc, k.argv ); } } }
/* * Returns true if sym is bound to any key except for 'except_keycode' on the * first four layers (normal, shift, mode_switch, mode_switch + shift). * */ static bool keysym_used_on_other_key(KeySym sym, xcb_keycode_t except_keycode) { xcb_keycode_t i, min_keycode = xcb_get_setup(conn)->min_keycode, max_keycode = xcb_get_setup(conn)->max_keycode; for (i = min_keycode; i && i <= max_keycode; i++) { if (i == except_keycode) continue; for (int level = 0; level < 4; level++) { if (xcb_key_symbols_get_keysym(keysyms, i, level) != sym) continue; return true; } } return false; }
xcb_keycode_t * xcb_key_symbols_get_keycode(xcb_key_symbols_t *syms, xcb_keysym_t keysym) { xcb_keysym_t ks; int j, nresult = 0; xcb_keycode_t i, min, max, *result = NULL, *result_np = NULL; if(syms && !xcb_connection_has_error(syms->c)) { xcb_key_symbols_get_reply (syms, NULL); min = xcb_get_setup(syms->c)->min_keycode; max = xcb_get_setup(syms->c)->max_keycode; if (!syms->u.reply) return NULL; for(i = min; i && i <= max; i++) for(j = 0; j < syms->u.reply->keysyms_per_keycode; j++) { ks = xcb_key_symbols_get_keysym(syms, i, j); if(ks == keysym) { nresult++; result_np = realloc(result, sizeof(xcb_keycode_t) * (nresult + 1)); if(result_np == NULL) { free(result); return NULL; } result = result_np; result[nresult - 1] = i; result[nresult] = XCB_NO_SYMBOL; break; } } } return result; }
int handle_key_press_event(void *data, xcb_connection_t *c, xcb_key_press_event_t *event) { xcb_keycode_t keycode = event->detail; xcb_keysym_t keysym = xcb_key_symbols_get_keysym(wm_conf.key_syms, keycode, 0); fprintf(stderr, "key press: keycode %u, keysym %u, state %u\n", keycode, keysym, event->state); /* search key bindings */ SCM key_proc = SCM_UNDEFINED; keybinding_t *binding = keybinding_list; while (binding) { if (binding->keysym == keysym && binding->mod_mask == event->state) { key_proc = binding->scm_proc; } binding = binding->next; } if (key_proc != SCM_UNDEFINED) scm_call_0(key_proc); return 0; }
static int _e_alert_handle_key_press(xcb_generic_event_t *event) { xcb_key_symbols_t *symbols; xcb_key_press_event_t *ev; xcb_keysym_t key; int r = 0; ev = (xcb_key_press_event_t *)event; symbols = xcb_key_symbols_alloc(conn); key = xcb_key_symbols_get_keysym(symbols, ev->detail, 0); if (key == XK_F1) r = 1; else if (key == XK_F12) r = 2; xcb_key_symbols_free(symbols); return r; }
void WindowSelector::handleKeyPress(xcb_keycode_t keycode, uint16_t state) { xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(connection()); xcb_keysym_t kc = xcb_key_symbols_get_keysym(symbols, keycode, 0); int mx = 0; int my = 0; const bool returnPressed = (kc == XK_Return) || (kc == XK_space); const bool escapePressed = (kc == XK_Escape); if (kc == XK_Left) { mx = -10; } if (kc == XK_Right) { mx = 10; } if (kc == XK_Up) { my = -10; } if (kc == XK_Down) { my = 10; } if (state & XCB_MOD_MASK_CONTROL) { mx /= 10; my /= 10; } Cursor::setPos(Cursor::pos() + QPoint(mx, my)); if (returnPressed) { selectWindowUnderPointer(); } if (returnPressed || escapePressed) { if (escapePressed) { m_callback(nullptr); } release(); } xcb_key_symbols_free(symbols); }
void X11WindowedBackend::handleEvent(xcb_generic_event_t *e) { const uint8_t eventType = e->response_type & ~0x80; switch (eventType) { case XCB_BUTTON_PRESS: case XCB_BUTTON_RELEASE: handleButtonPress(reinterpret_cast<xcb_button_press_event_t*>(e)); break; case XCB_MOTION_NOTIFY: { auto event = reinterpret_cast<xcb_motion_notify_event_t*>(e); auto it = std::find_if(m_windows.constBegin(), m_windows.constEnd(), [event] (const Output &o) { return o.window == event->event; }); if (it == m_windows.constEnd()) { break; } pointerMotion(QPointF(event->root_x - (*it).xPosition.x() + (*it).internalPosition.x(), event->root_y - (*it).xPosition.y() + (*it).internalPosition.y()), event->time); } break; case XCB_KEY_PRESS: case XCB_KEY_RELEASE: { auto event = reinterpret_cast<xcb_key_press_event_t*>(e); if (eventType == XCB_KEY_PRESS) { if (!m_keySymbols) { m_keySymbols = xcb_key_symbols_alloc(m_connection); } const xcb_keysym_t kc = xcb_key_symbols_get_keysym(m_keySymbols, event->detail, 0); if (kc == XK_Control_R) { grabKeyboard(event->time); } keyboardKeyPressed(event->detail - 8, event->time); } else { keyboardKeyReleased(event->detail - 8, event->time); } } break; case XCB_CONFIGURE_NOTIFY: updateSize(reinterpret_cast<xcb_configure_notify_event_t*>(e)); break; case XCB_ENTER_NOTIFY: { auto event = reinterpret_cast<xcb_enter_notify_event_t*>(e); auto it = std::find_if(m_windows.constBegin(), m_windows.constEnd(), [event] (const Output &o) { return o.window == event->event; }); if (it == m_windows.constEnd()) { break; } pointerMotion(QPointF(event->root_x - (*it).xPosition.x() + (*it).internalPosition.x(), event->root_y - (*it).xPosition.y() + (*it).internalPosition.y()), event->time); } break; case XCB_CLIENT_MESSAGE: handleClientMessage(reinterpret_cast<xcb_client_message_event_t*>(e)); break; case XCB_EXPOSE: handleExpose(reinterpret_cast<xcb_expose_event_t*>(e)); break; case XCB_MAPPING_NOTIFY: if (m_keySymbols) { xcb_refresh_keyboard_mapping(m_keySymbols, reinterpret_cast<xcb_mapping_notify_event_t*>(e)); } break; default: break; } }
/** Return the keysym from keycode. * \param detail The keycode received. * \param state The modifier state. * \return A keysym. */ xcb_keysym_t keyresolv_get_keysym(xcb_keycode_t detail, uint16_t state) { xcb_keysym_t k0, k1; /* 'col' (third parameter) is used to get the proper KeySym * according to modifier (XCB doesn't provide an equivalent to * XLookupString()). * * If Mode_Switch is ON we look into second group. */ if(state & globalconf.modeswitchmask) { k0 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 4); k1 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 5); } else { k0 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 0); k1 = xcb_key_symbols_get_keysym(globalconf.keysyms, detail, 1); } /* If the second column does not exists use the first one. */ if(k1 == XCB_NO_SYMBOL) k1 = k0; /* The numlock modifier is on and the second KeySym is a keypad * KeySym */ if((state & globalconf.numlockmask) && xcb_is_keypad_key(k1)) { /* The Shift modifier is on, or if the Lock modifier is on and * is interpreted as ShiftLock, use the first KeySym */ if((state & XCB_MOD_MASK_SHIFT) || (state & XCB_MOD_MASK_LOCK && (state & globalconf.shiftlockmask))) return k0; else return k1; } /* The Shift and Lock modifers are both off, use the first * KeySym */ else if(!(state & XCB_MOD_MASK_SHIFT) && !(state & XCB_MOD_MASK_LOCK)) return k0; /* The Shift modifier is off and the Lock modifier is on and is * interpreted as CapsLock */ else if(!(state & XCB_MOD_MASK_SHIFT) && (state & XCB_MOD_MASK_LOCK && (state & globalconf.capslockmask))) /* The first Keysym is used but if that KeySym is lowercase * alphabetic, then the corresponding uppercase KeySym is used * instead */ return k1; /* The Shift modifier is on, and the Lock modifier is on and is * interpreted as CapsLock */ else if((state & XCB_MOD_MASK_SHIFT) && (state & XCB_MOD_MASK_LOCK && (state & globalconf.capslockmask))) /* The second Keysym is used but if that KeySym is lowercase * alphabetic, then the corresponding uppercase KeySym is used * instead */ return k1; /* The Shift modifier is on, or the Lock modifier is on and is * interpreted as ShiftLock, or both */ else if((state & XCB_MOD_MASK_SHIFT) || (state & XCB_MOD_MASK_LOCK && (state & globalconf.shiftlockmask))) return k1; return XCB_NO_SYMBOL; }
void ae3d::Window::PumpEvents() { xcb_generic_event_t* event; while ((event = xcb_poll_for_event( WindowGlobal::connection ))) { //const bool synthetic_event = (event->response_type & 0x80) != 0; const uint8_t response_type = event->response_type & ~0x80; switch (response_type) { case XCB_EVENT_MASK_BUTTON_PRESS: case XCB_EVENT_MASK_BUTTON_RELEASE: { const xcb_query_pointer_reply_t* pointer = xcb_query_pointer_reply( WindowGlobal::connection, xcb_query_pointer(WindowGlobal::connection, XDefaultRootWindow(WindowGlobal::display)), nullptr ); const bool newb1 = (pointer->mask & XCB_BUTTON_MASK_1) != 0; const bool newb2 = (pointer->mask & XCB_BUTTON_MASK_2) != 0; const bool newb3 = (pointer->mask & XCB_BUTTON_MASK_3) != 0; const xcb_button_press_event_t* be = (xcb_button_press_event_t*)event; const auto b1Type = response_type == XCB_EVENT_MASK_BUTTON_PRESS ? ae3d::WindowEventType::Mouse1Down : ae3d::WindowEventType::Mouse1Up; const auto b2Type = response_type == XCB_EVENT_MASK_BUTTON_PRESS ? ae3d::WindowEventType::Mouse2Down : ae3d::WindowEventType::Mouse2Up; const auto b3Type = response_type == XCB_EVENT_MASK_BUTTON_PRESS ? ae3d::WindowEventType::MouseMiddleDown : ae3d::WindowEventType::MouseMiddleUp; WindowGlobal::IncEventIndex(); if (newb1) { WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = b1Type; } else if (newb3) { WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = b2Type; } else if (newb2) { WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = b3Type; } else { std::cerr << "Unhandled mouse button." << std::endl; WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = b1Type; } WindowGlobal::eventStack[ WindowGlobal::eventIndex ].mouseX = be->event_x; WindowGlobal::eventStack[ WindowGlobal::eventIndex ].mouseY = be->event_y; } break; case XCB_KEY_PRESS: case XCB_KEY_RELEASE: { xcb_key_press_event_t *e = (xcb_key_press_event_t *)event; const bool isDown = (response_type == XCB_KEY_PRESS); const auto type = isDown ? ae3d::WindowEventType::KeyDown : ae3d::WindowEventType::KeyUp; WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = type; const xcb_keysym_t keysym = xcb_key_symbols_get_keysym(WindowGlobal::key_symbols, e->detail, 0); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].keyCode = WindowGlobal::keyMap[ keysym ]; } case XCB_MOTION_NOTIFY: { xcb_motion_notify_event_t* e = (xcb_motion_notify_event_t*)event; WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = ae3d::WindowEventType::MouseMove; WindowGlobal::eventStack[ WindowGlobal::eventIndex ].mouseX = e->event_x; WindowGlobal::eventStack[ WindowGlobal::eventIndex ].mouseY = e->event_y; break; } case XCB_CLIENT_MESSAGE: { xcb_client_message_event_t* client_message_event = (xcb_client_message_event_t*)event; if (client_message_event->type == WindowGlobal::wm_protocols) { if (client_message_event->data.data32[0] == WindowGlobal::wm_delete_window) { exit(1); break; } } break; } case XCB_EXPOSE: { } break; } } if (!WindowGlobal::gamePad.isActive) { return; } js_event j; while (read( WindowGlobal::gamePad.fd, &j, sizeof(js_event) ) == sizeof(js_event)) //read(WindowGlobal::gamePad.fd, &j, sizeof(js_event)); { // Don't care if init or afterwards j.type &= ~JS_EVENT_INIT; if (j.type == JS_EVENT_BUTTON) { if (j.number == WindowGlobal::gamePad.buttonA) { if (j.value > 0) { WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadButtonA; } } else if (j.number == WindowGlobal::gamePad.buttonB) { if (j.value > 0) { WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadButtonB; } } else if (j.number == WindowGlobal::gamePad.buttonX) { if (j.value > 0) { WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadButtonX; } } else if (j.number == WindowGlobal::gamePad.buttonY) { if (j.value > 0) { WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadButtonY; } } else if (j.number == WindowGlobal::gamePad.buttonStart) { if (j.value > 0) { WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadButtonStart; } } else if (j.number == WindowGlobal::gamePad.buttonBack) { if (j.value > 0) { WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadButtonBack; } } else { //std::cout << "pressed button " << (int)j.number << std::endl; } } else if (j.type == JS_EVENT_AXIS) { if (j.number == WindowGlobal::gamePad.leftThumbX) { float x = ProcessGamePadStickValue( j.value, WindowGlobal::gamePad.deadZone ); WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadLeftThumbState; WindowGlobal::eventStack[ WindowGlobal::eventIndex ].gamePadThumbX = x; WindowGlobal::eventStack[ WindowGlobal::eventIndex ].gamePadThumbY = WindowGlobal::lastLeftThumbY; WindowGlobal::lastLeftThumbX = x; } else if (j.number == WindowGlobal::gamePad.leftThumbY) { float y = ProcessGamePadStickValue( j.value, WindowGlobal::gamePad.deadZone ); WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadLeftThumbState; WindowGlobal::eventStack[ WindowGlobal::eventIndex ].gamePadThumbX = WindowGlobal::lastLeftThumbX; WindowGlobal::eventStack[ WindowGlobal::eventIndex ].gamePadThumbY = y; WindowGlobal::lastLeftThumbY = y; } else if (j.number == WindowGlobal::gamePad.dpadXaxis) { if (j.value > 0) { WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadButtonDPadRight; } if (j.value < 0) { WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadButtonDPadLeft; } } else if (j.number == WindowGlobal::gamePad.dpadYaxis) { if (j.value < 0) { WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadButtonDPadUp; } if (j.value > 0) { WindowGlobal::IncEventIndex(); WindowGlobal::eventStack[ WindowGlobal::eventIndex ].type = WindowEventType::GamePadButtonDPadDown; } } } } }
void XCBInput::eventLoop() { xcb_keysym_t pressedKey; xcb_generic_event_t *event; xcb_motion_notify_event_t *motion; xcb_key_press_event_t *kp; xcb_key_release_event_t *kr; while ((event = xcb_poll_for_event(connection))) { switch (event->response_type & ~0x80) { case XCB_MOTION_NOTIFY: motion = reinterpret_cast<xcb_motion_notify_event_t *>(event); mediaLayer->mouseLook(motion->event_x, motion->event_y); break; case XCB_KEY_RELEASE: kr = reinterpret_cast<xcb_key_release_event_t *>(event); pressedKey = xcb_key_symbols_get_keysym(syms, kr->detail, 0); pressedKeys.removeAll(pressedKey); switch (pressedKey) { case XK_Shift_L: inputSpeed = .01; break; } break; case XCB_KEY_PRESS: kp = reinterpret_cast<xcb_key_press_event_t *>(event); pressedKey = xcb_key_symbols_get_keysym(syms, kp->detail, 0); switch (pressedKey) { case XK_Escape: emit shutdown(); break; case XK_m: mediaLayer->toggleMouseGrab(); break; case XK_f: mediaLayer->toggleFullScreen(); break; case XK_p: RenderEngine::Instance().toggleFBO(); break; case XK_c: RenderEngine::Instance().toggleLightView(); break; case XK_Tab: RenderEngine::Instance().toggleWire(); break; case XK_Shift_L: inputSpeed = .1; break; default: pressedKeys.push_back(pressedKey); } break; default: /* Unknown event type, ignore it */ // printf ("Unknown event: %d\n", event->response_type); break; } free(event); } foreach(xcb_keysym_t key, pressedKeys) { checkKey(key); }
internal void hhxcb_process_events(hhxcb_context *context, hhxcb_state *state, game_input *new_input, game_input *old_input) { game_controller_input *old_keyboard_controller = GetController(old_input, 0); game_controller_input *new_keyboard_controller = GetController(new_input, 0); *new_keyboard_controller = {}; new_keyboard_controller->IsConnected = true; for ( uint button_index = 0; button_index < ArrayCount(new_keyboard_controller->Buttons); ++button_index) { new_keyboard_controller->Buttons[button_index].EndedDown = old_keyboard_controller->Buttons[button_index].EndedDown; } new_input->MouseX = old_input->MouseX; new_input->MouseY = old_input->MouseY; for (int i = 0; i < HHXCB_MAX_CONTROLLERS; ++i) { hhxcb_controller_info *pad = &context->controller_info[i]; if (!pad->is_active) { continue; } game_controller_input *old_controller = GetController(old_input, i+1); game_controller_input *new_controller = GetController(new_input, i+1); *new_controller = *old_controller; new_controller->IsConnected = true; new_controller->IsAnalog = old_controller->IsAnalog; js_event j; while (read(pad->fd, &j, sizeof(js_event)) == sizeof(js_event)) { // Don't care if init or afterwards j.type &= ~JS_EVENT_INIT; if (j.type == JS_EVENT_BUTTON) { if (j.number == pad->a_button) { hhxcb_process_button((j.value > 0), &old_controller->ActionDown, &new_controller->ActionDown); } else if (j.number == pad->b_button) { hhxcb_process_button((j.value > 0), &old_controller->ActionRight, &new_controller->ActionRight); } else if (j.number == pad->x_button) { hhxcb_process_button((j.value > 0), &old_controller->ActionLeft, &new_controller->ActionLeft); } else if (j.number == pad->y_button) { hhxcb_process_button((j.value > 0), &old_controller->ActionUp, &new_controller->ActionUp); } else if (j.number == pad->l1_button) { hhxcb_process_button((j.value > 0), &old_controller->LeftShoulder, &new_controller->LeftShoulder); } else if (j.number == pad->r1_button) { hhxcb_process_button((j.value > 0), &old_controller->RightShoulder, &new_controller->RightShoulder); } else if (j.number == pad->back_button) { hhxcb_process_button((j.value > 0), &old_controller->Back, &new_controller->Back); } else if (j.number == pad->start_button) { hhxcb_process_button((j.value > 0), &old_controller->Start, &new_controller->Start); } else { printf("Unhandled button: number %d, value %d\n", j.number, j.value); } } if (j.type == JS_EVENT_AXIS) { uint16 dead_zone = pad->axis_dead_zones[j.number]; bool axis_inverted = pad->axis_inverted[j.number]; if (j.number == pad->left_thumb_x_axis) { new_controller->StickAverageX = hhxcb_process_controller_axis(j.value, dead_zone, axis_inverted); if (new_controller->StickAverageX != 0.0f) { new_controller->IsAnalog = true; } } else if (j.number == pad->left_thumb_y_axis) { new_controller->StickAverageY = hhxcb_process_controller_axis(j.value, dead_zone, axis_inverted); if (new_controller->StickAverageY != 0.0f) { new_controller->IsAnalog = true; } } else if (j.number == pad->right_thumb_x_axis) { // TODO(nbm): Do something with this. Here otherwise we get spammed. } else if (j.number == pad->right_thumb_y_axis) { // TODO(nbm): Do something with this. Here otherwise we get spammed. } else if (j.number == pad->dpad_x_axis) { hhxcb_process_button((j.value > 0), &old_controller->MoveRight, &new_controller->MoveRight); hhxcb_process_button((j.value < 0), &old_controller->MoveLeft, &new_controller->MoveLeft); new_controller->IsAnalog = false; } else if (j.number == pad->dpad_y_axis) { hhxcb_process_button((j.value > 0), &old_controller->MoveDown, &new_controller->MoveDown); hhxcb_process_button((j.value < 0), &old_controller->MoveUp, &new_controller->MoveUp); new_controller->IsAnalog = false; } else { printf("Unhandled Axis: number %d, value %d\n", j.number, j.value); } } } if (errno != EAGAIN) { context->need_controller_refresh = true; } } xcb_generic_event_t *event; while ((event = xcb_poll_for_event(context->connection))) { // NOTE(nbm): The high-order bit of response_type is whether the event // is synthetic. I'm not sure I care, but let's grab it in case. bool32 synthetic_event = (event->response_type & 0x80) != 0; uint8_t response_type = event->response_type & ~0x80; switch(response_type) { case XCB_KEY_PRESS: case XCB_KEY_RELEASE: { xcb_key_press_event_t *e = (xcb_key_press_event_t *)event; bool32 is_down = (response_type == XCB_KEY_PRESS); xcb_keysym_t keysym = xcb_key_symbols_get_keysym(context->key_symbols, e->detail, 0); if (keysym == XK_w) { hhxcb_process_keyboard_message(&new_keyboard_controller->MoveUp, is_down); } else if (keysym == XK_a) { hhxcb_process_keyboard_message(&new_keyboard_controller->MoveLeft, is_down); } else if (keysym == XK_s) { hhxcb_process_keyboard_message(&new_keyboard_controller->MoveDown, is_down); } else if (keysym == XK_d) { hhxcb_process_keyboard_message(&new_keyboard_controller->MoveRight, is_down); } else if (keysym == XK_q) { hhxcb_process_keyboard_message(&new_keyboard_controller->LeftShoulder, is_down); } else if (keysym == XK_e) { hhxcb_process_keyboard_message(&new_keyboard_controller->RightShoulder, is_down); } else if (keysym == XK_Up) { hhxcb_process_keyboard_message(&new_keyboard_controller->ActionUp, is_down); } else if (keysym == XK_Left) { hhxcb_process_keyboard_message(&new_keyboard_controller->ActionLeft, is_down); } else if (keysym == XK_Down) { hhxcb_process_keyboard_message(&new_keyboard_controller->ActionDown, is_down); } else if (keysym == XK_Right) { hhxcb_process_keyboard_message(&new_keyboard_controller->ActionRight, is_down); } else if (keysym == XK_Escape) { hhxcb_process_keyboard_message(&new_keyboard_controller->Back, is_down); } else if (keysym == XK_space) { hhxcb_process_keyboard_message(&new_keyboard_controller->Start, is_down); } else if (keysym == XK_l) { if (is_down) { if (state->playback_index == 0) { if (state->recording_index == 0) { hhxcb_start_recording(state, 1); } else { hhxcb_stop_recording(state); hhxcb_start_playback(state, 1); } } else { hhxcb_stop_playback(state); } } } break; } case XCB_NO_EXPOSURE: { // No idea what these are, but they're spamming me. break; } case XCB_MOTION_NOTIFY: { xcb_motion_notify_event_t* e = (xcb_motion_notify_event_t*)event; new_input->MouseX = e->event_x; new_input->MouseY = e->event_y; break; } case XCB_CLIENT_MESSAGE: { xcb_client_message_event_t* client_message_event = (xcb_client_message_event_t*)event; if (client_message_event->type == context->wm_protocols) { if (client_message_event->data.data32[0] == context->wm_delete_window) { context->ending_flag = 1; break; } } break; } default: { break; } } free(event); }; }
static void ephyrProcessKeyRelease(xcb_generic_event_t *xev) { xcb_connection_t *conn = hostx_get_xcbconn(); xcb_key_release_event_t *key = (xcb_key_release_event_t *)xev; static xcb_key_symbols_t *keysyms; static int grabbed_screen = -1; int mod1_down = ephyrUpdateGrabModifierState(key->state); if (!keysyms) keysyms = xcb_key_symbols_alloc(conn); if (!EphyrWantNoHostGrab && (((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_L || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Shift_R) && (key->state & XCB_MOD_MASK_CONTROL)) || ((xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_L || xcb_key_symbols_get_keysym(keysyms, key->detail, 0) == XK_Control_R) && (key->state & XCB_MOD_MASK_SHIFT)))) { KdScreenInfo *screen = screen_from_window(key->event); EphyrScrPriv *scrpriv = screen->driver; if (grabbed_screen != -1) { xcb_ungrab_keyboard(conn, XCB_TIME_CURRENT_TIME); xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME); grabbed_screen = -1; hostx_set_win_title(screen, "(ctrl+shift grabs mouse and keyboard)"); } else if (!mod1_down) { /* Attempt grab */ xcb_grab_keyboard_cookie_t kbgrabc = xcb_grab_keyboard(conn, TRUE, scrpriv->win, XCB_TIME_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); xcb_grab_keyboard_reply_t *kbgrabr; xcb_grab_pointer_cookie_t pgrabc = xcb_grab_pointer(conn, TRUE, scrpriv->win, 0, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, scrpriv->win, XCB_NONE, XCB_TIME_CURRENT_TIME); xcb_grab_pointer_reply_t *pgrabr; kbgrabr = xcb_grab_keyboard_reply(conn, kbgrabc, NULL); if (!kbgrabr || kbgrabr->status != XCB_GRAB_STATUS_SUCCESS) { xcb_discard_reply(conn, pgrabc.sequence); xcb_ungrab_pointer(conn, XCB_TIME_CURRENT_TIME); } else { pgrabr = xcb_grab_pointer_reply(conn, pgrabc, NULL); if (!pgrabr || pgrabr->status != XCB_GRAB_STATUS_SUCCESS) { xcb_ungrab_keyboard(conn, XCB_TIME_CURRENT_TIME); } else { grabbed_screen = scrpriv->mynum; hostx_set_win_title (screen, "(ctrl+shift releases mouse and keyboard)"); } } } } if (!ephyrKbd || !((EphyrKbdPrivate *) ephyrKbd->driverPrivate)->enabled) { return; } /* Still send the release event even if above has happened server * will get confused with just an up event. Maybe it would be * better to just block shift+ctrls getting to kdrive all * together. */ ephyrUpdateModifierState(key->state); KdEnqueueKeyboardEvent(ephyrKbd, key->detail, TRUE); }
void fill_keycodes() { struct xkb_keymap *keymap; struct xkb_context *context; const struct xkb_rule_names rules={ .rules=xkb_names[0], .model=xkb_names[1], .layout=xkb_names[2], .variant=xkb_names[3], .options=xkb_names[4] }; struct xkb_state *state; enum xkb_state_component current_state; int counter; int i,j,k; char mods[256]; char keysym_asc[256]; char file_path[256]; char command[15]; uint32_t max_keys; int w,h,retval; int jumpto; context=xkb_context_new(0); keymap=xkb_keymap_new_from_names(context,&rules,0); state=NULL; // Get all the modifier keys for(i=8;i<256;i++) { state=xkb_state_new(keymap); current_state=xkb_state_update_key(state, i,XKB_KEY_DOWN); if (current_state!=0) { mods[i]=1; } else { mods[i]=0; } xkb_state_unref(state); } mods[7]=1; // fake mod, used for "no mod" // Read the keyboard definition files sprintf(file_path,"%s/%s.keymap",BASE_CONFIG_DIR,lang_onscreen); FILE *keyboard_file=fopen(file_path,"r"); if (keyboard_file==NULL) { printf("Can't open keyboard definition file %s. Trying with US file\n",file_path); sprintf(file_path,"%s/us.keymap",BASE_CONFIG_DIR); keyboard_file=fopen(file_path,"r"); if (keyboard_file==NULL) { printf("Also failed to open the US keymap file. Aborting.\n"); exit(-1); } } retval=fscanf(keyboard_file,"%s %d",command,&keyboard_blocks); if (retval!=2) { printf("Can't read the number of blocks\n"); } else { max_keys=keyboard_blocks*4*KEYS_PER_ROW; keyboard_lowercase=(struct key_element *)malloc(max_keys*sizeof(struct key_element)); memset(keyboard_lowercase,0,max_keys*sizeof(struct key_element)); for(counter=0;(!feof(keyboard_file))&&(counter<max_keys);counter++) { retval=fscanf(keyboard_file,"%s %d %d",command,&w,&h); if(retval!=3) { break; } keyboard_lowercase[counter].size=KEYS_FONT_SIZE; keyboard_lowercase[counter].g_element[0]=0; keyboard_lowercase[counter].w=w; keyboard_lowercase[counter].h=h; keyboard_lowercase[counter].keycode=0; keyboard_lowercase[counter].modifier=0; if (!strcmp(command,"BLANK")) { keyboard_lowercase[counter].type=KEY_BLANK; keyboard_lowercase[counter].keysym=0; } else if (!strcmp(command,"KEY")) { keyboard_lowercase[counter].type=KEY_PH; retval=fscanf(keyboard_file,"%s",keyboard_lowercase[counter].g_element); keyboard_lowercase[counter].keysym=init_utf8_to_keysym(keyboard_lowercase[counter].g_element); if (keyboard_lowercase[counter].keysym==0) { keyboard_lowercase[counter].type=KEY_BLANK; } } else if ((!strcmp(command,"KEYSYM"))||(!strcmp(command,"KEYSYMTEXT"))) { keyboard_lowercase[counter].type=KEY_PH; retval=fscanf(keyboard_file,"%s",keysym_asc); keyboard_lowercase[counter].keysym=xkb_keysym_from_name(keysym_asc,0); if (keyboard_lowercase[counter].keysym==0) { printf("Unknown keysym %s\n",keysym_asc); keyboard_lowercase[counter].type=KEY_BLANK; } else { if (!strcmp(command,"KEYSYMTEXT")) { retval=fscanf(keyboard_file,"%s",keyboard_lowercase[counter].g_element); keyboard_lowercase[counter].size=KEYS_TEXT_FONT_SIZE; } else { retval=xkb_keysym_to_utf8(keyboard_lowercase[counter].keysym,keyboard_lowercase[counter].g_element,7); if (retval==-1) { retval++; } keyboard_lowercase[counter].g_element[retval]=0;// terminate string } } } else if (!strcmp(command,"TAB")) { keyboard_lowercase[counter].type=KEY_TAB; keyboard_lowercase[counter].keysym=XK_Tab; } else if (!strcmp(command,"SPACE")) { keyboard_lowercase[counter].type=KEY_SPACE; keyboard_lowercase[counter].keysym=XK_space; } else if (!strcmp(command,"RETURN")) { keyboard_lowercase[counter].type=KEY_RETURN; keyboard_lowercase[counter].keysym=XK_Return; } else if (!strcmp(command,"DELETE")) { keyboard_lowercase[counter].type=KEY_DELETE; keyboard_lowercase[counter].keysym=XK_BackSpace; } else if (!strcmp(command,"JUMPTO")) { retval=fscanf(keyboard_file,"%d %s",&jumpto,command); keyboard_lowercase[counter].type=KEY_JUMPTO; keyboard_lowercase[counter].keycode=jumpto; keyboard_lowercase[counter].keysym=0; if (!strcmp(command,"GEN")) { keyboard_lowercase[counter].modifier=0; } else if (!strcmp(command,"SHIFT")) { keyboard_lowercase[counter].modifier=1; } else if (!strcmp(command,"SYMBOLS")) { keyboard_lowercase[counter].modifier=2; } else if (!strcmp(command,"LETTERS")) { keyboard_lowercase[counter].modifier=3; } if (jumpto>=keyboard_blocks) { printf("Ilegal jump to block %d (max. is %d)\n",jumpto,keyboard_blocks); keyboard_lowercase[counter].type=KEY_BLANK; } } else if (!strcmp(command,"UP")) { keyboard_lowercase[counter].type=KEY_UP; keyboard_lowercase[counter].keysym=XK_Up; } else if (!strcmp(command,"DOWN")) { keyboard_lowercase[counter].type=KEY_DOWN; keyboard_lowercase[counter].keysym=XK_Down; } else if (!strcmp(command,"LEFT")) { keyboard_lowercase[counter].type=KEY_LEFT; keyboard_lowercase[counter].keysym=XK_Left; } else if (!strcmp(command,"RIGHT")) { keyboard_lowercase[counter].type=KEY_RIGHT; keyboard_lowercase[counter].keysym=XK_Right; } else { printf("Unknown command %s\n",command); keyboard_lowercase[counter].type=KEY_BLANK; keyboard_lowercase[counter].keysym=0; } } xkb_keysym_t keysym; xkb_keycode_t keycode_mod; for(i=7;i<256;i++) { // do a loop on every modifier if (!mods[i]) { continue; // In this loop we test each modifier with each keycode } state=xkb_state_new(keymap); if (i!=7) { xkb_state_update_key(state, i,XKB_KEY_DOWN); // press the modifier key keycode_mod=i; } else { keycode_mod=0; } for(j=8;j<256;j++) { if (mods[j]) { continue; // Don't test modifiers; we want "normal" keys } keysym=xkb_state_key_get_one_sym(state, j); if (keysym==XKB_KEY_NoSymbol) { continue; } for(k=0;k<counter;k++) { // and now we check each desired key with the keysymbol obtained if ((keyboard_lowercase[k].keycode==0)&&(keyboard_lowercase[k].type!=KEY_BLANK)&&(keyboard_lowercase[k].keysym==keysym)) { keyboard_lowercase[k].keycode=j; keyboard_lowercase[k].modifier=keycode_mod; } } } xkb_state_unref(state); } /*for(k=0;k<counter;k++) { // and now we check each desired key with the keysymbol obtained printf("Texto: %s, Keysym: %d, mod: %d\n",keyboard_lowercase[k].g_element,keyboard_lowercase[k].keycode,keyboard_lowercase[k].modifier); }*/ // Now assign new keysyms to keycodes not used, to allow other keysyms not available in US keyboards xcb_key_symbols_t *symbols; symbols=xcb_key_symbols_alloc(conn); xcb_flush(conn); xcb_keycode_t keycode=8; xcb_keycode_t keycode_found; xcb_keysym_t keysyms[4]; xcb_keycode_t keycode_shift; struct lower_upper_t {xcb_keysym_t upper_first; xcb_keysym_t upper_last; xcb_keysym_t lower_first; xcb_keysym_t lower_last; }; struct lower_upper_t lower_upper[] = { {XKB_KEY_Agrave,XKB_KEY_Odiaeresis,XKB_KEY_agrave,XKB_KEY_odiaeresis}, {XKB_KEY_Oslash,XKB_KEY_THORN,XKB_KEY_oslash,XKB_KEY_thorn}, {0,0,0,0} }; struct lower_upper_t *iter_lu; keycode_shift=*xcb_key_symbols_get_keycode(symbols,XKB_KEY_Shift_L); for(k=0;k<max_keys;k++) { // and now we check each desired key with the keysymbol obtained if ((keyboard_lowercase[k].keycode==0)&&(keyboard_lowercase[k].type!=KEY_BLANK)&&(keyboard_lowercase[k].type!=KEY_JUMPTO)) { // this key is not available in US keyboards; let's redefine a keycode for it keycode_found=0; while(keycode<256) { if ((0==xcb_key_symbols_get_keysym(symbols,keycode,0))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,1))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,2))&& (0==xcb_key_symbols_get_keysym(symbols,keycode,3))) { keycode_found=keycode; break; } keycode++; } if (keycode_found==0) { printf("No more codes available\n"); break; // there are no more free keycodes available } keycode=keycode_found; keysyms[0]=keyboard_lowercase[k].keysym; keysyms[1]=0; keysyms[2]=keyboard_lowercase[k].keysym; keysyms[3]=0; for(iter_lu=lower_upper;iter_lu->upper_first;iter_lu++) { if ((keysyms[0]>=iter_lu->upper_first)&&(keysyms[0]<=iter_lu->upper_last)) { // it's an uppercase special character keysyms[0]|=0x20; // first character as lowercase break; } if ((keysyms[0]>=iter_lu->lower_first)&&(keysyms[0]<=iter_lu->lower_last)) { // it's a lowercase special character keysyms[2]&=0xDF; // second character as uppercase break; } } xcb_change_keyboard_mapping(conn,1,keycode,4,keysyms); // insert the new keysym for(j=k;j<max_keys;j++) { // set the keycode and the shift modifier, if needed, to all keys with that keysyms if (keyboard_lowercase[j].keysym==keysyms[0]) { keyboard_lowercase[j].keycode=keycode; keyboard_lowercase[j].modifier=0; continue; } if (keyboard_lowercase[j].keysym==keysyms[2]) { keyboard_lowercase[j].keycode=keycode; keyboard_lowercase[j].modifier=keycode_shift; continue; } } keycode++; } } xcb_key_symbols_free(symbols); } fclose(keyboard_file); keyboard_current_block=0; xkb_keymap_unref(keymap); xkb_context_unref(context); }