X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6244848856584171db8cd74a7ff227250e46cc54..12a44087e448071f9f108208a0a88e908d543d44:/src/msw/app.cpp diff --git a/src/msw/app.cpp b/src/msw/app.cpp index aa041848e8..e795e42453 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -39,6 +39,17 @@ #include "wx/log.h" #include "wx/module.h" +#if wxUSE_THREADS + #include "wx/thread.h" + + // define the array of MSG strutures + WX_DECLARE_OBJARRAY(MSG, wxMsgArray); + + #include "wx/arrimpl.cpp" + + WX_DEFINE_OBJARRAY(wxMsgArray); +#endif // wxUSE_THREADS + #if wxUSE_WX_RESOURCES #include "wx/resource.h" #endif @@ -47,7 +58,7 @@ // if you don't do the same for the Ole calls further down. // Also, OLE is used not just for drag and drop (it's used by automatn.cpp). // #if wxUSE_DRAG_AND_DROP -#ifndef __GNUWIN32__ +#if !defined(__GNUWIN32__) && !defined(__SC__) #include #endif // #endif @@ -89,7 +100,7 @@ extern char *wxBuffer; extern char *wxOsVersion; extern wxList *wxWinHandleList; -extern wxList wxPendingDelete; +extern wxList WXDLLEXPORT wxPendingDelete; extern void wxSetKeyboardHook(bool doIt); extern wxCursor *g_globalCursor; @@ -196,7 +207,7 @@ bool wxApp::Initialize() } */ -#ifndef __GNUWIN32__ +#if !defined(__GNUWIN32__) && !defined(__SC__) // we need to initialize OLE library if ( FAILED(::OleInitialize(NULL)) ) wxFatalError(_("Cannot initialize OLE")); @@ -513,7 +524,7 @@ void wxApp::CleanUp() if ( wxDisableButtonBrush ) ::DeleteObject( wxDisableButtonBrush ) ; -#ifndef __GNUWIN32__ +#if !defined(__GNUWIN32__) && !defined(__SC__) ::OleUninitialize(); #endif @@ -557,7 +568,7 @@ int wxEntry(WXHINSTANCE hInstance, int nCmdShow, bool enterLoop) { -#ifndef __WXDEBUG__ // take everything into a try-except block in release build +#if !defined(__WXDEBUG__) && !defined(__BORLANDC__) && !defined(__WATCOMC__) // take everything into a try-except block in release build try { #endif @@ -627,7 +638,7 @@ int wxEntry(WXHINSTANCE hInstance, wxApp::CleanUp(); return retValue; -#ifndef __WXDEBUG__ // catch exceptions only in release build +#if !defined(__WXDEBUG__) && !defined(__BORLANDC__) && !defined(__WATCOMC__) // catch exceptions only in release build } except ( EXCEPTION_EXECUTE_HANDLER ) { /* @@ -732,24 +743,82 @@ bool wxApp::Initialized() /* * Get and process a message, returning FALSE if WM_QUIT - * received. + * received (and also set the flag telling the app to exit the main loop) * */ bool wxApp::DoMessage() { - if (!::GetMessage(&s_currentMsg, (HWND) NULL, 0, 0)) - { - return FALSE; - } + BOOL rc = ::GetMessage(&s_currentMsg, (HWND) NULL, 0, 0); + if ( rc == 0 ) + { + // got WM_QUIT + m_keepGoing = FALSE; + + return FALSE; + } + else if ( rc == -1 ) + { + // should never happen, but let's test for it nevertheless + wxLogLastError("GetMessage"); + } + else + { +#if wxUSE_THREADS + wxASSERT_MSG( wxThread::IsMain(), + "only the main thread can process Windows messages" ); - // Process the message - if (!ProcessMessage((WXMSG *)&s_currentMsg)) - { - ::TranslateMessage(&s_currentMsg); - wxApp::sm_lastMessageTime = s_currentMsg.time; /* MATTHEW: timeStamp impl. */ - ::DispatchMessage(&s_currentMsg); - } - return TRUE; + static bool s_hadGuiLock = TRUE; + static wxMsgArray s_aSavedMessages; + + // if a secondary thread owns is doing GUI calls, save all messages for + // later processing - we can't process them right now because it will + // lead to recursive library calls (and we're not reentrant) + if ( !wxGuiOwnedByMainThread() ) + { + s_hadGuiLock = FALSE; + + s_aSavedMessages.Add(s_currentMsg); + + return TRUE; + } + else + { + // have we just regained the GUI lock? if so, post all of the saved + // messages + // + // FIXME of course, it's not _exactly_ the same as processing the + // messages normally - expect some things to break... + if ( !s_hadGuiLock ) + { + s_hadGuiLock = TRUE; + + size_t count = s_aSavedMessages.Count(); + for ( size_t n = 0; n < count; n++ ) + { + MSG& msg = s_aSavedMessages[n]; + + if ( !ProcessMessage((WXMSG *)&msg) ) + { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + } + + s_aSavedMessages.Empty(); + } + } +#endif // wxUSE_THREADS + + // Process the message + if ( !ProcessMessage((WXMSG *)&s_currentMsg) ) + { + ::TranslateMessage(&s_currentMsg); + wxApp::sm_lastMessageTime = s_currentMsg.time; /* MATTHEW: timeStamp impl. */ + ::DispatchMessage(&s_currentMsg); + } + } + + return TRUE; } /* @@ -769,12 +838,19 @@ bool wxApp::DoMessage() int wxApp::MainLoop() { m_keepGoing = TRUE; - while (m_keepGoing) + + while ( m_keepGoing ) { - while (!::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) && - ProcessIdle()) {} - if (!DoMessage()) - m_keepGoing = FALSE; + #if wxUSE_THREADS + wxMutexGuiLeaveOrEnter(); + #endif // wxUSE_THREADS + + while ( !::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) && + ProcessIdle() ) + { + } + + DoMessage(); } return s_currentMsg.wParam; @@ -802,8 +878,7 @@ bool wxApp::Pending() void wxApp::Dispatch() { - if (!DoMessage()) - m_keepGoing = FALSE; + DoMessage(); } /* @@ -844,45 +919,47 @@ bool wxApp::ProcessMessage(WXMSG *Msg) void wxApp::OnIdle(wxIdleEvent& event) { - static bool inOnIdle = FALSE; + static bool s_inOnIdle = FALSE; - // Avoid recursion (via ProcessEvent default case) - if (inOnIdle) - return; + // Avoid recursion (via ProcessEvent default case) + if ( s_inOnIdle ) + return; - inOnIdle = TRUE; + s_inOnIdle = TRUE; - // 'Garbage' collection of windows deleted with Close(). - DeletePendingObjects(); + // 'Garbage' collection of windows deleted with Close(). + DeletePendingObjects(); - // flush the logged messages if any - wxLog *pLog = wxLog::GetActiveTarget(); - if ( pLog != NULL && pLog->HasPendingMessages() ) - pLog->Flush(); + // flush the logged messages if any + wxLog *pLog = wxLog::GetActiveTarget(); + if ( pLog != NULL && pLog->HasPendingMessages() ) + pLog->Flush(); - // Send OnIdle events to all windows - bool needMore = SendIdleEvents(); -// bool needMore = FALSE; - - if (needMore) - event.RequestMore(TRUE); + // Send OnIdle events to all windows + if ( SendIdleEvents() ) + { + // SendIdleEvents() returns TRUE if at least one window requested more + // idle events + event.RequestMore(TRUE); + } - inOnIdle = FALSE; + s_inOnIdle = FALSE; } // Send idle event to all top-level windows bool wxApp::SendIdleEvents() { bool needMore = FALSE; - wxNode* node = wxTopLevelWindows.First(); - while (node) - { - wxWindow* win = (wxWindow*) node->Data(); - if (SendIdleEvents(win)) + wxNode* node = wxTopLevelWindows.First(); + while (node) + { + wxWindow* win = (wxWindow*) node->Data(); + if (SendIdleEvents(win)) needMore = TRUE; - node = node->Next(); - } + node = node->Next(); + } + return needMore; } @@ -1017,7 +1094,7 @@ bool wxYield() // if we see a WM_QUIT. (?) while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) && msg.message != WM_QUIT) { - if (!wxTheApp->DoMessage()) + if ( !wxTheApp->DoMessage() ) break; }