]> git.saurik.com Git - wxWidgets.git/commitdiff
replaced wxYield() call in PopupMenu() by a much safer wxYieldForCommandsOnly() ...
authorVadim Zeitlin <vadim@wxwidgets.org>
Fri, 8 Jun 2001 01:47:15 +0000 (01:47 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Fri, 8 Jun 2001 01:47:15 +0000 (01:47 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@10455 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/app.h
src/msw/app.cpp
src/msw/window.cpp

index 90a612d06c520003c5f75534a75f5478645b1121..79431e92beecbcb87be94a8d477a8a3501d605ee 100644 (file)
@@ -77,10 +77,25 @@ public:
     static void CleanUp();
 
     static bool RegisterWindowClasses();
+
     // Convert Windows to argc, argv style
     void ConvertToStandardCommandArgs(char* p);
+
+    // message processing
+    // ------------------
+
+    // process the given message
+    virtual void DoMessage(WXMSG *pMsg);
+
+    // retrieve the next message from the queue and process it
     virtual bool DoMessage();
+
+    // preprocess the message
     virtual bool ProcessMessage(WXMSG* pMsg);
+
+    // idle processing
+    // ---------------
+
     void DeletePendingObjects();
     bool ProcessIdle();
 
index ed4d7367887739ba8cb9c71fb08307ef66151cdd..5cbf84c3b7825b8fcecf5c50a2399b525205af58 100644 (file)
@@ -957,16 +957,21 @@ bool wxApp::DoMessage()
 #endif // wxUSE_THREADS
 
         // Process the message
-        if ( !ProcessMessage((WXMSG *)&s_currentMsg) )
-        {
-            ::TranslateMessage(&s_currentMsg);
-            ::DispatchMessage(&s_currentMsg);
-        }
+        DoMessage((WXMSG *)&s_currentMsg);
     }
 
     return TRUE;
 }
 
+void wxApp::DoMessage(WXMSG *pMsg)
+{
+    if ( !ProcessMessage(pMsg) )
+    {
+        ::TranslateMessage((MSG *)pMsg);
+        ::DispatchMessage((MSG *)pMsg);
+    }
+}
+
 /*
  * Keep trying to process messages until WM_QUIT
  * received.
index 7b171f9f7cc9c4d11ec8c01ef07129881ab0c8e4..faf7da613622f04c03e2c26453530bbee27c28d0 100644 (file)
@@ -1484,6 +1484,23 @@ void wxWindow::GetCaretPos(int *x, int *y) const
 // popup menu
 // ---------------------------------------------------------------------------
 
+// yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
+// immediately, without waiting for the next event loop iteration
+//
+// NB: this function should probably be made public later as it can almost
+//     surely replace wxYield() elsewhere as well
+static void wxYieldForCommandsOnly()
+{
+    // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
+    // want to process it here)
+    MSG msg;
+    while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE)
+                && msg.message != WM_QUIT )
+    {
+        wxTheApp->DoMessage((WXMSG *)&msg);
+    }
+}
+
 bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
 {
     menu->SetInvokingWindow(this);
@@ -1497,7 +1514,16 @@ bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
     ::ClientToScreen(hWnd, &point);
     wxCurrentPopupMenu = menu;
     ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
-    wxYieldIfNeeded();
+
+    // we need to do it righ now as otherwise the events are never going to be
+    // sent to wxCurrentPopupMenu from HandleCommand()
+    //
+    // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
+    // help and we'd still need wxYieldForCommandsOnly() as the menu may be
+    // destroyed as soon as we return (it can be a local variable in the caller
+    // for example) and so we do need to process the event immediately
+    wxYieldForCommandsOnly();
+
     wxCurrentPopupMenu = NULL;
 
     menu->SetInvokingWindow(NULL);