]> git.saurik.com Git - wxWidgets.git/commitdiff
Fix generation of key events for non-alphabetic keys under Windows.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 11 Sep 2010 10:19:02 +0000 (10:19 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 11 Sep 2010 10:19:02 +0000 (10:19 +0000)
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
src/msw/listctrl.cpp
src/msw/window.cpp

index 5bc8cc74452def405e77b71f8a86816fa164153c..ef32ae28a1a60613f8ed86de861a84f94b4669ac 100644 (file)
@@ -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
index 6e526f3784a82b91785db0acc47755b4924454d7..9308756df2bb38e2fe2dd50459d46fc9964081fa 100644 (file)
@@ -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 =
index d389407b7007bf7e171d622d38bd26a093ca7c80..332e309cde3eb473cb69b6c3179ac8db814d8175 100644 (file)
@@ -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;