Patch 8.2.4807
Problem:    Processing key eveints in Win32 GUI is not ideal.
Solution:   Improve processing of key events. (closes #10155)
Files:      src/gui_w32.c


*** ../vim-8.2.4806/src/gui_w32.c       2022-04-13 11:47:21.711886557 +0100
--- src/gui_w32.c       2022-04-22 22:45:08.369018686 +0100
***************
*** 824,837 ****
      static void
  _OnChar(
      HWND hwnd UNUSED,
!     UINT ch,
      int cRepeat UNUSED)
  {
      char_u    string[40];
      int               len = 0;
  
      dead_key = 0;
  
      len = char_to_string(ch, string, 40, FALSE);
      if (len == 1 && string[0] == Ctrl_C && ctrl_c_interrupts)
      {
--- 824,862 ----
      static void
  _OnChar(
      HWND hwnd UNUSED,
!     UINT cch,
      int cRepeat UNUSED)
  {
      char_u    string[40];
      int               len = 0;
+     int               modifiers = 0;
+     int               ch = cch;   // special keys are negative
  
      dead_key = 0;
  
+     if (GetKeyState(VK_SHIFT) & 0x8000)
+       modifiers |= MOD_MASK_SHIFT;
+     if (GetKeyState(VK_CONTROL) & 0x8000)
+       modifiers |= MOD_MASK_CTRL;
+ 
+     ch = simplify_key(ch, &modifiers);
+     // remove the SHIFT modifier for keys where it's already included, e.g.,
+     // '(' and '*'
+     modifiers = may_remove_shift_modifier(modifiers, ch);
+ 
+     // Unify modifiers somewhat.  No longer use ALT to set the 8th bit.
+     ch = extract_modifiers(ch, &modifiers, FALSE, NULL);
+     if (ch == CSI)
+       ch = K_CSI;
+ 
+     if (modifiers)
+     {
+       string[0] = CSI;
+       string[1] = KS_MODIFIER;
+       string[2] = modifiers;
+       add_to_input_buf(string, 3);
+     }
+ 
      len = char_to_string(ch, string, 40, FALSE);
      if (len == 1 && string[0] == Ctrl_C && ctrl_c_interrupts)
      {
***************
*** 858,865 ****
  
      dead_key = 0;
  
-     // TRACE("OnSysChar(%d, %c)\n", ch, ch);
- 
      // OK, we have a character key (given by ch) which was entered with the
      // ALT key pressed. Eg, if the user presses Alt-A, then ch == 'A'. Note
      // that the system distinguishes Alt-a and Alt-A (Alt-Shift-a unless
--- 883,888 ----
***************
*** 1816,1822 ****
                                                          originalMsg.lParam);
  }
  
- 
  /*
   * Process a single Windows message.
   * If one is not available we hang until one is.
--- 1839,1844 ----
***************
*** 1833,1838 ****
--- 1855,1861 ----
  #ifdef FEAT_MENU
      static char_u k10[] = {K_SPECIAL, 'k', ';', 0};
  #endif
+     BYTE      keyboard_state[256];
  
      GetMessageW(&msg, NULL, 0, 0);
  
***************
*** 1894,1911 ****
             * VK_BACK, or VK_ESCAPE it means that he actually wants to deal
             * with the dead char now, so do nothing special and let Windows
             * handle it.
-            *
-            * Note that VK_SPACE combines with the dead_key's character and
-            * only one WM_CHAR will be generated by TranslateMessage(), in
-            * the two other cases two WM_CHAR will be generated: the dead
-            * char and VK_BACK or VK_ESCAPE. That is most likely what the
-            * user expects.
             */
            if ((vk == VK_SPACE || vk == VK_BACK || vk == VK_ESCAPE))
            {
                dead_key = 0;
-               TranslateMessage(&msg);
-               return;
            }
            // In modes where we are not typing, dead keys should behave
            // normally
--- 1917,1926 ----
***************
*** 1926,1931 ****
--- 1941,1953 ----
            add_to_input_buf(string, 1);
        }
  
+       // This is an IME event or a synthetic keystroke, let Windows handle it.
+       if (vk == VK_PROCESSKEY || vk == VK_PACKET)
+       {
+           TranslateMessage(&msg);
+           return;
+       }
+ 
        for (i = 0; special_keys[i].key_sym != 0; i++)
        {
            // ignore VK_SPACE when ALT key pressed: system menu
***************
*** 2005,2043 ****
                break;
            }
        }
        if (special_keys[i].key_sym == 0)
        {
!           // Some keys need C-S- where they should only need C-.
!           // Ignore 0xff, Windows XP sends it when NUMLOCK has changed since
!           // system startup (Helmut Stiegler, 2003 Oct 3).
!           if (vk != 0xff
!                   && (GetKeyState(VK_CONTROL) & 0x8000)
!                   && !(GetKeyState(VK_SHIFT) & 0x8000)
!                   && !(GetKeyState(VK_MENU) & 0x8000))
            {
!               // CTRL-6 is '^'; Japanese keyboard maps '^' to vk == 0xDE
!               if (vk == '6' || MapVirtualKey(vk, 2) == (UINT)'^')
!               {
!                   string[0] = Ctrl_HAT;
!                   add_to_input_buf(string, 1);
!               }
!               // vk == 0xBD AZERTY for CTRL-'-', but CTRL-[ for * QWERTY!
!               else if (vk == 0xBD)    // QWERTY for CTRL-'-'
!               {
!                   string[0] = Ctrl__;
!                   add_to_input_buf(string, 1);
!               }
!               // CTRL-2 is '@'; Japanese keyboard maps '@' to vk == 0xC0
!               else if (vk == '2' || MapVirtualKey(vk, 2) == (UINT)'@')
!               {
!                   string[0] = Ctrl_AT;
!                   add_to_input_buf(string, 1);
!               }
!               else
!                   TranslateMessage(&msg);
            }
            else
!               TranslateMessage(&msg);
        }
      }
  #ifdef FEAT_MBYTE_IME
