/* * Handle key presses. Fixes state, then looks up the key symbol for the * given keycode, then looks up the key symbol (as UCS-2), converts it to * UTF-8 and stores it in the password array. * */ static void handle_key_press(xcb_key_press_event_t *event) { xkb_keysym_t ksym; char buffer[128]; int n; bool ctrl; bool composed = false; ksym = xkb_state_key_get_one_sym(xkb_state, event->detail); ctrl = xkb_state_mod_name_is_active(xkb_state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_DEPRESSED); /* The buffer will be null-terminated, so n >= 2 for 1 actual character. */ memset(buffer, '\0', sizeof(buffer)); if (xkb_compose_state && xkb_compose_state_feed(xkb_compose_state, ksym) == XKB_COMPOSE_FEED_ACCEPTED) { switch (xkb_compose_state_get_status(xkb_compose_state)) { case XKB_COMPOSE_NOTHING: break; case XKB_COMPOSE_COMPOSING: return; case XKB_COMPOSE_COMPOSED: /* xkb_compose_state_get_utf8 doesn't include the terminating byte in the return value * as xkb_keysym_to_utf8 does. Adding one makes the variable n consistent. */ n = xkb_compose_state_get_utf8(xkb_compose_state, buffer, sizeof(buffer)) + 1; ksym = xkb_compose_state_get_one_sym(xkb_compose_state); composed = true; break; case XKB_COMPOSE_CANCELLED: xkb_compose_state_reset(xkb_compose_state); return; } } if (!composed) { n = xkb_keysym_to_utf8(ksym, buffer, sizeof(buffer)); } switch (ksym) { case XKB_KEY_Return: case XKB_KEY_KP_Enter: case XKB_KEY_XF86ScreenSaver: if (pam_state == STATE_PAM_WRONG) return; if (skip_without_validation()) { clear_input(); return; } password[input_position] = '\0'; unlock_state = STATE_KEY_PRESSED; redraw_screen(); input_done(); skip_repeated_empty_password = true; return; default: skip_repeated_empty_password = false; } switch (ksym) { case XKB_KEY_u: if (ctrl) { DEBUG("C-u pressed\n"); clear_input(); return; } break; case XKB_KEY_Escape: clear_input(); return; case XKB_KEY_BackSpace: if (input_position == 0) return; /* decrement input_position to point to the previous glyph */ u8_dec(password, &input_position); password[input_position] = '\0'; /* Hide the unlock indicator after a bit if the password buffer is * empty. */ START_TIMER(clear_indicator_timeout, 1.0, clear_indicator_cb); unlock_state = STATE_BACKSPACE_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; return; } if ((input_position + 8) >= sizeof(password)) return; #if 0 /* FIXME: 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)); #endif if (n < 2) return; /* store it in the password array as UTF-8 */ memcpy(password + input_position, buffer, n - 1); input_position += n - 1; DEBUG("current password = %.*s\n", input_position, password); if (unlock_indicator) { unlock_state = STATE_KEY_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; struct ev_timer *timeout = NULL; START_TIMER(timeout, TSTAMP_N_SECS(0.25), redraw_timeout); STOP_TIMER(clear_indicator_timeout); } START_TIMER(discard_passwd_timeout, TSTAMP_N_MINS(3), discard_passwd_cb); }
/* * Handle key presses. Fixes state, then looks up the key symbol for the * given keycode, then looks up the key symbol (as UCS-2), converts it to * UTF-8 and stores it in the password array. * */ static void handle_key_press(xcb_key_press_event_t *event) { xkb_keysym_t ksym; char buffer[128]; int n; bool ctrl; ksym = xkb_state_key_get_one_sym(xkb_state, event->detail); ctrl = xkb_state_mod_name_is_active(xkb_state, "Control", XKB_STATE_MODS_DEPRESSED); /* The buffer will be null-terminated, so n >= 2 for 1 actual character. */ memset(buffer, '\0', sizeof(buffer)); n = xkb_keysym_to_utf8(ksym, buffer, sizeof(buffer)); switch (ksym) { case XKB_KEY_Return: case XKB_KEY_KP_Enter: case XKB_KEY_XF86ScreenSaver: if (skip_without_validation()) { clear_input(); return; } password[input_position] = '\0'; unlock_state = STATE_KEY_PRESSED; redraw_screen(); input_done(); skip_repeated_empty_password = true; return; default: skip_repeated_empty_password = false; } switch (ksym) { case XKB_KEY_u: if (ctrl) { DEBUG("C-u pressed\n"); clear_input(); return; } break; case XKB_KEY_Escape: clear_input(); return; case XKB_KEY_BackSpace: if (input_position == 0) return; /* decrement input_position to point to the previous glyph */ u8_dec(password, &input_position); password[input_position] = '\0'; /* Hide the unlock indicator after a bit if the password buffer is * empty. */ START_TIMER(clear_indicator_timeout, 1.0, clear_indicator_cb); unlock_state = STATE_BACKSPACE_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; return; } if ((input_position + 8) >= sizeof(password)) return; #if 0 /* FIXME: 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)); #endif if (n < 2) return; /* store it in the password array as UTF-8 */ memcpy(password+input_position, buffer, n-1); input_position += n-1; DEBUG("current password = %.*s\n", input_position, password); unlock_state = STATE_KEY_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; struct ev_timer *timeout = NULL; START_TIMER(timeout, TSTAMP_N_SECS(0.25), redraw_timeout); STOP_TIMER(clear_indicator_timeout); START_TIMER(discard_passwd_timeout, TSTAMP_N_MINS(3), discard_passwd_cb); }
/* * Handle key presses. Fixes state, then looks up the key symbol for the * given keycode, then looks up the key symbol (as UCS-2), converts it to * UTF-8 and stores it in the password array. * */ static void handle_key_press(xcb_key_press_event_t *event) { xkb_keysym_t ksym; char buffer[128]; int n; bool ctrl; ksym = xkb_state_key_get_one_sym(xkb_state, event->detail); ctrl = xkb_state_mod_name_is_active(xkb_state, "Control", XKB_STATE_MODS_DEPRESSED); xkb_state_update_key(xkb_state, event->detail, XKB_KEY_DOWN); /* The buffer will be null-terminated, so n >= 2 for 1 actual character. */ memset(buffer, '\0', sizeof(buffer)); n = xkb_keysym_to_utf8(ksym, buffer, sizeof(buffer)); switch (ksym) { case XKB_KEY_Return: case XKB_KEY_KP_Enter: case XKB_KEY_XF86ScreenSaver: password[input_position] = '\0'; unlock_state = STATE_KEY_PRESSED; redraw_screen(); input_done(); return; case XKB_KEY_u: if (ctrl) { DEBUG("C-u pressed\n"); clear_input(); return; } break; case XKB_KEY_Escape: clear_input(); return; case XKB_KEY_BackSpace: if (input_position == 0) return; /* decrement input_position to point to the previous glyph */ u8_dec(password, &input_position); password[input_position] = '\0'; /* Hide the unlock indicator after a bit if the password buffer is * empty. */ start_clear_indicator_timeout(); unlock_state = STATE_BACKSPACE_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; return; } if ((input_position + 8) >= sizeof(password)) return; #if 0 /* FIXME: 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)); #endif if (n < 2) return; /* store it in the password array as UTF-8 */ memcpy(password+input_position, buffer, n-1); input_position += n-1; DEBUG("current password = %.*s\n", input_position, password); unlock_state = STATE_KEY_ACTIVE; redraw_screen(); unlock_state = STATE_KEY_PRESSED; struct ev_timer *timeout = calloc(sizeof(struct ev_timer), 1); if (timeout) { ev_timer_init(timeout, redraw_timeout, 0.25, 0.); ev_timer_start(main_loop, timeout); } stop_clear_indicator_timeout(); }
/* * 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; }