]> git.saurik.com Git - wxWidgets.git/commitdiff
Fix recently broken generation of wxEVT_CHAR_HOOK events in wxMSW.
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 22 Sep 2010 13:31:32 +0000 (13:31 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 22 Sep 2010 13:31:32 +0000 (13:31 +0000)
Changes to VKToWX() semantics broke the logic of the global keyboard hook
function in wxMSW which didn't generate wxEVT_CHAR_HOOK events for ASCII
special keys such as WXK_ESCAPE any more.

Fix this and also generate wxEVT_CHAR_HOOK for all events, not just the
non-ASCII keys for consistency with the documentation and wxGTK.

Closes #12501.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65589 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/msw/window.cpp

index c9015b7469764d797761efcdfa25a17be87a2635..7c21aaee024e788a3936e574592462f1a11adf0f 100644 (file)
@@ -5632,28 +5632,65 @@ void wxWindowMSW::GenerateMouseLeave()
 // keyboard handling
 // ---------------------------------------------------------------------------
 
+namespace
+{
+
+// Implementation of InitAnyKeyEvent() which can also be used when there is no
+// associated window: this can happen for the wxEVT_CHAR_HOOK events created by
+// the global keyboard hook (e.g. the event might have happened in a non-wx
+// window).
 void
-wxWindowMSW::InitAnyKeyEvent(wxKeyEvent& event,
-                             WXWPARAM wParam,
-                             WXLPARAM lParam) const
+MSWInitAnyKeyEvent(wxKeyEvent& event,
+                   WXWPARAM wParam,
+                   WXLPARAM lParam,
+                   const wxWindow *win /* may be NULL */)
 {
-    event.SetId(GetId());
+    if ( win )
+    {
+        event.SetId(win->GetId());
+        event.SetEventObject(const_cast<wxWindow *>(win));
+    }
+    else // No associated window.
+    {
+        // Use wxID_ANY for compatibility with the old code even if wxID_NONE
+        // would arguably make more sense.
+        event.SetId(wxID_ANY);
+    }
+
     event.m_shiftDown = wxIsShiftDown();
     event.m_controlDown = wxIsCtrlDown();
     event.m_altDown = (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN;
 
-    event.SetEventObject(const_cast<wxWindow *>(this));
-
     event.m_rawCode = (wxUint32) wParam;
     event.m_rawFlags = (wxUint32) lParam;
 #ifndef __WXWINCE__
     event.SetTimestamp(::GetMessageTime());
 #endif
 
-    // translate the position to client coordinates
-    const wxPoint mousePos = ScreenToClient(wxGetMousePosition());
-    event.m_x = mousePos.x;
-    event.m_y = mousePos.y;
+    // Event coordinates must be in window client coordinates system which
+    // doesn't make sense if there is no window.
+    //
+    // We could use screen coordinates for such events but this would make the
+    // logic of the event handlers more complicated: you'd need to test for the
+    // event object and interpret the coordinates differently according to
+    // whether it's NULL or not so unless somebody really asks for this let's
+    // just avoid the issue.
+    if ( win )
+    {
+        const wxPoint mousePos = win->ScreenToClient(wxGetMousePosition());
+        event.m_x = mousePos.x;
+        event.m_y = mousePos.y;
+    }
+}
+
+} // anonymous namespace
+
+void
+wxWindowMSW::InitAnyKeyEvent(wxKeyEvent& event,
+                             WXWPARAM wParam,
+                             WXLPARAM lParam) const
+{
+    MSWInitAnyKeyEvent(event, wParam, lParam, this);
 }
 
 wxKeyEvent
@@ -6560,32 +6597,22 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
     DWORD hiWord = HIWORD(lParam);
     if ( nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0) )
     {
-        int id = wxMSWKeyboard::VKToWX(wParam, lParam);
-        if ( id >= WXK_START )
+        wchar_t uc;
+        int id = wxMSWKeyboard::VKToWX(wParam, lParam, &uc);
+        if ( id != WXK_NONE )
         {
+            const wxWindow * const win = wxGetActiveWindow();
+
             wxKeyEvent event(wxEVT_CHAR_HOOK);
-            if ( (HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN )
-                event.m_altDown = true;
+            MSWInitAnyKeyEvent(event, wParam, lParam, win);
 
-            event.SetEventObject(NULL);
             event.m_keyCode = id;
-            event.m_shiftDown = wxIsShiftDown();
-            event.m_controlDown = wxIsCtrlDown();
-#ifndef __WXWINCE__
-            event.SetTimestamp(::GetMessageTime());
-#endif
-            wxWindow *win = wxGetActiveWindow();
-            wxEvtHandler *handler;
-            if ( win )
-            {
-                handler = win->GetEventHandler();
-                event.SetId(win->GetId());
-            }
-            else
-            {
-                handler = wxTheApp;
-                event.SetId(wxID_ANY);
-            }
+#if wxUSE_UNICODE
+            event.m_uniChar = uc;
+#endif // wxUSE_UNICODE
+
+            wxEvtHandler * const handler = win ? win->GetEventHandler()
+                                               : wxTheApp;
 
             if ( handler && handler->ProcessEvent(event) )
             {