Don't intercept Escape key while IME is active.
authorVadim Zeitlin <vadim@wxwidgets.org>
Mon, 14 Mar 2011 11:54:51 +0000 (11:54 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Mon, 14 Mar 2011 11:54:51 +0000 (11:54 +0000)
Escape is used by IME and intercepting it at wxWidgets level to generate
EVT_CHAR_HOOK breaks the IME UI and may result in unexpected loss of data
entered by user.

To work around this, don't generate EVT_CHAR_HOOK for Escape while IME is
active by checking for the special semaphore variable (which could be also
used for other things in the future, see #9102) value.

Closes #11386.

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

src/msw/window.cpp

index 71e169e0bcce8dda03c519e7ae29d6f245af63fe..e1d2af0ad754e2c1cdf682b5a85e3371632d4c2e 100644 (file)
@@ -228,6 +228,15 @@ EraseBgHooks gs_eraseBgHooks;
 
 #endif // wxHAS_MSW_BACKGROUND_ERASE_HOOK
 
+// If this variable is strictly positive, EVT_CHAR_HOOK is not generated for
+// Escape key presses as it can't be intercepted because it's needed by some
+// currently shown window, e.g. IME entry.
+//
+// This is currently global as we allow using UI from the main thread only
+// anyhow but could be replaced with a thread-specific value in the future if
+// needed.
+int gs_modalEntryWindowCount = 0;
+
 } // anonymous namespace
 
 // ---------------------------------------------------------------------------
@@ -3171,6 +3180,17 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
             }
             break;
 
+        case WM_IME_STARTCOMPOSITION:
+            // IME popup needs Escape as it should undo the changes in its
+            // entry window instead of e.g. closing the dialog for which the
+            // IME is used (and losing all the changes in the IME window).
+            gs_modalEntryWindowCount++;
+            break;
+
+        case WM_IME_ENDCOMPOSITION:
+            gs_modalEntryWindowCount--;
+            break;
+
 #if wxUSE_HOTKEY
         case WM_HOTKEY:
             processed = HandleHotKey((WORD)wParam, lParam);
@@ -6497,29 +6517,36 @@ wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
     {
         wchar_t uc;
         int id = wxMSWKeyboard::VKToWX(wParam, lParam, &uc);
-        if ( id != WXK_NONE
+
+        // Don't intercept keyboard entry (notably Escape) if a modal window
+        // (not managed by wx, e.g. IME one) is currently opened as more often
+        // than not it needs all the keys for itself.
+        if ( !gs_modalEntryWindowCount )
+        {
+            if ( id != WXK_NONE
 #if wxUSE_UNICODE
-                || static_cast<int>(uc) != WXK_NONE
+                    || static_cast<int>(uc) != WXK_NONE
 #endif // wxUSE_UNICODE
-                )
-        {
-            const wxWindow * const win = wxGetActiveWindow();
+                    )
+            {
+                const wxWindow * const win = wxGetActiveWindow();
 
-            wxKeyEvent event(wxEVT_CHAR_HOOK);
-            MSWInitAnyKeyEvent(event, wParam, lParam, win);
+                wxKeyEvent event(wxEVT_CHAR_HOOK);
+                MSWInitAnyKeyEvent(event, wParam, lParam, win);
 
-            event.m_keyCode = id;
+                event.m_keyCode = id;
 #if wxUSE_UNICODE
-            event.m_uniChar = uc;
+                event.m_uniChar = uc;
 #endif // wxUSE_UNICODE
 
-            wxEvtHandler * const handler = win ? win->GetEventHandler()
-                                               : wxTheApp;
+                wxEvtHandler * const handler = win ? win->GetEventHandler()
+                                                   : wxTheApp;
 
-            if ( handler && handler->ProcessEvent(event) )
-            {
-                // processed
-                return 1;
+                if ( handler && handler->ProcessEvent(event) )
+                {
+                    // processed
+                    return 1;
+                }
             }
         }
     }