diff --git a/input-keys.c b/input-keys.c index 342a3dd8..e690a3a8 100644 --- a/input-keys.c +++ b/input-keys.c @@ -557,10 +557,6 @@ input_key_mode1(struct bufferevent *bev, key_code key) (onlykey >= '@' && onlykey <= '~'))) return (input_key_vt10x(bev, key)); - /* Avoid reporting A as Shift-A, which is not expected in mode 1. */ - if ((key & KEYC_MASK_MODIFIERS) == KEYC_SHIFT) - return (input_key_vt10x(bev, key)); - /* * A regular key + Meta. In the absence of a standard to back this, we * mimic what iTerm 2 does. diff --git a/tty-keys.c b/tty-keys.c index 9a0f3ea6..8c77d031 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -1016,7 +1016,7 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, u_int number, modifiers; char tmp[64]; cc_t bspace; - key_code nkey; + key_code nkey, onlykey; struct utf8_data ud; utf8_char uc; @@ -1080,13 +1080,7 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, /* Update the modifiers. */ if (modifiers > 0) { modifiers--; - /* - * The Shift modifier may not be reported in some input modes, - * which is unfortunate, as in general case determining if a - * character is shifted or not requires knowing the input - * keyboard layout. So we only fix up the trivial case. - */ - if (modifiers & 1 || (nkey >= 'A' && nkey <= 'Z')) + if (modifiers & 1) nkey |= KEYC_SHIFT; if (modifiers & 2) nkey |= (KEYC_META|KEYC_IMPLIED_META); /* Alt */ @@ -1100,6 +1094,26 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, if ((nkey & KEYC_MASK_KEY) == '\011' && (nkey & KEYC_SHIFT)) nkey = KEYC_BTAB | (nkey & ~KEYC_MASK_KEY & ~KEYC_SHIFT); + /* + * Deal with the Shift modifier when present alone. The problem is that + * in mode 2 some terminals would report shifted keys, like S-a, as + * just A, and some as S-A. + * + * Because we need an unambiguous internal representation, and because + * restoring the Shift modifier when it's missing would require knowing + * the keyboard layout, and because S-A would cause a lot of issues + * downstream, we choose to lose the Shift for all printable + * characters. + * + * That still leaves some ambiguity, such as C-S-A vs. C-A, but that's + * OK, and applications can handle that. + */ + onlykey = nkey & KEYC_MASK_KEY; + if (((onlykey > 0x20 && onlykey < 0x7f) || + KEYC_IS_UNICODE(nkey)) && + (nkey & KEYC_MASK_MODIFIERS) == KEYC_SHIFT) + nkey &= ~KEYC_SHIFT; + if (log_get_level() != 0) { log_debug("%s: extended key %.*s is %llx (%s)", c->name, (int)*size, buf, nkey, key_string_lookup_key(nkey, 1));