# HG changeset patch # User Bram Moolenaar # Date 1669296603 -3600 # Node ID d6355c3af2111eb9743d4c03e53c48daca770beb # Parent 50ad80360e9981f99c50aae9c0e710e61386ce43 patch 9.0.0939: still using simplified mappings when using kitty protocol Commit: https://github.com/vim/vim/commit/47f1fdc28c6839ec8f5aede631d3a870624767b6 Author: Bram Moolenaar Date: Thu Nov 24 13:27:36 2022 +0000 patch 9.0.0939: still using simplified mappings when using kitty protocol Problem: Still using simplified mappings when using the kitty keyboard protocol. Solution: Use the kitty_protocol_state value to decide whether to use simplified mappings. Improve how seenModifyOtherKeys is set and reset. diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -971,13 +971,18 @@ 1.11 MAPPING IN modifyOtherKeys mode * Xterm and a few other terminals can be put in a mode where keys with modifiers are sent with a special escape code. Vim recognizes these codes and can then make a difference between CTRL-H and Backspace, even when Backspace sends the -character 8. And many more special keys. +character 8. And many more special keys, such as Tab and CTRL-I, which cannot +be mapped separately otherwise. For xterm modifyOtherKeys is enabled in the builtin termcap entry. If this is not used you can enable modifyOtherKeys with these lines in your vimrc: > let &t_TI = "\[>4;2m" let &t_TE = "\[>4;m" +This sets modifyOtherKeys to level 2. Note that modifyOtherKeys level 1 does +not work. Some terminals do not support level 2 and then send key codes that +Vim will not be able to correctly recognize. + In case the modifyOtherKeys mode causes problems you can disable it: > let &t_TI = "" let &t_TE = "" @@ -1001,10 +1006,15 @@ spots an escape sequence that must have detected such an escape sequence use `:verbose map`, the first line will then show "Seen modifyOtherKeys: true" (possibly translated). +This automatic detection depends on receiving an escape code starting with +"<1b>[27;". This is the normal way xterm sends these key codes. However, if +the *formatOtherKeys* resource is set another form is used that is not +recognized, therefore you must not set formatOtherKeys. + A known side effect is that in Insert mode the raw escape sequence is inserted after the CTRL-V key. This can be used to check whether modifyOtherKeys is enabled: In Insert mode type CTRL-SHIFT-V CTRL-V, if you get one byte then -modifyOtherKeys is off, if you get <1b>27;5;118~ then it is on. +modifyOtherKeys is off, if you get <1b>[27;5;118~ then it is on. When the 'esckeys' option is off, then modifyOtherKeys will be disabled in Insert mode to avoid every key with a modifier causing Insert mode to end. diff --git a/src/getchar.c b/src/getchar.c --- a/src/getchar.c +++ b/src/getchar.c @@ -2456,6 +2456,17 @@ check_simplify_modifier(int max_offset) } /* + * Return TRUE if the terminal sends modifiers with various keys. This is when + * modifyOtherKeys level 2 is enabled or the kitty keyboard protocol is + * enabled. + */ + static int +key_protocol_enabled(void) +{ + return seenModifyOtherKeys || kitty_protocol_state == KKPS_ENABLED; +} + +/* * Handle mappings in the typeahead buffer. * - When something was mapped, return map_result_retry for recursive mappings. * - When nothing mapped and typeahead has a character: return map_result_get. @@ -2564,7 +2575,7 @@ handle_mapping( // Skip ":lmap" mappings if keys were mapped. if (mp->m_keys[0] == tb_c1 && (mp->m_mode & local_State) - && !(mp->m_simplified && seenModifyOtherKeys + && !(mp->m_simplified && key_protocol_enabled() && typebuf.tb_maplen == 0) && ((mp->m_mode & MODE_LANGMAP) == 0 || typebuf.tb_maplen == 0)) diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1264,7 +1264,7 @@ struct mapblock int m_keylen; // strlen(m_keys) int m_mode; // valid mode int m_simplified; // m_keys was simplified, do not use this map - // if seenModifyOtherKeys is TRUE + // if key_protocol_enabled() returns TRUE int m_noremap; // if non-zero no re-mapping for m_str char m_silent; // used, don't echo commands char m_nowait; // used diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -3675,9 +3675,16 @@ out_str_t_TE(void) { out_str(T_CTE); + // The seenModifyOtherKeys flag is not reset here. We do expect t_TE to + // disable modifyOtherKeys, but there is no way to detect it's enabled + // again after the following t_TI. We assume that when seenModifyOtherKeys + // was set before it will still be valid. + // When the kitty keyboard protocol is enabled we expect t_TE to disable // it. Remembering that it was detected to be enabled is useful in some // situations. + // The following t_TI is expected to request the state and then + // kitty_protocol_state will be set again. if (kitty_protocol_state == KKPS_ENABLED || kitty_protocol_state == KKPS_DISABLED) kitty_protocol_state = KKPS_DISABLED; @@ -5050,9 +5057,22 @@ handle_key_with_modifier( int modifiers; char_u string[MAX_KEY_CODE_LEN + 1]; + // Only set seenModifyOtherKeys for the "{lead}27;" code to avoid setting + // it for terminals using the kitty keyboard protocol. Xterm sends + // the form ending in "u" when the formatOtherKeys resource is set. We do + // not support this. + // + // Do not set seenModifyOtherKeys if there was a positive response at any + // time from requesting the kitty keyboard protocol state, these are not + // expected to support modifyOtherKeys level 2. + // // Do not set seenModifyOtherKeys for kitty, it does send some sequences // like this but does not have the modifyOtherKeys feature. - if (term_props[TPR_KITTY].tpr_status != TPR_YES) + if (trail != 'u' + && (kitty_protocol_state == KKPS_INITIAL + || kitty_protocol_state == KKPS_OFF + || kitty_protocol_state == KKPS_AFTER_T_KE) + && term_props[TPR_KITTY].tpr_status != TPR_YES) seenModifyOtherKeys = TRUE; if (trail == 'u') @@ -5237,7 +5257,18 @@ handle_csi( { // The protocol has various "progressive enhancement flags" values, but // we only check for zero and non-zero here. - kitty_protocol_state = arg[0] == '0' ? KKPS_OFF : KKPS_ENABLED; + if (arg[0] == '0') + { + kitty_protocol_state = KKPS_OFF; + } + else + { + kitty_protocol_state = KKPS_ENABLED; + + // Reset seenModifyOtherKeys just in case some key combination has + // been seen that set it before we get the status response. + seenModifyOtherKeys = FALSE; + } key_name[0] = (int)KS_EXTRA; key_name[1] = (int)KE_IGNORE; diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 939, +/**/ 938, /**/ 937,