]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/evtloop.cpp
second part of #10320: move wxApp event handling functions to wxEventLoopBase (in...
[wxWidgets.git] / src / msw / evtloop.cpp
index 96e618066449a292e439f4a5c4a59c53f190c374..aa294c31c4787f1559d037d4f8b11c9d2fa9c822 100644 (file)
@@ -35,6 +35,7 @@
 #include "wx/thread.h"
 #include "wx/except.h"
 #include "wx/msw/private.h"
+#include "wx/scopeguard.h"
 
 #if wxUSE_GUI
     #include "wx/tooltip.h"
@@ -358,6 +359,164 @@ void wxGUIEventLoop::WakeUp()
     ::PostMessage(NULL, WM_NULL, 0, 0);
 }
 
+
+// ----------------------------------------------------------------------------
+// Yield to incoming messages
+// ----------------------------------------------------------------------------
+
+#include <wx/arrimpl.cpp>
+WX_DEFINE_OBJARRAY(wxMSGArray);
+
+bool wxGUIEventLoop::YieldFor(long eventsToProcess)
+{
+    // set the flag and don't forget to reset it before returning
+    m_isInsideYield = true;
+    m_eventsToProcessInsideYield = eventsToProcess;
+
+    wxON_BLOCK_EXIT_SET(m_isInsideYield, false);
+
+#if wxUSE_LOG
+    // disable log flushing from here because a call to wxYield() shouldn't
+    // normally result in message boxes popping up &c
+    wxLog::Suspend();
+
+    // ensure the logs will be flashed again when we exit
+    wxON_BLOCK_EXIT0(wxLog::Resume);
+#endif // wxUSE_LOG
+
+    // we don't want to process WM_QUIT from here - it should be processed in
+    // the main event loop in order to stop it
+    MSG msg;
+    while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
+            msg.message != WM_QUIT )
+    {
+#if wxUSE_THREADS
+        wxMutexGuiLeaveOrEnter();
+#endif // wxUSE_THREADS
+
+        if (msg.message == WM_PAINT)
+        {
+            // WM_PAINT messages are the last ones of the queue...
+            break;
+        }
+
+        // choose a wxEventCategory for this Windows message
+        wxEventCategory cat;
+        switch (msg.message)
+        {
+            case WM_NCMOUSEMOVE:
+            case WM_NCLBUTTONDOWN:
+            case WM_NCLBUTTONUP:
+            case WM_NCLBUTTONDBLCLK:
+            case WM_NCRBUTTONDOWN:
+            case WM_NCRBUTTONUP:
+            case WM_NCRBUTTONDBLCLK:
+            case WM_NCMBUTTONDOWN:
+            case WM_NCMBUTTONUP:
+            case WM_NCMBUTTONDBLCLK:
+
+            case WM_KEYDOWN:
+            case WM_KEYUP:
+            case WM_CHAR:
+            case WM_DEADCHAR:
+            case WM_SYSKEYDOWN:
+            case WM_SYSKEYUP:
+            case WM_SYSCHAR:
+            case WM_SYSDEADCHAR:
+#ifdef WM_UNICHAR
+            case WM_UNICHAR:
+#endif
+            case WM_HOTKEY:
+            case WM_IME_STARTCOMPOSITION:
+            case WM_IME_ENDCOMPOSITION:
+            case WM_IME_COMPOSITION:
+            case WM_COMMAND:
+            case WM_SYSCOMMAND:
+
+            case WM_IME_SETCONTEXT:
+            case WM_IME_NOTIFY:
+            case WM_IME_CONTROL:
+            case WM_IME_COMPOSITIONFULL:
+            case WM_IME_SELECT:
+            case WM_IME_CHAR:
+            case WM_IME_KEYDOWN:
+            case WM_IME_KEYUP:
+
+            case WM_MOUSEHOVER:
+#ifdef WM_NCMOUSELEAVE
+            case WM_NCMOUSELEAVE:
+#endif
+            case WM_MOUSELEAVE:
+
+            case WM_CUT:
+            case WM_COPY:
+            case WM_PASTE:
+            case WM_CLEAR:
+            case WM_UNDO:
+
+            case WM_MOUSEMOVE:
+            case WM_LBUTTONDOWN:
+            case WM_LBUTTONUP:
+            case WM_LBUTTONDBLCLK:
+            case WM_RBUTTONDOWN:
+            case WM_RBUTTONUP:
+            case WM_RBUTTONDBLCLK:
+            case WM_MBUTTONDOWN:
+            case WM_MBUTTONUP:
+            case WM_MBUTTONDBLCLK:
+            case WM_MOUSEWHEEL:
+                cat = wxEVT_CATEGORY_USER_INPUT;
+                break;
+
+            case WM_TIMER:
+                cat = wxEVT_CATEGORY_TIMER;
+                break;
+
+            default:
+                if (msg.message < WM_USER)
+                {
+                    // 0;WM_USER-1 is the range of message IDs reserved for use
+                    // by the system.
+
+                    // there are too many of these types of messages to handle
+                    // them in this switch
+                    cat = wxEVT_CATEGORY_UI;
+                }
+                else
+                    cat = wxEVT_CATEGORY_UNKNOWN;
+        }
+
+        // should we process this event now?
+        if (cat & eventsToProcess)
+        {
+            if ( !wxTheApp->Dispatch() )
+                break;
+        }
+        else
+        {
+            // remove the message and store it
+            ::GetMessage(&msg, NULL, 0, 0);
+            m_arrMSG.Add(msg);
+        }
+    }
+
+    // if there are pending events, we must process them.
+    ProcessPendingEvents();
+
+    // put back unprocessed events in the queue
+    DWORD id = GetCurrentThreadId();
+    for (size_t i=0; i<m_arrMSG.GetCount(); i++)
+    {
+        PostThreadMessage(id, m_arrMSG[i].message,
+                          m_arrMSG[i].wParam, m_arrMSG[i].lParam);
+    }
+
+    m_arrMSG.Clear();
+
+    return true;
+}
+
+
 #else // !wxUSE_GUI