1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        common/appcmn.cpp 
   3 // Purpose:     wxAppConsole and wxAppBase methods common to all platforms 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) Vadim Zeitlin 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // --------------------------------------------------------------------------- 
  18 // --------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "appbase.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  27 #if defined(__BORLANDC__) 
  33     #include "wx/bitmap.h" 
  37     #include "wx/msgdlg.h" 
  38     #include "wx/bitmap.h" 
  39     #include "wx/confbase.h" 
  42 #include "wx/apptrait.h" 
  43 #include "wx/cmdline.h" 
  44 #include "wx/evtloop.h" 
  45 #include "wx/msgout.h" 
  46 #include "wx/thread.h" 
  48 #include "wx/ptr_scpd.h" 
  50 #if defined(__WXMSW__) 
  51   #include  "wx/msw/private.h"  // includes windows.h for LOGFONT 
  55     #include "wx/fontmap.h" 
  56 #endif // wxUSE_FONTMAP 
  58 // DLL options compatibility check: 
  60 WX_CHECK_BUILD_OPTIONS("wxCore") 
  63 // ---------------------------------------------------------------------------- 
  65 // ---------------------------------------------------------------------------- 
  67 // this defines wxEventLoopPtr 
  68 wxDEFINE_SCOPED_PTR_TYPE(wxEventLoop
); 
  70 // but we need a smart pointer tied to wxAppBase::m_mainLoop, so we define 
  71 // another helper class 
  72 class wxTiedEventLoopPtr 
: public wxEventLoopPtr
 
  75     wxTiedEventLoopPtr(wxEventLoop 
**ppEvtLoop
, wxEventLoop 
*pLoop
) 
  76         : wxEventLoopPtr(*ppEvtLoop 
= pLoop
), m_ppEvtLoop(ppEvtLoop
) 
  80     ~wxTiedEventLoopPtr() { *m_ppEvtLoop 
= NULL
; } 
  83     wxEventLoop 
**m_ppEvtLoop
; 
  86 // ============================================================================ 
  87 // wxAppBase implementation 
  88 // ============================================================================ 
  90 // ---------------------------------------------------------------------------- 
  92 // ---------------------------------------------------------------------------- 
  94 wxAppBase::wxAppBase() 
  96     m_topWindow 
= (wxWindow 
*)NULL
; 
  97     m_useBestVisual 
= FALSE
; 
 102     // We don't want to exit the app if the user code shows a dialog from its 
 103     // OnInit() -- but this is what would happen if we set m_exitOnFrameDelete 
 104     // to Yes initially as this dialog would be the last top level window. 
 105     // OTOH, if we set it to No initially we'll have to overwrite it with Yes 
 106     // when we enter our OnRun() because we do want the default behaviour from 
 107     // then on. But this would be a problem if the user code calls 
 108     // SetExitOnFrameDelete(FALSE) from OnInit(). 
 110     // So we use the special "Later" value which is such that 
 111     // GetExitOnFrameDelete() returns FALSE for it but which we know we can 
 112     // safely (i.e. without losing the effect of the users SetExitOnFrameDelete 
 113     // call) overwrite in OnRun() 
 114     m_exitOnFrameDelete 
= Later
; 
 117 bool wxAppBase::Initialize(int& argc
, wxChar 
**argv
) 
 119     if ( !wxAppConsole::Initialize(argc
, argv
) ) 
 123     wxPendingEventsLocker 
= new wxCriticalSection
; 
 126     wxInitializeStockLists(); 
 127     wxInitializeStockObjects(); 
 129     wxBitmap::InitStandardHandlers(); 
 134 // ---------------------------------------------------------------------------- 
 136 // ---------------------------------------------------------------------------- 
 138 wxAppBase::~wxAppBase() 
 140     // this destructor is required for Darwin 
 143 void wxAppBase::CleanUp() 
 145     // one last chance for pending objects to be cleaned up 
 146     DeletePendingObjects(); 
 148     wxBitmap::CleanUpHandlers(); 
 150     wxDeleteStockObjects(); 
 152     wxDeleteStockLists(); 
 154     delete wxTheColourDatabase
; 
 155     wxTheColourDatabase 
