diff options
Diffstat (limited to 'input/keycodes.c')
-rw-r--r-- | input/keycodes.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/input/keycodes.c b/input/keycodes.c index 078e29f361..00f983e140 100644 --- a/input/keycodes.c +++ b/input/keycodes.c @@ -239,14 +239,14 @@ found: struct bstr rest; int code = bstr_decode_utf8(bname, &rest); if (code >= 0 && rest.len == 0) - return code + modifiers; + return mp_normalize_keycode(code + modifiers); if (bstr_startswith0(bname, "0x")) - return strtol(name, NULL, 16) + modifiers; + return mp_normalize_keycode(strtol(name, NULL, 16) + modifiers); for (int i = 0; key_names[i].name != NULL; i++) { if (strcasecmp(key_names[i].name, name) == 0) - return key_names[i].key + modifiers; + return mp_normalize_keycode(key_names[i].key + modifiers); } return -1; @@ -330,3 +330,25 @@ void mp_print_key_list(struct mp_log *out) for (int i = 0; key_names[i].name != NULL; i++) mp_info(out, "%s\n", key_names[i].name); } + +int mp_normalize_keycode(int keycode) +{ + if (keycode <= 0) + return keycode; + int code = keycode & ~MP_KEY_MODIFIER_MASK; + int mod = keycode & MP_KEY_MODIFIER_MASK; + /* On normal keyboards shift changes the character code of non-special + * keys, so don't count the modifier separately for those. In other words + * we want to have "a" and "A" instead of "a" and "Shift+A"; but a separate + * shift modifier is still kept for special keys like arrow keys. */ + if (code >= 32 && code < MP_KEY_BASE) { + /* Still try to support ASCII case-modifications properly. For example, + * we want to change "Shift+a" to "A", not "a". Doing this for unicode + * in general would require huge lookup tables, or a libc with proper + * unicode support, so we don't do that. */ + if (code >= 'a' && code <= 'z' && (mod & MP_KEY_MODIFIER_SHIFT)) + code &= 0x5F; + mod &= ~MP_KEY_MODIFIER_SHIFT; + } + return code | mod; +} |