1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/evtloopconsole.cpp
3 // Purpose:     wxConsoleEventLoop class for Windows
4 // Author:      Vadim Zeitlin
5 // Modified by:
6 // Created:     01.06.01
7 // Copyright:   (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21 
22 #ifdef __BORLANDC__
23     #pragma hdrstop
24 #endif
25 
26 #ifndef WX_PRECOMP
27     #include "wx/log.h"
28     #include "wx/msw/wrapwin.h"
29 #endif //WX_PRECOMP
30 
31 #include "wx/evtloop.h"
32 
33 // ============================================================================
34 // wxMSWEventLoopBase implementation
35 // ============================================================================
36 
37 // ----------------------------------------------------------------------------
38 // ctor/dtor
39 // ----------------------------------------------------------------------------
40 
wxMSWEventLoopBase()41 wxMSWEventLoopBase::wxMSWEventLoopBase()
42 {
43     m_shouldExit = false;
44     m_exitcode = 0;
45 }
46 
47 // ----------------------------------------------------------------------------
48 // wxEventLoop message processing dispatching
49 // ----------------------------------------------------------------------------
50 
Pending() const51 bool wxMSWEventLoopBase::Pending() const
52 {
53     MSG msg;
54     return ::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE) != 0;
55 }
56 
GetNextMessage(WXMSG * msg)57 bool wxMSWEventLoopBase::GetNextMessage(WXMSG* msg)
58 {
59     const BOOL rc = ::GetMessage(msg, NULL, 0, 0);
60 
61     if ( rc == 0 )
62     {
63         // got WM_QUIT
64         return false;
65     }
66 
67     if ( rc == -1 )
68     {
69         // should never happen, but let's test for it nevertheless
70         wxLogLastError(wxT("GetMessage"));
71 
72         // still break from the loop
73         return false;
74     }
75 
76     return true;
77 }
78 
GetNextMessageTimeout(WXMSG * msg,unsigned long timeout)79 int wxMSWEventLoopBase::GetNextMessageTimeout(WXMSG *msg, unsigned long timeout)
80 {
81     // MsgWaitForMultipleObjects() won't notice any input which was already
82     // examined (e.g. using PeekMessage()) but not yet removed from the queue
83     // so we need to remove any immediately messages manually
84     //
85     // NB: using MsgWaitForMultipleObjectsEx() could simplify the code here but
86     //     it is not available in very old Windows versions
87     if ( !::PeekMessage(msg, 0, 0, 0, PM_REMOVE) )
88     {
89         // we use this function just in order to not block longer than the
90         // given timeout, so we don't pass any handles to it at all
91         DWORD rc = ::MsgWaitForMultipleObjects
92                      (
93                         0, NULL,
94                         FALSE,
95                         timeout,
96                         QS_ALLINPUT
97                      );
98 
99         switch ( rc )
100         {
101             default:
102                 wxLogDebug("unexpected MsgWaitForMultipleObjects() return "
103                            "value %lu", rc);
104                 // fall through
105 
106             case WAIT_TIMEOUT:
107                 return -1;
108 
109             case WAIT_OBJECT_0:
110                 if ( !::PeekMessage(msg, 0, 0, 0, PM_REMOVE) )
111                 {
112                     // somehow it may happen that MsgWaitForMultipleObjects()
113                     // returns true but there are no messages -- just treat it
114                     // the same as timeout then
115                     return -1;
116                 }
117                 break;
118         }
119     }
120 
121     return msg->message != WM_QUIT;
122 }
123 
124 // ============================================================================
125 // wxConsoleEventLoop implementation
126 // ============================================================================
127 
128 #if wxUSE_CONSOLE_EVENTLOOP
129 
WakeUp()130 void wxConsoleEventLoop::WakeUp()
131 {
132 #if wxUSE_THREADS
133     wxWakeUpMainThread();
134 #endif
135 }
136 
ProcessMessage(WXMSG * msg)137 void wxConsoleEventLoop::ProcessMessage(WXMSG *msg)
138 {
139     ::DispatchMessage(msg);
140 }
141 
Dispatch()142 bool wxConsoleEventLoop::Dispatch()
143 {
144     MSG msg;
145     if ( !GetNextMessage(&msg) )
146         return false;
147 
148     ProcessMessage(&msg);
149 
150     return !m_shouldExit;
151 }
152 
DispatchTimeout(unsigned long timeout)153 int wxConsoleEventLoop::DispatchTimeout(unsigned long timeout)
154 {
155     MSG msg;
156     int rc = GetNextMessageTimeout(&msg, timeout);
157     if ( rc != 1 )
158         return rc;
159 
160     ProcessMessage(&msg);
161 
162     return !m_shouldExit;
163 }
164 
165 #endif // wxUSE_CONSOLE_EVENTLOOP
166