1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        os2/evtloop.cpp 
   3 // Purpose:     implements wxEventLoop for PM 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 // License:     wxWindows license 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "evtloop.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  32     #include "wx/window.h" 
  36 #include "wx/evtloop.h" 
  37 #include "wx/tooltip.h" 
  39 #include "wx/os2/private.h" 
  42     // define the array of QMSG strutures 
  43     WX_DECLARE_OBJARRAY(QMSG
, wxMsgArray
); 
  44     // VS: this is a bit dirty - it duplicates same declaration in app.cpp 
  45     //     (and there's no WX_DEFINE_OBJARRAY for that reason - it is already 
  46     //     defined in app.cpp). 
  51 // ---------------------------------------------------------------------------- 
  53 // ---------------------------------------------------------------------------- 
  55 class WXDLLEXPORT wxEventLoopImpl
 
  59     wxEventLoopImpl() { SetExitCode(0); } 
  62     void ProcessMessage(QMSG 
*msg
); 
  64     // generate an idle message, return TRUE if more idle time requested 
  65     bool SendIdleMessage(); 
  67     // set/get the exit code 
  68     void SetExitCode(int exitcode
) { m_exitcode 
= exitcode
; } 
  69     int GetExitCode() const { return m_exitcode
; } 
  72     // preprocess a message, return TRUE if processed (i.e. no further 
  73     // dispatching required) 
  74     bool PreProcessMessage(QMSG 
*msg
); 
  76     // the exit code of the event loop 
  80 // ============================================================================ 
  81 // wxEventLoopImpl implementation 
  82 // ============================================================================ 
  84 // ---------------------------------------------------------------------------- 
  85 // wxEventLoopImpl message processing 
  86 // ---------------------------------------------------------------------------- 
  88 void wxEventLoopImpl::ProcessMessage(QMSG 
*msg
) 
  90     // give us the chance to preprocess the message first 
  91     if ( !PreProcessMessage(msg
) ) 
  93         // if it wasn't done, dispatch it to the corresponding window 
  94         ::WinDispatchMsg(vHabMain
, msg
); 
  98 bool wxEventLoopImpl::PreProcessMessage(QMSG 
*msg
) 
 100     HWND hWnd 
= msg
->hwnd
; 
 101     wxWindow 
*wndThis 
= wxFindWinFromHandle((WXHWND
)hWnd
); 
 104     // we must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to 
 105     // popup the tooltip bubbles 
 106     if ( wndThis 
&& (msg
->message 
== WM_MOUSEMOVE
) ) 
 108         wxToolTip 
*tt 
= wndThis
->GetToolTip(); 
 111             tt
->RelayEvent((WXMSG 
*)msg
); 
 114 #endif // wxUSE_TOOLTIPS 
 116     // try translations first; find the youngest window with a translation 
 119     for ( wnd 
= wndThis
; wnd
; wnd 
= wnd
->GetParent() ) 
 121         if ( wnd
->OS2TranslateMessage((WXMSG 
*)msg
) ) 
 125     // Anyone for a non-translation message? Try youngest descendants first. 
 126     for ( wnd 
= wndThis
; wnd
; wnd 
= wnd
->GetParent() ) 
 128         if ( wnd
->OS2ProcessMessage((WXMSG 
*)msg
) ) 
 135 // ---------------------------------------------------------------------------- 
 136 // wxEventLoopImpl idle event processing 
 137 // ---------------------------------------------------------------------------- 
 139 bool wxEventLoopImpl::SendIdleMessage() 
 143     return wxTheApp
->ProcessEvent(event
) && event
.MoreRequested(); 
 146 // ============================================================================ 
 147 // wxEventLoop implementation 
 148 // ============================================================================ 
 150 wxEventLoop 
*wxEventLoop::ms_activeLoop 
= NULL
; 
 152 // ---------------------------------------------------------------------------- 
 153 // wxEventLoop running and exiting 
 154 // ---------------------------------------------------------------------------- 
 156 wxEventLoop::~wxEventLoop() 
 158     wxASSERT_MSG( !m_impl
, _T("should have been deleted in Run()") ); 
 161 bool wxEventLoop::IsRunning() const 
 163     return m_impl 
!= NULL
; 
 166 int wxEventLoop::Run() 
 168     // event loops are not recursive, you need to create another loop! 
 169     wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") ); 
 171     m_impl 
= new wxEventLoopImpl
; 
 173     wxEventLoop 
*oldLoop 
= ms_activeLoop
; 
 174     ms_activeLoop 
= this; 
 179         wxMutexGuiLeaveOrEnter(); 
 180 #endif // wxUSE_THREADS 
 182         // generate and process idle events for as long as we don't have 
 183         // anything else to do 
 184         while ( !Pending() && m_impl
->SendIdleMessage() ) 
 187         // a message came or no more idle processing to do, sit in Dispatch() 
 188         // waiting for the next message 
 196     int exitcode 
= m_impl
->GetExitCode(); 
 200     ms_activeLoop 
= oldLoop
; 
 205 void wxEventLoop::Exit(int rc
) 
 207     wxCHECK_RET( IsRunning(), _T("can't call Exit() if not running") ); 
 209     m_impl
->SetExitCode(rc
); 
 211     ::WinPostMsg(NULL
, WM_QUIT
, 0, 0); 
 214 // ---------------------------------------------------------------------------- 
 215 // wxEventLoop message processing dispatching 
 216 // ---------------------------------------------------------------------------- 
 218 bool wxEventLoop::Pending() const 
 221     return ::WinPeekMsg(vHabMain
, &msg
, 0, 0, 0, PM_NOREMOVE
) != 0; 
 224 bool wxEventLoop::Dispatch() 
 226     wxCHECK_MSG( IsRunning(), FALSE
, _T("can't call Dispatch() if not running") ); 
 229     BOOL rc 
= ::WinGetMsg(vHabMain
, &msg
, (HWND
) NULL
, 0, 0); 
 239         // should never happen, but let's test for it nevertheless 
 240         wxLogLastError(wxT("GetMessage")); 
 242         // still break from the loop 
 247     wxASSERT_MSG( wxThread::IsMain(), 
 248                   wxT("only the main thread can process Windows messages") ); 
 250     static bool s_hadGuiLock 
= TRUE
; 
 251     static wxMsgArray s_aSavedMessages
; 
 253     // if a secondary thread owning the mutex is doing GUI calls, save all 
 254     // messages for later processing - we can't process them right now because 
 255     // it will lead to recursive library calls (and we're not reentrant) 
 256     if ( !wxGuiOwnedByMainThread() ) 
 258         s_hadGuiLock 
= FALSE
; 
 260         // leave out WM_COMMAND messages: too dangerous, sometimes 
 261         // the message will be processed twice 
 262         if ( !wxIsWaitingForThread() || msg
.message 
!= WM_COMMAND 
) 
 264             s_aSavedMessages
.Add(msg
); 
 271         // have we just regained the GUI lock? if so, post all of the saved 
 274         // FIXME of course, it's not _exactly_ the same as processing the 
 275         //       messages normally - expect some things to break... 
 280             size_t count 
= s_aSavedMessages
.Count(); 
 281             for ( size_t n 
= 0; n 
< count
; n
++ ) 
 283                 MSG
& msg 
= s_aSavedMessages
[n
]; 
 284                 m_impl
->ProcessMessage(&msg
); 
 287             s_aSavedMessages
.Empty(); 
 290 #endif // wxUSE_THREADS 
 292     m_impl
->ProcessMessage(&msg
);