patch 8.2.4807: processing key eveints in Win32 GUI is not ideal
Problem: Processing key eveints in Win32 GUI is not ideal. Solution: Improve processing of key events. (closes #10155)
This commit is contained in:
143
src/gui_w32.c
143
src/gui_w32.c
@ -824,14 +824,39 @@ char_to_string(int ch, char_u *string, int slen, int had_alt)
|
||||
static void
|
||||
_OnChar(
|
||||
HWND hwnd UNUSED,
|
||||
UINT ch,
|
||||
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,8 +883,6 @@ _OnSysChar(
|
||||
|
||||
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
|
||||
@ -1816,7 +1839,6 @@ outputDeadKey_rePost(MSG originalMsg)
|
||||
originalMsg.lParam);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process a single Windows message.
|
||||
* If one is not available we hang until one is.
|
||||
@ -1833,6 +1855,7 @@ process_message(void)
|
||||
#ifdef FEAT_MENU
|
||||
static char_u k10[] = {K_SPECIAL, 'k', ';', 0};
|
||||
#endif
|
||||
BYTE keyboard_state[256];
|
||||
|
||||
GetMessageW(&msg, NULL, 0, 0);
|
||||
|
||||
@ -1894,18 +1917,10 @@ process_message(void)
|
||||
* 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
|
||||
@ -1926,6 +1941,13 @@ process_message(void)
|
||||
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,39 +2027,58 @@ process_message(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Not a special key.
|
||||
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))
|
||||
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)
|
||||
{
|
||||
// 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);
|
||||
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
|
||||
TranslateMessage(&msg);
|
||||
{
|
||||
for (i = 0; i < len; i++)
|
||||
PostMessageW(msg.hwnd, WM_SYSCHAR, ch[i], msg.lParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef FEAT_MBYTE_IME
|
||||
@ -3728,8 +3769,6 @@ _OnDropFiles(
|
||||
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);
|
||||
@ -4580,10 +4619,8 @@ _WndProc(
|
||||
WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
/*
|
||||
TRACE("WndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
|
||||
hwnd, uMsg, wParam, lParam);
|
||||
*/
|
||||
// TRACE("WndProc: hwnd = %08x, msg = %x, wParam = %x, lParam = %x\n",
|
||||
// hwnd, uMsg, wParam, lParam);
|
||||
|
||||
HandleMouseHide(uMsg, lParam);
|
||||
|
||||
@ -4635,20 +4672,6 @@ _WndProc(
|
||||
}
|
||||
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.
|
||||
|
||||
@ -746,6 +746,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
4807,
|
||||
/**/
|
||||
4806,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user