= NULL
; 
 158     delete wxPendingEvents
; 
 159     wxPendingEvents 
= NULL
; 
 161     delete wxPendingEventsLocker
; 
 162     wxPendingEventsLocker 
= NULL
; 
 165         // If we don't do the following, we get an apparent memory leak. 
 166         ((wxEvtHandler
&) wxDefaultValidator
).ClearEventLocker(); 
 167     #endif // wxUSE_VALIDATORS 
 168 #endif // wxUSE_THREADS 
 171 #if wxUSE_CMDLINE_PARSER 
 173 // ---------------------------------------------------------------------------- 
 174 // GUI-specific command line options handling 
 175 // ---------------------------------------------------------------------------- 
 177 #define OPTION_THEME   _T("theme") 
 178 #define OPTION_MODE    _T("mode") 
 180 void wxAppBase::OnInitCmdLine(wxCmdLineParser
& parser
) 
 182     // first add the standard non GUI options 
 183     wxAppConsole::OnInitCmdLine(parser
); 
 185     // the standard command line options 
 186     static const wxCmdLineEntryDesc cmdLineGUIDesc
[] = 
 188 #ifdef __WXUNIVERSAL__ 
 193             gettext_noop("specify the theme to use"), 
 194             wxCMD_LINE_VAL_STRING
, 
 197 #endif // __WXUNIVERSAL__ 
 199 #if defined(__WXMGL__) 
 200         // VS: this is not specific to wxMGL, all fullscreen (framebuffer) ports 
 201         //     should provide this option. That's why it is in common/appcmn.cpp 
 202         //     and not mgl/app.cpp 
 207             gettext_noop("specify display mode to use (e.g. 640x480-16)"), 
 208             wxCMD_LINE_VAL_STRING
, 
 224     parser
.SetDesc(cmdLineGUIDesc
); 
 227 bool wxAppBase::OnCmdLineParsed(wxCmdLineParser
& parser
) 
 229 #ifdef __WXUNIVERSAL__ 
 231     if ( parser
.Found(OPTION_THEME
, &themeName
) ) 
 233         wxTheme 
*theme 
= wxTheme::Create(themeName
); 
 236             wxLogError(_("Unsupported theme '%s'."), themeName
.c_str()); 
 240         // Delete the defaultly created theme and set the new theme. 
 241         delete wxTheme::Get(); 
 244 #endif // __WXUNIVERSAL__ 
 246 #if defined(__WXMGL__) 
 248     if ( parser
.Found(OPTION_MODE
, &modeDesc
) ) 
 251         if ( wxSscanf(modeDesc
.c_str(), _T("%ux%u-%u"), &w
, &h
, &bpp
) != 3 ) 
 253             wxLogError(_("Invalid display mode specification '%s'."), modeDesc
.c_str()); 
 257         if ( !SetDisplayMode(wxDisplayModeInfo(w
, h
, bpp
)) ) 
 262     return wxAppConsole::OnCmdLineParsed(parser
); 
 265 #endif // wxUSE_CMDLINE_PARSER 
 267 // ---------------------------------------------------------------------------- 
 268 // main event loop implementation 
 269 // ---------------------------------------------------------------------------- 
 271 int wxAppBase::MainLoop() 
 273     wxTiedEventLoopPtr 
mainLoop(&m_mainLoop
, new wxEventLoop
); 
 275     return m_mainLoop
->Run(); 
 278 void wxAppBase::ExitMainLoop() 
 280     // we should exit from the main event loop, not just any currently active 
 281     // (e.g. modal dialog) event loop 
 288 bool wxAppBase::Pending() 
 290     // use the currently active message loop here, not m_mainLoop, because if 
 291     // we're showing a modal dialog (with its own event loop) currently the 
 292     // main event loop is not running anyhow 
 293     wxEventLoop 
* const loop 
= wxEventLoop::GetActive(); 
 295     return loop 
&& loop
->Pending(); 
 298 bool wxAppBase::Dispatch() 
 300     // see comment in Pending() 
 301     wxEventLoop 
* const loop 
= wxEventLoop::GetActive(); 
 303     return loop 
