From 5844ad30dd364fd9121b947dfb5164f4ad3a94da Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 11 Sep 2010 10:19:02 +0000 Subject: [PATCH] Fix generation of key events for non-alphabetic keys under Windows. Don't hardcode the values of VK_OEM_XXX keys which are completely nonsensical on keyboards with non-US layouts. Use the real unshifted value of the key as its key code instead -- at least if it's a Latin-1 character. Otherwise, use WXK_NONE as the key code and pass the character generated by the key as Unicode character code. Also generate WXK_NONE events for dead keys to avoid confusing them with the corresponding normal key events. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65525 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/msw/private/keyboard.h | 6 +- src/msw/listctrl.cpp | 8 +++ src/msw/window.cpp | 107 ++++++++++++++++++++++-------- 3 files changed, 92 insertions(+), 29 deletions(-) diff --git a/include/wx/msw/private/keyboard.h b/include/wx/msw/private/keyboard.h index 5bc8cc7445..ef32ae28a1 100644 --- a/include/wx/msw/private/keyboard.h +++ b/include/wx/msw/private/keyboard.h @@ -25,7 +25,11 @@ namespace wxMSWKeyboard // Translate MSW virtual key code to wx key code. lParam is used to distinguish // between numpad and extended version of the keys, extended is assumed by // default if lParam == 0. -WXDLLIMPEXP_CORE int VKToWX(WXWORD vk, WXLPARAM lParam = 0); +// +// Returns WXK_NONE if translation couldn't be done at all (this happens e.g. +// for dead keys) or if the key corresponds to a non-ASCII character in which +// case uc is filled with its Unicode value. +WXDLLIMPEXP_CORE int VKToWX(WXWORD vk, WXLPARAM lParam = 0, wchar_t *uc = NULL); // Translate wxKeyCode enum element (passed as int for compatibility reasons) // to MSW virtual key code. isExtended is set to true if the key corresponds to diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index 6e526f3784..9308756df2 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -2342,6 +2342,14 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) eventType = wxEVT_COMMAND_LIST_KEY_DOWN; event.m_code = wxMSWKeyboard::VKToWX(wVKey); + + if ( event.m_code == WXK_NONE ) + { + // We can't translate this to a standard key code, + // until support for Unicode key codes is added to + // wxListEvent we just ignore them. + return false; + } } event.m_itemIndex = diff --git a/src/msw/window.cpp b/src/msw/window.cpp index d389407b70..332e309cde 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -5665,17 +5665,14 @@ wxWindowMSW::CreateKeyEvent(wxEventType evType, wxKeyEvent event(evType); InitAnyKeyEvent(event, wParam, lParam); - event.m_keyCode = wxMSWKeyboard::VKToWX(wParam, lParam); + event.m_keyCode = wxMSWKeyboard::VKToWX + ( + wParam, + lParam #if wxUSE_UNICODE - if ( event.m_keyCode < WXK_START ) - { - // It's an ASCII character, set Unicode key code to the same value - // for compatibility (both with the previous versions of wx and with - // the other ports), even if it's not very useful for these events as - // Unicode character is/should be mostly used by EVT_CHAR handlers. - event.m_uniChar = event.m_keyCode; - } + , &event.m_uniChar #endif // wxUSE_UNICODE + ); return event; } @@ -6158,32 +6155,76 @@ const struct wxKeyMapping } // anonymous namespace -int VKToWX(WXWORD vk, WXLPARAM lParam) +int VKToWX(WXWORD vk, WXLPARAM lParam, wchar_t *uc) { + int wxk; + // check the table first for ( size_t n = 0; n < WXSIZEOF(gs_specialKeys); n++ ) { if ( gs_specialKeys[n].vk == vk ) - return gs_specialKeys[n].wxk; + { + wxk = gs_specialKeys[n].wxk; + if ( wxk < WXK_START ) + { + // Unicode code for this key is the same as its ASCII code. + if ( uc ) + *uc = wxk; + } + + return wxk; + } } // keys requiring special handling - int wxk; switch ( vk ) { - // the mapping for these keys may be incorrect on non-US keyboards so - // maybe we shouldn't map them to ASCII values at all - case VK_OEM_1: wxk = ';'; break; - case VK_OEM_PLUS: wxk = '+'; break; - case VK_OEM_COMMA: wxk = ','; break; - case VK_OEM_MINUS: wxk = '-'; break; - case VK_OEM_PERIOD: wxk = '.'; break; - case VK_OEM_2: wxk = '/'; break; - case VK_OEM_3: wxk = '~'; break; - case VK_OEM_4: wxk = '['; break; - case VK_OEM_5: wxk = '\\'; break; - case VK_OEM_6: wxk = ']'; break; - case VK_OEM_7: wxk = '\''; break; + case VK_OEM_1: + case VK_OEM_PLUS: + case VK_OEM_COMMA: + case VK_OEM_MINUS: + case VK_OEM_PERIOD: + case VK_OEM_2: + case VK_OEM_3: + case VK_OEM_4: + case VK_OEM_5: + case VK_OEM_6: + case VK_OEM_7: + // MapVirtualKey() returns 0 if it fails to convert the virtual + // key which nicely corresponds to our WXK_NONE. + wxk = ::MapVirtualKey(vk, MAPVK_VK_TO_CHAR); + + if ( HIWORD(wxk) & 0x8000 ) + { + // It's a dead key and we don't return anything at all for them + // as we simply don't have any way to indicate the difference + // between e.g. a normal "'" and "'" as a dead key -- and + // generating the same events for them just doesn't seem like a + // good idea. + wxk = WXK_NONE; + } + else // Not a dead key. + { + // In any case return this as a Unicode character value. + if ( uc ) + *uc = wxk; + + // For compatibility with the old non-Unicode code we continue + // returning key codes for Latin-1 characters directly + // (normally it would really only make sense to do it for the + // ASCII characters, not Latin-1 ones). + if ( wxk > 255 ) + { + // But for anything beyond this we can only return the key + // value as a real Unicode character, not a wxKeyCode + // because this enum values clash with Unicode characters + // (e.g. WXK_LBUTTON also happens to be U+012C a.k.a. + // "LATIN CAPITAL LETTER I WITH BREVE"). + wxk = WXK_NONE; + } + // + } + break; // handle extended keys case VK_PRIOR: @@ -6233,9 +6274,19 @@ int VKToWX(WXWORD vk, WXLPARAM lParam) break; default: - // must be a simple alphanumeric key and the values of them - // coincide in Windows and wx - wxk = vk; + if ( (vk >= '0' && vk <= '9') || (vk >= 'A' && vk <= 'Z') ) + { + // A simple alphanumeric key and the values of them coincide in + // Windows and wx for both ASCII and Unicode codes. + wxk = vk; + + if ( uc ) + *uc = vk; + } + else // Something we simply don't know about at all. + { + wxk = WXK_NONE; + } } return wxk; -- 2.45.2