- DEBUG("keypress %d, state raw = %d, modeswitch_active = %d, iso_level3_shift_active = %d\n",
- event->detail, event->state, modeswitch_active, iso_level3_shift_active);
-
- xcb_keysym_t sym0, sym1, sym;
- /* For each keycode, there is a list of symbols. The list could look like this:
- * $ xmodmap -pke | grep 'keycode 38'
- * keycode 38 = a A adiaeresis Adiaeresis o O
- * In non-X11 terminology, the symbols for the keycode 38 (the key labeled
- * with "a" on my keyboard) are "a A ä Ä o O".
- * Another form to display the same information is using xkbcomp:
- * $ xkbcomp $DISPLAY /tmp/xkb.dump
- * Then open /tmp/xkb.dump and search for '\<a\>' (in VIM regexp-language):
- *
- * symbols[Group1]= [ a, A, o, O ],
- * symbols[Group2]= [ adiaeresis, Adiaeresis ]
- *
- * So there are two *groups*, one containing 'a A' and one containing 'ä
- * Ä'. You can use Mode_switch to switch between these groups. You can use
- * ISO_Level3_Shift to reach the 'o O' part of the first group (it’s the
- * same group, just an even higher shift level).
- *
- * So, using the "logical" XKB information, the following lookup will be
- * performed:
- *
- * Neither Mode_switch nor ISO_Level3_Shift active: group 1, column 0 and 1
- * Mode_switch active: group 2, column 0 and 1
- * ISO_Level3_Shift active: group 1, column 2 and 3
- *
- * Using the column index which xcb_key_press_lookup_keysym uses (and
- * xmodmap prints out), the following lookup will be performed:
- *
- * Neither Mode_switch nor ISO_Level3_Shift active: column 0 and 1
- * Mode_switch active: column 2 and 3
- * ISO_Level3_Shift active: column 4 and 5
- */
- int base_column = 0;
- if (modeswitch_active)
- base_column = 2;
- if (iso_level3_shift_active)
- base_column = 4;
- if (iso_level5_shift_active)
- base_column = 6;
- sym0 = xcb_key_press_lookup_keysym(symbols, event, base_column);
- sym1 = xcb_key_press_lookup_keysym(symbols, event, base_column + 1);
- switch (sym0) {
- case XK_Mode_switch:
- DEBUG("Mode switch enabled\n");
- modeswitch_active = true;
- return;
- case XK_ISO_Level3_Shift:
- DEBUG("ISO_Level3_Shift enabled\n");
- iso_level3_shift_active = true;
- return;
- case XK_ISO_Level5_Shift:
- DEBUG("ISO_Level5_Shift enabled\n");
- iso_level5_shift_active = true;
- return;
- case XK_Return:
- case XK_KP_Enter:
- input_done();
- case XK_Escape:
- input_position = 0;
- clear_password_memory();
- password[input_position] = '\0';
- return;
+ 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;