? loop
->Dispatch() : true; 
 306 // ---------------------------------------------------------------------------- 
 308 // ---------------------------------------------------------------------------- 
 310 bool wxAppBase::OnInitGui() 
 312 #ifdef __WXUNIVERSAL__ 
 313     if ( !wxTheme::Get() && !wxTheme::CreateDefault() ) 
 315 #endif // __WXUNIVERSAL__ 
 320 int wxAppBase::OnRun() 
 322     // see the comment in ctor: if the initial value hasn't been changed, use 
 323     // the default Yes from now on 
 324     if ( m_exitOnFrameDelete 
== Later 
) 
 326         m_exitOnFrameDelete 
= Yes
; 
 328     //else: it has been changed, assume the user knows what he is doing 
 333 int wxAppBase::OnExit() 
 335 #ifdef __WXUNIVERSAL__ 
 336     delete wxTheme::Set(NULL
); 
 337 #endif // __WXUNIVERSAL__ 
 339     return wxAppConsole::OnExit(); 
 342 void wxAppBase::Exit() 
 347 wxAppTraits 
*wxAppBase::CreateTraits() 
 349     return new wxGUIAppTraits
; 
 352 // ---------------------------------------------------------------------------- 
 354 // ---------------------------------------------------------------------------- 
 356 void wxAppBase::SetActive(bool active
, wxWindow 
* WXUNUSED(lastFocus
)) 
 358     if ( active 
== m_isActive 
) 
 363     wxActivateEvent 
event(wxEVT_ACTIVATE_APP
, active
); 
 364     event
.SetEventObject(this); 
 366     (void)ProcessEvent(event
); 
 369 void wxAppBase::DeletePendingObjects() 
 371     wxList::compatibility_iterator node 
= wxPendingDelete
.GetFirst(); 
 374         wxObject 
*obj 
= node
->GetData(); 
 378         if (wxPendingDelete
.Member(obj
)) 
 379             wxPendingDelete
.Erase(node
); 
 381         // Deleting one object may have deleted other pending 
 382         // objects, so start from beginning of list again. 
 383         node 
= wxPendingDelete
.GetFirst(); 
 387 // Returns TRUE if more time is needed. 
 388 bool wxAppBase::ProcessIdle() 
 391     bool needMore 
= FALSE
; 
 392     wxWindowList::compatibility_iterator node 
= wxTopLevelWindows
.GetFirst(); 
 395         wxWindow
* win 
= node
->GetData(); 
 396         if (SendIdleEvents(win
, event
)) 
 398         node 
= node
->GetNext(); 
 401     event
.SetEventObject(this); 
 402     (void) ProcessEvent(event
); 
 403     if (event
.MoreRequested()) 
 406     wxUpdateUIEvent::ResetUpdateTime(); 
 411 // Send idle event to window and all subwindows 
 412 bool wxAppBase::SendIdleEvents(wxWindow
* win
, wxIdleEvent
& event
) 
 414     bool needMore 
= FALSE
; 
 416     win
->OnInternalIdle(); 
 418     if (wxIdleEvent::CanSend(win
)) 
 420         event
.SetEventObject(win
); 
 421         win
->GetEventHandler()->ProcessEvent(event
); 
 423         if (event
.MoreRequested()) 
 426     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
 429         wxWindow 
*child 
= node
->GetData(); 
 430         if (SendIdleEvents(child
, event
)) 
 433         node 
= node
->GetNext(); 
 439 void wxAppBase::OnIdle(wxIdleEvent
& WXUNUSED(event
)) 
 441     // If there are pending events, we must process them: pending events 
 442     // are either events to the threads other than main or events posted 
 443     // with wxPostEvent() functions 
 444     // GRG: I have moved this here so that all pending events are processed 
 445     //   before starting to delete any objects. This behaves better (in 
 446     //   particular, wrt wxPostEvent) and is coherent with wxGTK's current 
 447     //   behaviour. Changed Feb/2000 before 2.1.14 
 448     ProcessPendingEvents(); 
 450     // 'Garbage' collection of windows deleted with Close(). 
 451     DeletePendingObjects(); 
 454     // flush the logged messages if any 
 455     wxLog::FlushActive(); 
 460 // ---------------------------------------------------------------------------- 
 461 // wxGUIAppTraitsBase 
 462 // ---------------------------------------------------------------------------- 
 466 wxLog 
