bool App::nativeEvent(xcb_generic_event_t* event) { if ((event->response_type & ~0x80) == XCB_KEY_PRESS) { auto keypress = reinterpret_cast<xcb_key_press_event_t*>(event); if (keypress->event == QX11Info::appRootWindow()) { auto sym = xcb_key_press_lookup_keysym(m_syms, keypress, 0); uint state = keypress->state & USED_MASK; bool forward; if ((forward = m_triggersList.contains(qMakePair<uint, uint>(sym, state))) || m_triggersList.contains(qMakePair<uint, uint>(sym, state & (~XCB_MOD_MASK_SHIFT)))) { if (m_keyboardGrabbed) { ibus_panel_impanel_navigate(m_impanel, false, forward); } else { if (grabXKeyboard()) { ibus_panel_impanel_navigate(m_impanel, true, forward); } else { ibus_panel_impanel_move_next(m_impanel); } } } } } else if ((event->response_type & ~0x80) == XCB_KEY_RELEASE) { auto keyrelease = reinterpret_cast<xcb_key_release_event_t*>(event); if (keyrelease->event == QX11Info::appRootWindow()) { keyRelease(keyrelease); } } return false; }
/* * Deactivates the Mode_switch bit upon release of the Mode_switch key. * */ static int handle_key_release(void *ignored, xcb_connection_t *conn, xcb_key_release_event_t *event) { printf("releasing %d, state raw = %d\n", event->detail, event->state); xcb_keysym_t sym = xcb_key_press_lookup_keysym(symbols, event, event->state); if (sym == XK_Mode_switch) { printf("Mode switch disabled\n"); modeswitch_active = false; } return 1; }
/** * Process an X11 event, convert into VLC hotkey event if applicable. * * @param ctx key handler created with CreateKeyHandler() * @param ev XCB event to process * @return 0 if the event was handled and free()'d, non-zero otherwise */ int XCB_keyHandler_Process (key_handler_t *ctx, xcb_generic_event_t *ev) { assert (ctx); switch (ev->response_type & 0x7f) { case XCB_KEY_PRESS: { xcb_key_press_event_t *e = (xcb_key_press_event_t *)ev; xcb_keysym_t sym = xcb_key_press_lookup_keysym (ctx->syms, e, 0); uint_fast32_t vk = ConvertKeySym (sym); msg_Dbg (ctx->obj, "key: 0x%08"PRIxFAST32" (X11: 0x%04"PRIx32")", vk, sym); if (vk == KEY_UNSET) break; if (e->state & XCB_MOD_MASK_SHIFT) /* Shift */ vk |= KEY_MODIFIER_SHIFT; /* XCB_MOD_MASK_LOCK */ /* Caps Lock */ if (e->state & XCB_MOD_MASK_CONTROL) /* Control */ vk |= KEY_MODIFIER_CTRL; if (e->state & XCB_MOD_MASK_1) /* Alternate */ vk |= KEY_MODIFIER_ALT; /* XCB_MOD_MASK_2 */ /* Numeric Pad Lock */ if (e->state & XCB_MOD_MASK_3) /* Super */ vk |= KEY_MODIFIER_META; if (e->state & XCB_MOD_MASK_4) /* Meta */ vk |= KEY_MODIFIER_META; if (e->state & XCB_MOD_MASK_5) /* Alternate Graphic */ vk |= KEY_MODIFIER_ALT; var_SetInteger (ctx->obj->obj.libvlc, "key-pressed", vk); break; } case XCB_KEY_RELEASE: break; case XCB_MAPPING_NOTIFY: { xcb_mapping_notify_event_t *e = (xcb_mapping_notify_event_t *)ev; msg_Dbg (ctx->obj, "refreshing keyboard mapping"); xcb_refresh_keyboard_mapping (ctx->syms, e); break; } default: return -1; } free (ev); return 0; }
/** * Process an X11 event, convert into VLC hotkey event if applicable. * * @param ctx key handler created with CreateKeyHandler() * @param ev XCB event to process * @return 0 if the event was handled and free()'d, non-zero otherwise */ int ProcessKeyEvent (key_handler_t *ctx, xcb_generic_event_t *ev) { assert (ctx); switch (ev->response_type & 0x7f) { case XCB_KEY_PRESS: { xcb_key_press_event_t *e = (xcb_key_press_event_t *)ev; xcb_keysym_t sym = xcb_key_press_lookup_keysym (ctx->syms, e, 0); uint_fast32_t vk = ConvertKeySym (sym); msg_Dbg (ctx->obj, "key: 0x%08"PRIxFAST32, vk); if (vk == KEY_UNSET) break; if (e->state & XCB_MOD_MASK_SHIFT) vk |= KEY_MODIFIER_SHIFT; if (e->state & XCB_MOD_MASK_CONTROL) vk |= KEY_MODIFIER_CTRL; if (e->state & XCB_MOD_MASK_1) vk |= KEY_MODIFIER_ALT; if (e->state & XCB_MOD_MASK_4) vk |= KEY_MODIFIER_META; var_SetInteger (ctx->obj->p_libvlc, "key-pressed", vk); break; } case XCB_KEY_RELEASE: break; case XCB_MAPPING_NOTIFY: { xcb_mapping_notify_event_t *e = (xcb_mapping_notify_event_t *)ev; msg_Dbg (ctx->obj, "refreshing keyboard mapping"); xcb_refresh_keyboard_mapping (ctx->syms, e); break; } default: return -1; } free (ev); return 0; }
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; }
/* * Handles keypresses by converting the keycodes to keysymbols, then the * keysymbols to UCS-2. If the conversion succeeded, the glyph is saved in the * internal buffers and displayed in the input window. * * Also handles backspace (deleting one character) and return (sending the * command to i3). * */ 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); // TODO: port the input handling code from i3lock once libxkbcommon ≥ 0.5.0 // is available in distros. /* See the documentation of xcb_key_symbols_get_keysym for this one. * Basically: We get either col 0 or col 1, depending on whether shift is * pressed. */ int col = (event->state & XCB_MOD_MASK_SHIFT); /* If modeswitch is currently active, we need to look in group 2 or 3, * respectively. */ if (modeswitch_active) col += 2; xcb_keysym_t sym = xcb_key_press_lookup_keysym(symbols, event, col); if (sym == XK_Mode_switch) { printf("Mode switch enabled\n"); modeswitch_active = true; return 1; } if (sym == XK_Return) finish_input(); if (sym == XK_BackSpace) { if (input_position == 0) return 1; input_position--; free(glyphs_utf8[input_position]); handle_expose(NULL, conn, NULL); return 1; } if (sym == XK_Escape) { exit(0); } /* TODO: handle all of these? */ printf("is_keypad_key = %d\n", xcb_is_keypad_key(sym)); printf("is_private_keypad_key = %d\n", xcb_is_private_keypad_key(sym)); printf("xcb_is_cursor_key = %d\n", xcb_is_cursor_key(sym)); printf("xcb_is_pf_key = %d\n", xcb_is_pf_key(sym)); printf("xcb_is_function_key = %d\n", xcb_is_function_key(sym)); printf("xcb_is_misc_function_key = %d\n", xcb_is_misc_function_key(sym)); printf("xcb_is_modifier_key = %d\n", xcb_is_modifier_key(sym)); if (xcb_is_modifier_key(sym) || xcb_is_cursor_key(sym)) return 1; printf("sym = %c (%d)\n", sym, sym); /* convert the keysym to UCS */ uint16_t ucs = keysym2ucs(sym); if ((int16_t)ucs == -1) { fprintf(stderr, "Keysym could not be converted to UCS, skipping\n"); return 1; } xcb_char2b_t inp; inp.byte1 = (ucs & 0xff00) >> 2; inp.byte2 = (ucs & 0x00ff) >> 0; printf("inp.byte1 = %02x, inp.byte2 = %02x\n", inp.byte1, inp.byte2); /* convert it to UTF-8 */ char *out = convert_ucs2_to_utf8(&inp, 1); printf("converted to %s\n", out); glyphs_ucs[input_position] = inp; glyphs_utf8[input_position] = out; input_position++; if (input_position == limit) finish_input(); handle_expose(NULL, conn, NULL); return 1; }