Improve fix for shifted keys so it works for all the keys it should,
authornicm <nicm@openbsd.org>
Thu, 3 Oct 2024 05:41:59 +0000 (05:41 +0000)
committernicm <nicm@openbsd.org>
Thu, 3 Oct 2024 05:41:59 +0000 (05:41 +0000)
Stanislav Kljuhhin in GitHub issue 4146.

usr.bin/tmux/input-keys.c
usr.bin/tmux/tty-keys.c

index f775685..fc6cf7f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: input-keys.c,v 1.100 2024/10/02 08:06:45 nicm Exp $ */
+/* $OpenBSD: input-keys.c,v 1.101 2024/10/03 05:41:59 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -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.
index e01f52a..d95ded3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty-keys.c,v 1.180 2024/10/01 06:15:47 nicm Exp $ */
+/* $OpenBSD: tty-keys.c,v 1.181 2024/10/03 05:41:59 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -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));