*wxGUIAppTraitsBase::CreateLogTarget() 
 473 wxMessageOutput 
*wxGUIAppTraitsBase::CreateMessageOutput() 
 475     // The standard way of printing help on command line arguments (app --help) 
 476     // is (according to common practice): 
 477     //     - console apps: to stderr (on any platform) 
 478     //     - GUI apps: stderr on Unix platforms (!) 
 479     //                 message box under Windows and others 
 481     return new wxMessageOutputStderr
; 
 483     // wxMessageOutputMessageBox doesn't work under Motif 
 485         return new wxMessageOutputLog
; 
 487         return new wxMessageOutputMessageBox
; 
 489 #endif // __UNIX__/!__UNIX__ 
 494 wxFontMapper 
*wxGUIAppTraitsBase::CreateFontMapper() 
 496     return new wxFontMapper
; 
 499 #endif // wxUSE_FONTMAP 
 501 wxRendererNative 
*wxGUIAppTraitsBase::CreateRenderer() 
 503     // use the default native renderer by default 
 509 bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString
& msg
) 
 511     // under MSW we prefer to use the base class version using ::MessageBox() 
 512     // even if wxMessageBox() is available because it has less chances to 
 513     // double fault our app than our wxMessageBox() 
 514 #if defined(__WXMSW__) || !wxUSE_MSGDLG 
 515     return wxAppTraitsBase::ShowAssertDialog(msg
); 
 516 #else // wxUSE_MSGDLG 
 517     // this message is intentionally not translated -- it is for 
 519     wxString 
msgDlg(msg
); 
 520     msgDlg 
+= wxT("\nDo you want to stop the program?\n") 
 521               wxT("You can also choose [Cancel] to suppress ") 
 522               wxT("further warnings."); 
 524     switch ( wxMessageBox(msgDlg
, wxT("wxWindows Debug Alert"), 
 525                           wxYES_NO 
| wxCANCEL 
| wxICON_STOP 
) ) 
 535         //case wxNO: nothing to do 
 539 #endif // !wxUSE_MSGDLG/wxUSE_MSGDLG 
 542 #endif // __WXDEBUG__ 
 544 bool wxGUIAppTraitsBase::HasStderr() 
 546     // we consider that under Unix stderr always goes somewhere, even if the 
 547     // user doesn't always see it under GUI desktops 
 555 void wxGUIAppTraitsBase::ScheduleForDestroy(wxObject 
*object
) 
 557     if ( !wxPendingDelete
.Member(object
) ) 
 558         wxPendingDelete
.Append(object
); 
 561 void wxGUIAppTraitsBase::RemoveFromPendingDelete(wxObject 
*object
) 
 563     wxPendingDelete
.DeleteObject(object
); 
 568 #if defined(__UNIX__) || defined(__DARWIN__) || defined(__OS2__) 
 569     #include "wx/unix/gsockunx.h" 
 570 #elif defined(__WINDOWS__) 
 571     #include "wx/msw/gsockmsw.h" 
 572 #elif defined(__WXMAC__) 
 573   #include <MacHeaders.c> 
 574   #define OTUNIXERRORS 1 
 575   #include <OpenTransport.h> 
 576   #include <OpenTransportProviders.h> 
 577   #include <OpenTptInternet.h> 
 579   #include "wx/mac/gsockmac.h" 
 581     #error "Must include correct GSocket header here" 
 584 GSocketGUIFunctionsTable
* wxGUIAppTraitsBase::GetSocketGUIFunctionsTable() 
 587     // NB: wxMac does not have any GUI-specific functions in gsocket.c and 
 588     //     so it doesn't need this table at all 
 591     static GSocketGUIFunctionsTable table 
= 
 594         _GSocket_GUI_Cleanup
, 
 595         _GSocket_GUI_Init_Socket
, 
 596         _GSocket_GUI_Destroy_Socket
, 
 598         _GSocket_Install_Callback
, 
 599         _GSocket_Uninstall_Callback
, 
 601         _GSocket_Enable_Events
, 
 602         _GSocket_Disable_Events
 
 605 #endif // __WXMAC__/!__WXMAC__