--- 2027,2084 ----
                break;
            }
        }
+ 
+       // Not a special key.
        if (special_keys[i].key_sym == 0)
        {
!           WCHAR       ch[8];
!           int         len;
!           int         i;
!           UINT        scan_code;
! 
!           if (GetKeyState(VK_SHIFT) & 0x8000)
!               modifiers |= MOD_MASK_SHIFT;
!           if (GetKeyState(VK_CONTROL) & 0x8000)
!               modifiers |= MOD_MASK_CTRL;
!           if (GetKeyState(VK_LMENU) & 0x8000)
!               modifiers |= MOD_MASK_ALT;
! 
!           // Construct the state table with only a few modifiers, we don't
!           // really care about the presence of Ctrl/Alt as those modifiers are
!           // handled by Vim separately.
!           memset(keyboard_state, 0, 256);
!           if (GetKeyState(VK_SHIFT) & 0x8000)
!               keyboard_state[VK_SHIFT] = 0x80;
!           if (GetKeyState(VK_RMENU) & 0x8000)
            {
!               keyboard_state[VK_MENU] = 0x80;
!               keyboard_state[VK_CONTROL] = 0x80;
!           }
! 
!           // Translate the virtual key according to the current keyboard
!           // layout.
!           scan_code = MapVirtualKey(vk, MAPVK_VK_TO_VSC);
!           // Convert the scan-code into a sequence of zero or more unicode
!           // codepoints.
!           // If this is a dead key ToUnicode returns a negative value.
!           len = ToUnicode(vk, scan_code, keyboard_state, ch, ARRAY_LENGTH(ch),
!                   0);
!           dead_key = len < 0;
! 
!           if (len <= 0)
!               return;
! 
!           // Post the message as TranslateMessage would do.
!           if (msg.message == WM_KEYDOWN)
!           {
!               for (i = 0; i < len; i++)
!                   PostMessageW(msg.hwnd, WM_CHAR, ch[i], msg.lParam);
            }
            else
!           {
!               for (i = 0; i < len; i++)
!                   PostMessageW(msg.hwnd, WM_SYSCHAR, ch[i], msg.lParam);
!           }
        }
      }
  #ifdef FEAT_MBYTE_IME
***************
*** 3728,3735 ****
      POINT   pt;
      int_u   modifiers = 0;
  
-     // TRACE("_OnDropFiles: %d files dropped\n", cFiles);
- 
      // Obtain dropped position
      DragQueryPoint(hDrop, &pt);
      MapWindowPoints(s_hwnd, s_textArea, &pt, 1);
--- 3769,3774 ----
***************
*** 4580,4589 ****
      WPARAM wParam,
      LPARAM lParam)
  {
!     /*
!     TRACE("WndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
!         hwnd, uMsg, wParam, lParam);
!     */
  
      HandleMouseHide(uMsg, lParam);
  
--- 4619,4626 ----
      WPARAM wParam,
      LPARAM lParam)
  {
!     // TRACE("WndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
!     //       hwnd, uMsg, wParam, lParam);
  
      HandleMouseHide(uMsg, lParam);
  
***************
*** 4635,4654 ****
        }
        break;
  
-     case WM_KEYUP:
-       // handle CTRL-/
-       if ((GetKeyState(VK_CONTROL) & 0x8000) != 0 && wParam == 0xBF)
-       {
-           char_u string[4];
- 
-           string[0] = CSI;
-           string[1] = KS_MODIFIER;
-           string[2] = MOD_MASK_CTRL;
-           string[3] = 0x2F;
-           add_to_input_buf(string, 4);
-       }
-       return 0L;
- 
      case WM_CHAR:
        // Don't use HANDLE_MSG() for WM_CHAR, it truncates wParam to a single
        // byte while we want the UTF-16 character value.
--- 4672,4677 ----
*** ../vim-8.2.4806/src/version.c       2022-04-22 21:20:22.829092772 +0100
--- src/version.c       2022-04-22 22:45:20.280996863 +0100
***************
*** 748,749 ****
--- 748,751 ----
  {   /* Add new patch number below this line */
+ /**/
+     4807,
  /**/

-- 
A day without sunshine is like, well, night.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20220422214630.919541C13F1%40moolenaar.net.

Raspunde prin e-mail lui