X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5109ae5d178fb4025c6b92bb2f840c07dae99a82..5767e836997b965b9d936f1d65244bb886c39025:/src/common/appcmn.cpp?ds=sidebyside diff --git a/src/common/appcmn.cpp b/src/common/appcmn.cpp index 8fa4b91bd4..4b5a93d453 100644 --- a/src/common/appcmn.cpp +++ b/src/common/appcmn.cpp @@ -17,7 +17,7 @@ // headers // --------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "appbase.h" #endif @@ -40,11 +40,14 @@ #endif #include "wx/apptrait.h" +#include "wx/cmdline.h" +#include "wx/evtloop.h" #include "wx/msgout.h" #include "wx/thread.h" #include "wx/utils.h" +#include "wx/ptr_scpd.h" -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__PALMOS__) #include "wx/msw/private.h" // includes windows.h for LOGFONT #endif @@ -52,6 +55,18 @@ #include "wx/fontmap.h" #endif // wxUSE_FONTMAP +// DLL options compatibility check: +#include "wx/build.h" +WX_CHECK_BUILD_OPTIONS("wxCore") + + +// ---------------------------------------------------------------------------- +// wxEventLoopPtr +// ---------------------------------------------------------------------------- + +// this defines wxEventLoopPtr +wxDEFINE_TIED_SCOPED_PTR_TYPE(wxEventLoop); + // ============================================================================ // wxAppBase implementation // ============================================================================ @@ -63,8 +78,12 @@ wxAppBase::wxAppBase() { m_topWindow = (wxWindow *)NULL; - m_useBestVisual = FALSE; - m_isActive = TRUE; + m_useBestVisual = false; + m_isActive = true; + +#if wxUSE_EVTLOOP_IN_APP + m_mainLoop = NULL; +#endif // wxUSE_EVTLOOP_IN_APP // We don't want to exit the app if the user code shows a dialog from its // OnInit() -- but this is what would happen if we set m_exitOnFrameDelete @@ -72,10 +91,10 @@ wxAppBase::wxAppBase() // OTOH, if we set it to No initially we'll have to overwrite it with Yes // when we enter our OnRun() because we do want the default behaviour from // then on. But this would be a problem if the user code calls - // SetExitOnFrameDelete(FALSE) from OnInit(). + // SetExitOnFrameDelete(false) from OnInit(). // // So we use the special "Later" value which is such that - // GetExitOnFrameDelete() returns FALSE for it but which we know we can + // GetExitOnFrameDelete() returns false for it but which we know we can // safely (i.e. without losing the effect of the users SetExitOnFrameDelete // call) overwrite in OnRun() m_exitOnFrameDelete = Later; @@ -109,9 +128,19 @@ wxAppBase::~wxAppBase() void wxAppBase::CleanUp() { - // one last chance for pending objects to be cleaned up + // clean up all the pending objects DeletePendingObjects(); + // and any remaining TLWs (they remove themselves from wxTopLevelWindows + // when destroyed, so iterate until none are left) + while ( !wxTopLevelWindows.empty() ) + { + // do not use Destroy() here as it only puts the TLW in pending list + // but we want to delete them now + delete wxTopLevelWindows.GetFirst()->GetData(); + } + + // undo everything we did in Initialize() above wxBitmap::CleanUpHandlers(); wxDeleteStockObjects(); @@ -121,20 +150,169 @@ void wxAppBase::CleanUp() delete wxTheColourDatabase; wxTheColourDatabase = NULL; -#if wxUSE_THREADS delete wxPendingEvents; wxPendingEvents = NULL; +#if wxUSE_THREADS delete wxPendingEventsLocker; wxPendingEventsLocker = NULL; -#if wxUSE_VALIDATORS - // If we don't do the following, we get an apparent memory leak. - ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker(); -#endif // wxUSE_VALIDATORS + #if wxUSE_VALIDATORS + // If we don't do the following, we get an apparent memory leak. + ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker(); + #endif // wxUSE_VALIDATORS #endif // wxUSE_THREADS } +#if wxUSE_CMDLINE_PARSER + +// ---------------------------------------------------------------------------- +// GUI-specific command line options handling +// ---------------------------------------------------------------------------- + +#define OPTION_THEME _T("theme") +#define OPTION_MODE _T("mode") + +void wxAppBase::OnInitCmdLine(wxCmdLineParser& parser) +{ + // first add the standard non GUI options + wxAppConsole::OnInitCmdLine(parser); + + // the standard command line options + static const wxCmdLineEntryDesc cmdLineGUIDesc[] = + { +#ifdef __WXUNIVERSAL__ + { + wxCMD_LINE_OPTION, + _T(""), + OPTION_THEME, + gettext_noop("specify the theme to use"), + wxCMD_LINE_VAL_STRING, + 0x0 + }, +#endif // __WXUNIVERSAL__ + +#if defined(__WXMGL__) + // VS: this is not specific to wxMGL, all fullscreen (framebuffer) ports + // should provide this option. That's why it is in common/appcmn.cpp + // and not mgl/app.cpp + { + wxCMD_LINE_OPTION, + _T(""), + OPTION_MODE, + gettext_noop("specify display mode to use (e.g. 640x480-16)"), + wxCMD_LINE_VAL_STRING, + 0x0 + }, +#endif // __WXMGL__ + + // terminator + { + wxCMD_LINE_NONE, + _T(""), + _T(""), + _T(""), + wxCMD_LINE_VAL_NONE, + 0x0 + } + }; + + parser.SetDesc(cmdLineGUIDesc); +} + +bool wxAppBase::OnCmdLineParsed(wxCmdLineParser& parser) +{ +#ifdef __WXUNIVERSAL__ + wxString themeName; + if ( parser.Found(OPTION_THEME, &themeName) ) + { + wxTheme *theme = wxTheme::Create(themeName); + if ( !theme ) + { + wxLogError(_("Unsupported theme '%s'."), themeName.c_str()); + return false; + } + + // Delete the defaultly created theme and set the new theme. + delete wxTheme::Get(); + wxTheme::Set(theme); + } +#endif // __WXUNIVERSAL__ + +#if defined(__WXMGL__) + wxString modeDesc; + if ( parser.Found(OPTION_MODE, &modeDesc) ) + { + unsigned w, h, bpp; + if ( wxSscanf(modeDesc.c_str(), _T("%ux%u-%u"), &w, &h, &bpp) != 3 ) + { + wxLogError(_("Invalid display mode specification '%s'."), modeDesc.c_str()); + return false; + } + + if ( !SetDisplayMode(wxVideoMode(w, h, bpp)) ) + return false; + } +#endif // __WXMGL__ + + return wxAppConsole::OnCmdLineParsed(parser); +} + +#endif // wxUSE_CMDLINE_PARSER + +// ---------------------------------------------------------------------------- +// main event loop implementation +// ---------------------------------------------------------------------------- + +int wxAppBase::MainLoop() +{ +#if wxUSE_EVTLOOP_IN_APP + wxEventLoopTiedPtr mainLoop(&m_mainLoop, new wxEventLoop); + + return m_mainLoop->Run(); +#else // !wxUSE_EVTLOOP_IN_APP + return 0; +#endif // wxUSE_EVTLOOP_IN_APP/!wxUSE_EVTLOOP_IN_APP +} + +void wxAppBase::ExitMainLoop() +{ +#if wxUSE_EVTLOOP_IN_APP + // we should exit from the main event loop, not just any currently active + // (e.g. modal dialog) event loop + if ( m_mainLoop && m_mainLoop->IsRunning() ) + { + m_mainLoop->Exit(0); + } +#endif // wxUSE_EVTLOOP_IN_APP +} + +bool wxAppBase::Pending() +{ +#if wxUSE_EVTLOOP_IN_APP + // use the currently active message loop here, not m_mainLoop, because if + // we're showing a modal dialog (with its own event loop) currently the + // main event loop is not running anyhow + wxEventLoop * const loop = wxEventLoop::GetActive(); + + return loop && loop->Pending(); +#else // wxUSE_EVTLOOP_IN_APP + return false; +#endif // wxUSE_EVTLOOP_IN_APP/!wxUSE_EVTLOOP_IN_APP +} + +bool wxAppBase::Dispatch() +{ +#if wxUSE_EVTLOOP_IN_APP + // see comment in Pending() + wxEventLoop * const loop = wxEventLoop::GetActive(); + + return loop && loop->Dispatch(); +#else // wxUSE_EVTLOOP_IN_APP + return true; +#endif // wxUSE_EVTLOOP_IN_APP/!wxUSE_EVTLOOP_IN_APP +} + // ---------------------------------------------------------------------------- // OnXXX() hooks // ---------------------------------------------------------------------------- @@ -143,10 +321,10 @@ bool wxAppBase::OnInitGui() { #ifdef __WXUNIVERSAL__ if ( !wxTheme::Get() && !wxTheme::CreateDefault() ) - return FALSE; + return false; #endif // __WXUNIVERSAL__ - return TRUE; + return true; } int wxAppBase::OnRun() @@ -162,6 +340,15 @@ int wxAppBase::OnRun() return MainLoop(); } +int wxAppBase::OnExit() +{ +#ifdef __WXUNIVERSAL__ + delete wxTheme::Set(NULL); +#endif // __WXUNIVERSAL__ + + return wxAppConsole::OnExit(); +} + void wxAppBase::Exit() { ExitMainLoop(); @@ -207,71 +394,51 @@ void wxAppBase::DeletePendingObjects() } } -// Returns TRUE if more time is needed. +// Returns true if more time is needed. bool wxAppBase::ProcessIdle() { wxIdleEvent event; - bool needMore = FALSE; + bool needMore = false; wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst(); - node = wxTopLevelWindows.GetFirst(); while (node) { wxWindow* win = node->GetData(); if (SendIdleEvents(win, event)) - needMore = TRUE; + needMore = true; node = node->GetNext(); } event.SetEventObject(this); (void) ProcessEvent(event); if (event.MoreRequested()) - needMore = TRUE; + needMore = true; wxUpdateUIEvent::ResetUpdateTime(); - - return needMore; -} - -#if 0 -// Send idle event to all top-level windows -bool wxAppBase::SendIdleEvents() -{ - bool needMore = FALSE; - - wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst(); - while (node) - { - wxWindow* win = node->GetData(); - if (SendIdleEvents(win)) - needMore = TRUE; - node = node->GetNext(); - } return needMore; } -#endif // Send idle event to window and all subwindows bool wxAppBase::SendIdleEvents(wxWindow* win, wxIdleEvent& event) { - bool needMore = FALSE; - + bool needMore = false; + win->OnInternalIdle(); + if (wxIdleEvent::CanSend(win)) { event.SetEventObject(win); win->GetEventHandler()->ProcessEvent(event); if (event.MoreRequested()) - needMore = TRUE; + needMore = true; } - wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst(); while ( node ) { - wxWindow *win = node->GetData(); - if (SendIdleEvents(win, event)) - needMore = TRUE; + wxWindow *child = node->GetData(); + if (SendIdleEvents(child, event)) + needMore = true; node = node->GetNext(); } @@ -279,6 +446,26 @@ bool wxAppBase::SendIdleEvents(wxWindow* win, wxIdleEvent& event) return needMore; } +void wxAppBase::OnIdle(wxIdleEvent& WXUNUSED(event)) +{ + // If there are pending events, we must process them: pending events + // are either events to the threads other than main or events posted + // with wxPostEvent() functions + // GRG: I have moved this here so that all pending events are processed + // before starting to delete any objects. This behaves better (in + // particular, wrt wxPostEvent) and is coherent with wxGTK's current + // behaviour. Changed Feb/2000 before 2.1.14 + ProcessPendingEvents(); + + // 'Garbage' collection of windows deleted with Close(). + DeletePendingObjects(); + +#if wxUSE_LOG + // flush the logged messages if any + wxLog::FlushActive(); +#endif // wxUSE_LOG + +} // ---------------------------------------------------------------------------- // wxGUIAppTraitsBase @@ -288,7 +475,12 @@ bool wxAppBase::SendIdleEvents(wxWindow* win, wxIdleEvent& event) wxLog *wxGUIAppTraitsBase::CreateLogTarget() { +#if wxUSE_LOGGUI return new wxLogGui; +#else + // wem ust have something! + return new wxLogStderr; +#endif } #endif // wxUSE_LOG @@ -321,6 +513,12 @@ wxFontMapper *wxGUIAppTraitsBase::CreateFontMapper() #endif // wxUSE_FONTMAP +wxRendererNative *wxGUIAppTraitsBase::CreateRenderer() +{ + // use the default native renderer by default + return NULL; +} + #ifdef __WXDEBUG__ bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg) @@ -338,7 +536,7 @@ bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg) wxT("You can also choose [Cancel] to suppress ") wxT("further warnings."); - switch ( wxMessageBox(msgDlg, wxT("wxWindows Debug Alert"), + switch ( wxMessageBox(msgDlg, wxT("wxWidgets Debug Alert"), wxYES_NO | wxCANCEL | wxICON_STOP ) ) { case wxYES: @@ -380,3 +578,35 @@ void wxGUIAppTraitsBase::RemoveFromPendingDelete(wxObject *object) wxPendingDelete.DeleteObject(object); } +#if wxUSE_SOCKETS + +#if defined(__UNIX__) || defined(__DARWIN__) || defined(__OS2__) + #include "wx/unix/gsockunx.h" +#elif defined(__WINDOWS__) + #include "wx/msw/gsockmsw.h" +#elif defined(__WXMAC__) + #include + #define OTUNIXERRORS 1 + #include + #include + #include + + #include "wx/mac/gsockmac.h" +#else + #error "Must include correct GSocket header here" +#endif + +GSocketGUIFunctionsTable* wxGUIAppTraitsBase::GetSocketGUIFunctionsTable() +{ +#if defined(__WXMAC__) && !defined(__DARWIN__) + // NB: wxMac CFM does not have any GUI-specific functions in gsocket.c and + // so it doesn't need this table at all + return NULL; +#else // !__WXMAC__ || __DARWIN__ + static GSocketGUIFunctionsTableConcrete table; + return &table; +#endif // !__WXMAC__ || __DARWIN__ +} + +#endif +