/* * Returns the modifier mask (XCB_MOD_MASK_*) for the given keysymbol, for * example for XCB_NUM_LOCK (usually configured to mod2). * * This function does not initiate any round-trips. * */ uint32_t get_mod_mask_for(uint32_t keysym, xcb_key_symbols_t *symbols, xcb_get_modifier_mapping_reply_t *modmap_reply) { xcb_keycode_t *codes, *modmap; xcb_keycode_t mod_code; modmap = xcb_get_modifier_mapping_keycodes(modmap_reply); /* Get the list of keycodes for the given symbol */ if (!(codes = xcb_key_symbols_get_keycode(symbols, keysym))) return 0; /* Loop through all modifiers (Mod1-Mod5, Shift, Control, Lock) */ for (int mod = 0; mod < 8; mod++) for (int j = 0; j < modmap_reply->keycodes_per_modifier; j++) { /* Store the current keycode (for modifier 'mod') */ mod_code = modmap[(mod * modmap_reply->keycodes_per_modifier) + j]; /* Check if that keycode is in the list of previously resolved * keycodes for our symbol. If so, return the modifier mask. */ for (xcb_keycode_t *code = codes; *code; code++) { if (*code != mod_code) continue; free(codes); /* This corresponds to the XCB_MOD_MASK_* constants */ return (1 << mod); } } return 0; }
/* * Returns the mask for Mode_switch (to be used for looking up keysymbols by * keycode). * */ uint32_t get_mod_mask(xcb_connection_t *conn, uint32_t keycode) { xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(conn); xcb_get_modifier_mapping_reply_t *modmap_r; xcb_keycode_t *modmap, kc; xcb_keycode_t *modeswitchcodes = xcb_key_symbols_get_keycode(symbols, keycode); if (modeswitchcodes == NULL) return 0; modmap_r = xcb_get_modifier_mapping_reply(conn, xcb_get_modifier_mapping(conn), NULL); modmap = xcb_get_modifier_mapping_keycodes(modmap_r); for (int i = 0; i < 8; i++) for (int j = 0; j < modmap_r->keycodes_per_modifier; j++) { kc = modmap[i * modmap_r->keycodes_per_modifier + j]; for (xcb_keycode_t *ktest = modeswitchcodes; *ktest; ktest++) { if (*ktest != kc) continue; free(modeswitchcodes); free(modmap_r); return (1 << i); } } return 0; }
int16_t modfield_from_keysym(xcb_keysym_t keysym) { uint16_t modfield = 0; xcb_keycode_t *keycodes = NULL, *mod_keycodes = NULL; xcb_get_modifier_mapping_reply_t *reply = NULL; xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(dpy); if ((keycodes = xcb_key_symbols_get_keycode(symbols, keysym)) == NULL || (reply = xcb_get_modifier_mapping_reply(dpy, xcb_get_modifier_mapping(dpy), NULL)) == NULL || reply->keycodes_per_modifier < 1 || (mod_keycodes = xcb_get_modifier_mapping_keycodes(reply)) == NULL) { goto end; } unsigned int num_mod = xcb_get_modifier_mapping_keycodes_length(reply) / reply->keycodes_per_modifier; for (unsigned int i = 0; i < num_mod; i++) { for (unsigned int j = 0; j < reply->keycodes_per_modifier; j++) { xcb_keycode_t mk = mod_keycodes[i * reply->keycodes_per_modifier + j]; if (mk == XCB_NO_SYMBOL) { continue; } for (xcb_keycode_t *k = keycodes; *k != XCB_NO_SYMBOL; k++) { if (*k == mk) { modfield |= (1 << i); } } } } end: xcb_key_symbols_free(symbols); free(keycodes); free(reply); return modfield; }
void keyboard::update_mapping( void ) { auto cookie = xcb_get_modifier_mapping_unchecked( _connection ); if ( _keysyms ) xcb_key_symbols_free( _keysyms ); _keysyms = xcb_key_symbols_alloc( _connection ); auto numlockcodes = core::wrap_cptr( xcb_key_symbols_get_keycode( _keysyms, XK_Num_Lock ) ); auto shiftlockcodes = core::wrap_cptr( xcb_key_symbols_get_keycode( _keysyms, XK_Shift_Lock ) ); auto capslockcodes = core::wrap_cptr( xcb_key_symbols_get_keycode( _keysyms, XK_Caps_Lock ) ); auto modeswitchcodes = core::wrap_cptr( xcb_key_symbols_get_keycode( _keysyms, XK_Mode_switch ) ); auto modmap_r = core::wrap_cptr( xcb_get_modifier_mapping_reply( _connection, cookie, nullptr ) ); xcb_keycode_t *modmap = xcb_get_modifier_mapping_keycodes( modmap_r.get() ); _numlock = 0; _shiftlock = 0; _capslock = 0; _modeswitch = 0; for( int i = 0; i < 8; i++ ) { for( int j = 0; j < modmap_r->keycodes_per_modifier; j++ ) { xcb_keycode_t kc = modmap[i * modmap_r->keycodes_per_modifier + j]; look_for( _numlock, numlockcodes, kc, i ); look_for( _shiftlock, shiftlockcodes, kc, i ); look_for( _capslock, capslockcodes, kc, i ); look_for( _modeswitch, modeswitchcodes, kc, i ); } } }
static unsigned GetModifier( xcb_connection_t *p_connection, xcb_key_symbols_t *p_symbols, xcb_keysym_t sym ) { static const unsigned pi_mask[8] = { XCB_MOD_MASK_SHIFT, XCB_MOD_MASK_LOCK, XCB_MOD_MASK_CONTROL, XCB_MOD_MASK_1, XCB_MOD_MASK_2, XCB_MOD_MASK_3, XCB_MOD_MASK_4, XCB_MOD_MASK_5 }; const xcb_keycode_t key = xcb_key_symbols_get_keycode( p_symbols, sym ); if( key == 0 ) return 0; xcb_get_modifier_mapping_cookie_t r = xcb_get_modifier_mapping( p_connection ); xcb_get_modifier_mapping_reply_t *p_map = xcb_get_modifier_mapping_reply( p_connection, r, NULL ); if( !p_map ) return 0; xcb_keycode_t *p_keycode = xcb_get_modifier_mapping_keycodes( p_map ); if( !p_keycode ) return 0; unsigned i_mask = 0; for( int i = 0; i < 8; i++ ) { for( int j = 0; j < p_map->keycodes_per_modifier; j++ ) { if( p_keycode[i * p_map->keycodes_per_modifier + j] == key ) i_mask = pi_mask[i]; } } free( p_map ); // FIXME to check return i_mask; }
static unsigned GetModifier( xcb_connection_t *p_connection, xcb_key_symbols_t *p_symbols, xcb_keysym_t sym ) { static const unsigned pi_mask[8] = { XCB_MOD_MASK_SHIFT, XCB_MOD_MASK_LOCK, XCB_MOD_MASK_CONTROL, XCB_MOD_MASK_1, XCB_MOD_MASK_2, XCB_MOD_MASK_3, XCB_MOD_MASK_4, XCB_MOD_MASK_5 }; if( sym == 0 ) return 0; /* no modifier */ xcb_get_modifier_mapping_cookie_t r = xcb_get_modifier_mapping( p_connection ); xcb_get_modifier_mapping_reply_t *p_map = xcb_get_modifier_mapping_reply( p_connection, r, NULL ); if( !p_map ) return 0; xcb_keycode_t *p_keys = xcb_key_symbols_get_keycode( p_symbols, sym ); if( !p_keys ) goto end; int i = 0; bool no_modifier = true; while( p_keys[i] != XCB_NO_SYMBOL ) { if( p_keys[i] != 0 ) { no_modifier = false; break; } i++; } if( no_modifier ) goto end; xcb_keycode_t *p_keycode = xcb_get_modifier_mapping_keycodes( p_map ); if( !p_keycode ) goto end; for( int i = 0; i < 8; i++ ) for( int j = 0; j < p_map->keycodes_per_modifier; j++ ) for( int k = 0; p_keys[k] != XCB_NO_SYMBOL; k++ ) if( p_keycode[i*p_map->keycodes_per_modifier + j] == p_keys[k]) { free( p_keys ); free( p_map ); return pi_mask[i]; } end: free( p_keys ); free( p_map ); // FIXME to check return 0; }
/* * Finds out which modifier mask is the one for numlock, as the user may change this. * */ void xcb_get_numlock_mask(xcb_connection_t *conn) { xcb_key_symbols_t *keysyms; xcb_get_modifier_mapping_cookie_t cookie; xcb_get_modifier_mapping_reply_t *reply; xcb_keycode_t *modmap; int mask, i; const int masks[8] = { XCB_MOD_MASK_SHIFT, XCB_MOD_MASK_LOCK, XCB_MOD_MASK_CONTROL, XCB_MOD_MASK_1, XCB_MOD_MASK_2, XCB_MOD_MASK_3, XCB_MOD_MASK_4, XCB_MOD_MASK_5 }; /* Request the modifier map */ cookie = xcb_get_modifier_mapping_unchecked(conn); /* Get the keysymbols */ keysyms = xcb_key_symbols_alloc(conn); if ((reply = xcb_get_modifier_mapping_reply(conn, cookie, NULL)) == NULL) { xcb_key_symbols_free(keysyms); return; } modmap = xcb_get_modifier_mapping_keycodes(reply); /* Get the keycode for numlock */ #ifdef OLD_XCB_KEYSYMS_API xcb_keycode_t numlock = xcb_key_symbols_get_keycode(keysyms, XCB_NUM_LOCK); #else /* For now, we only use the first keysymbol. */ xcb_keycode_t *numlock_syms = xcb_key_symbols_get_keycode(keysyms, XCB_NUM_LOCK); if (numlock_syms == NULL) return; xcb_keycode_t numlock = *numlock_syms; free(numlock_syms); #endif /* Check all modifiers (Mod1-Mod5, Shift, Control, Lock) */ for (mask = 0; mask < 8; mask++) for (i = 0; i < reply->keycodes_per_modifier; i++) if (modmap[(mask * reply->keycodes_per_modifier) + i] == numlock) xcb_numlock_mask = masks[mask]; xcb_key_symbols_free(keysyms); free(reply); }
XRecordKeyboardMonitor::XRecordKeyboardMonitor(Display *display) : m_connection(xcb_connect(XDisplayString(display), 0)), m_modifiersPressed(0), m_keysPressed(0) { if (!m_connection) { return; } xcb_get_modifier_mapping_cookie_t modmapCookie = xcb_get_modifier_mapping(m_connection); m_context = xcb_generate_id(m_connection); xcb_record_range_t range; memset(&range, 0, sizeof(range)); range.device_events.first = XCB_KEY_PRESS; range.device_events.last = XCB_KEY_RELEASE; xcb_record_client_spec_t cs = XCB_RECORD_CS_ALL_CLIENTS; xcb_record_create_context(m_connection, m_context, 0, 1, 1, &cs, &range); xcb_flush(m_connection); QScopedPointer<xcb_get_modifier_mapping_reply_t, QScopedPointerPodDeleter> modmap(xcb_get_modifier_mapping_reply(m_connection, modmapCookie, 0)); if (!modmap) { return; } int nModifiers = xcb_get_modifier_mapping_keycodes_length(modmap.data()); xcb_keycode_t *modifiers = xcb_get_modifier_mapping_keycodes(modmap.data()); m_modifier.fill(false, std::numeric_limits<xcb_keycode_t>::max() + 1); for (xcb_keycode_t *i = modifiers; i < modifiers + nModifiers; i++) { m_modifier[*i] = true; } m_ignore.fill(false, std::numeric_limits<xcb_keycode_t>::max() + 1); for (xcb_keycode_t *i = modifiers; i < modifiers + modmap->keycodes_per_modifier; i++) { m_ignore[*i] = true; } m_pressed.fill(false, std::numeric_limits<xcb_keycode_t>::max() + 1); m_cookie = xcb_record_enable_context(m_connection, m_context); xcb_flush(m_connection); m_notifier = new QSocketNotifier(xcb_get_file_descriptor(m_connection), QSocketNotifier::Read, this); connect(m_notifier, SIGNAL(activated(int)), SLOT(processNextReply())); m_notifier->setEnabled(true); }
static void update_keys_mask() { xcb_keycode_t key_num, key_shift, key_caps, key_mode, key; xcb_get_modifier_mapping_reply_t *reply; xcb_keycode_t *codes; unsigned int i, j; nil_.mask_numlock = 0; nil_.mask_shiftlock = 0; nil_.mask_capslock = 0; nil_.mask_modeswitch = 0; key_num = get_keycode(XK_Num_Lock); key_shift = get_keycode(XK_Shift_Lock); key_caps = get_keycode(XK_Caps_Lock); key_mode = get_keycode(XK_Mode_switch); reply = xcb_get_modifier_mapping_reply(nil_.con, xcb_get_modifier_mapping_unchecked(nil_.con), 0); codes = xcb_get_modifier_mapping_keycodes(reply); /* The number of keycodes in the list is 8 * keycodes_per_modifier */ for (i = 0; i < 8; ++i) { for (j = 0; j < reply->keycodes_per_modifier; ++j) { key = codes[i * reply->keycodes_per_modifier + j]; if (!key) { continue; } if (key == key_num) { nil_.mask_numlock = (uint16_t)(1 << i); } else if (key == key_shift) { nil_.mask_shiftlock = (uint16_t)(1 << i); } else if (key == key_caps) { nil_.mask_capslock = (uint16_t)(1 << i); } else if (key == key_mode) { nil_.mask_modeswitch = (uint16_t)(1 << i); } } } NIL_LOG("mask num=0x%x shift=0x%x caps=0x%x mode=0x%x", nil_.mask_numlock, nil_.mask_shiftlock, nil_.mask_capslock, nil_.mask_modeswitch); free(reply); }
void App::keyRelease(const xcb_key_release_event_t* event) { unsigned int mk = event->state & USED_MASK; // ev.state is state before the key release, so just checking mk being 0 isn't enough // using XQueryPointer() also doesn't seem to work well, so the check that all // modifiers are released: only one modifier is active and the currently released // key is this modifier - if yes, release the grab int mod_index = -1; for (int i = XCB_MAP_INDEX_SHIFT; i <= XCB_MAP_INDEX_5; ++i) if ((mk & (1 << i)) != 0) { if (mod_index >= 0) return; mod_index = i; } bool release = false; if (mod_index == -1) release = true; else { auto cookie = xcb_get_modifier_mapping(QX11Info::connection()); auto reply = xcb_get_modifier_mapping_reply(QX11Info::connection(), cookie, NULL); if (reply) { auto keycodes = xcb_get_modifier_mapping_keycodes(reply); for (int i = 0; i < reply->keycodes_per_modifier; i++) { if (keycodes[reply->keycodes_per_modifier * mod_index + i] == event->detail) { release = true; } } } free(reply); } if (!release) { return; } if (m_keyboardGrabbed) { accept(); } }
static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_t *event) { printf("Keypress %d, state raw = %d\n", event->detail, event->state); /* Remove the numlock bit, all other bits are modifiers we can bind to */ uint16_t state_filtered = event->state & ~(xcb_numlock_mask | XCB_MOD_MASK_LOCK); /* Only use the lower 8 bits of the state (modifier masks) so that mouse * button masks are filtered out */ state_filtered &= 0xFF; xcb_keysym_t sym = xcb_key_press_lookup_keysym(symbols, event, state_filtered); printf("sym = %c (%d)\n", sym, sym); if (sym == XK_Return || sym == XK_KP_Enter) { if (current_step == STEP_WELCOME) { current_step = STEP_GENERATE; /* Set window title */ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3: generate config"), "i3: generate config"); xcb_flush(conn); } else finish(); } /* cancel any time */ if (sym == XK_Escape) exit(0); /* Check if this is Mod1 or Mod4. The modmap contains Shift, Lock, Control, * Mod1, Mod2, Mod3, Mod4, Mod5 (in that order) */ xcb_keycode_t *modmap = xcb_get_modifier_mapping_keycodes(modmap_reply); /* Mod1? */ int mask = 3; for (int i = 0; i < modmap_reply->keycodes_per_modifier; i++) { xcb_keycode_t code = modmap[(mask * modmap_reply->keycodes_per_modifier) + i]; if (code == XCB_NONE) continue; printf("Modifier keycode for Mod1: 0x%02x\n", code); if (code == event->detail) { modifier = MOD_Mod1; printf("This is Mod1!\n"); } } /* Mod4? */ mask = 6; for (int i = 0; i < modmap_reply->keycodes_per_modifier; i++) { xcb_keycode_t code = modmap[(mask * modmap_reply->keycodes_per_modifier) + i]; if (code == XCB_NONE) continue; printf("Modifier keycode for Mod4: 0x%02x\n", code); if (code == event->detail) { modifier = MOD_Mod4; printf("This is Mod4!\n"); } } handle_expose(); return 1; }
// http://svn.tribler.org/vlc/trunk/modules/control/globalhotkeys/xcb.c // Copyright (C) 2009 the VideoLAN team static unsigned GetModifier( xcb_connection_t *p_connection, xcb_key_symbols_t *p_symbols, xcb_keysym_t sym ) { static const unsigned pi_mask[8] = { XCB_MOD_MASK_SHIFT, XCB_MOD_MASK_LOCK, XCB_MOD_MASK_CONTROL, XCB_MOD_MASK_1, XCB_MOD_MASK_2, XCB_MOD_MASK_3, XCB_MOD_MASK_4, XCB_MOD_MASK_5 }; if( sym == 0 ) return 0; /* no modifier */ #ifdef XCB_KEYSYM_OLD_API /* as seen in Debian Lenny */ const xcb_keycode_t key = xcb_key_symbols_get_keycode( p_symbols, sym ); if( key == 0 ) return 0; #else const xcb_keycode_t *p_keys = xcb_key_symbols_get_keycode( p_symbols, sym ); if( !p_keys ) return 0; int i = 0; bool no_modifier = true; while( p_keys[i] != XCB_NO_SYMBOL ) { if( p_keys[i] != 0 ) { no_modifier = false; break; } i++; } if( no_modifier ) return 0; #endif xcb_get_modifier_mapping_cookie_t r = xcb_get_modifier_mapping( p_connection ); xcb_get_modifier_mapping_reply_t *p_map = xcb_get_modifier_mapping_reply( p_connection, r, NULL ); if( !p_map ) return 0; xcb_keycode_t *p_keycode = xcb_get_modifier_mapping_keycodes( p_map ); if( !p_keycode ) return 0; for( int i = 0; i < 8; i++ ) for( int j = 0; j < p_map->keycodes_per_modifier; j++ ) #ifdef XCB_KEYSYM_OLD_API /* as seen in Debian Lenny */ if( p_keycode[i * p_map->keycodes_per_modifier + j] == key ) { free( p_map ); return pi_mask[i]; } #else for( int k = 0; p_keys[k] != XCB_NO_SYMBOL; k++ ) if( p_keycode[i*p_map->keycodes_per_modifier + j] == p_keys[k]) { free( p_map ); return pi_mask[i]; } #endif free( p_map ); // FIXME to check return 0; }