1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/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 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  23 #if defined(__BORLANDC__) 
  29     #include "wx/window.h" 
  30     #include "wx/bitmap.h" 
  32     #include "wx/msgdlg.h" 
  33     #include "wx/confbase.h" 
  37 #include "wx/apptrait.h" 
  38 #include "wx/cmdline.h" 
  39 #include "wx/evtloop.h" 
  40 #include "wx/msgout.h" 
  41 #include "wx/thread.h" 
  42 #include "wx/vidmode.h" 
  43 #include "wx/ptr_scpd.h" 
  45 #if defined(__WXMSW__) 
  46     #include  "wx/msw/private.h"  // includes windows.h for LOGFONT 
  50     #include "wx/fontmap.h" 
  51 #endif // wxUSE_FONTMAP 
  53 // DLL options compatibility check: 
  55 WX_CHECK_BUILD_OPTIONS("wxCore") 
  57 WXDLLIMPEXP_DATA_CORE(wxList
) wxPendingDelete
; 
  59 // ---------------------------------------------------------------------------- 
  61 // ---------------------------------------------------------------------------- 
  63 // this defines wxEventLoopPtr 
  64 wxDEFINE_TIED_SCOPED_PTR_TYPE(wxEventLoop
) 
  66 // ============================================================================ 
  67 // wxAppBase implementation 
  68 // ============================================================================ 
  70 // ---------------------------------------------------------------------------- 
  72 // ---------------------------------------------------------------------------- 
  74 wxAppBase::wxAppBase() 
  76     m_topWindow 
= (wxWindow 
*)NULL
; 
  77     m_useBestVisual 
= false; 
  82     // We don't want to exit the app if the user code shows a dialog from its 
  83     // OnInit() -- but this is what would happen if we set m_exitOnFrameDelete 
  84     // to Yes initially as this dialog would be the last top level window. 
  85     // OTOH, if we set it to No initially we'll have to overwrite it with Yes 
  86     // when we enter our OnRun() because we do want the default behaviour from 
  87     // then on. But this would be a problem if the user code calls 
  88     // SetExitOnFrameDelete(false) from OnInit(). 
  90     // So we use the special "Later" value which is such that 
  91     // GetExitOnFrameDelete() returns false for it but which we know we can 
  92     // safely (i.e. without losing the effect of the users SetExitOnFrameDelete 
  93     // call) overwrite in OnRun() 
  94     m_exitOnFrameDelete 
= Later
; 
  97 bool wxAppBase::Initialize(int& argcOrig
, wxChar 
**argvOrig
) 
  99     if ( !wxAppConsole::Initialize(argcOrig
, argvOrig
) ) 
 103     wxPendingEventsLocker 
= new wxCriticalSection
; 
 106     wxInitializeStockLists(); 
 108     wxBitmap::InitStandardHandlers(); 
 113 // ---------------------------------------------------------------------------- 
 115 // ---------------------------------------------------------------------------- 
 117 wxAppBase::~wxAppBase() 
 119     // this destructor is required for Darwin 
 122 void wxAppBase::CleanUp() 
 124     // clean up all the pending objects 
 125     DeletePendingObjects(); 
 127     // and any remaining TLWs (they remove themselves from wxTopLevelWindows 
 128     // when destroyed, so iterate until none are left) 
 129     while ( !wxTopLevelWindows
.empty() ) 
 131         // do not use Destroy() here as it only puts the TLW in pending list 
 132         // but we want to delete them now 
 133         delete wxTopLevelWindows
.GetFirst()->GetData(); 
 136     // undo everything we did in Initialize() above 
 137     wxBitmap::CleanUpHandlers(); 
 139     wxStockGDI::DeleteAll(); 
 141     wxDeleteStockLists(); 
 143     delete wxTheColourDatabase
; 
 144     wxTheColourDatabase 
= NULL
; 
 146     delete wxPendingEvents
; 
 147     wxPendingEvents 
= NULL
; 
 150     delete wxPendingEventsLocker
; 
 151     wxPendingEventsLocker 
= NULL
; 
 154         // If we don't do the following, we get an apparent memory leak. 
 155         ((wxEvtHandler
&) wxDefaultValidator
).ClearEventLocker(); 
 156     #endif // wxUSE_VALIDATORS 
 157 #endif // wxUSE_THREADS 
 160 // ---------------------------------------------------------------------------- 
 162 // ---------------------------------------------------------------------------- 
 164 wxWindow
* wxAppBase::GetTopWindow() const 
 166     wxWindow
* window 
= m_topWindow
; 
 167     if (window 
== NULL 
&& wxTopLevelWindows
.GetCount() > 0) 
 168         window 
= wxTopLevelWindows
.GetFirst()->GetData(); 
 172 wxVideoMode 
wxAppBase::GetDisplayMode() const 
 174     return wxVideoMode(); 
 177 wxLayoutDirection 
wxAppBase::GetLayoutDirection() const 
 180     const wxLocale 
*const locale 
= wxGetLocale(); 
 183         const wxLanguageInfo 
*const 
 184             info 
= wxLocale::GetLanguageInfo(locale
->GetLanguage()); 
 187             return info
->LayoutDirection
; 
 192     return wxLayout_Default
; 
 195 #if wxUSE_CMDLINE_PARSER 
 197 // ---------------------------------------------------------------------------- 
 198 // GUI-specific command line options handling 
 199 // ---------------------------------------------------------------------------- 
 201 #define OPTION_THEME   _T("theme") 
 202 #define OPTION_MODE    _T("mode") 
 204 void wxAppBase::OnInitCmdLine(wxCmdLineParser
& parser
) 
 206     // first add the standard non GUI options 
 207     wxAppConsole::OnInitCmdLine(parser
); 
 209     // the standard command line options 
 210     static const wxCmdLineEntryDesc cmdLineGUIDesc
[] = 
 212 #ifdef __WXUNIVERSAL__ 
 217             gettext_noop("specify the theme to use"), 
 218             wxCMD_LINE_VAL_STRING
, 
 221 #endif // __WXUNIVERSAL__ 
 223 #if defined(__WXMGL__) 
 224         // VS: this is not specific to wxMGL, all fullscreen (framebuffer) ports 
 225         //     should provide this option. That's why it is in common/appcmn.cpp 
 226         //     and not mgl/app.cpp 
 231             gettext_noop("specify display mode to use (e.g. 640x480-16)"), 
 232             wxCMD_LINE_VAL_STRING
, 
 248     parser
.SetDesc(cmdLineGUIDesc
); 
 251 bool wxAppBase::OnCmdLineParsed(wxCmdLineParser
& parser
) 
 253 #ifdef __WXUNIVERSAL__ 
 255     if ( parser
.Found(OPTION_THEME
, &themeName
) ) 
 257         wxTheme 
*theme 
= wxTheme::Create(themeName
); 
 260             wxLogError(_("Unsupported theme '%s'."), themeName
.c_str()); 
 264         // Delete the defaultly created theme and set the new theme. 
 265         delete wxTheme::Get(); 
 268 #endif // __WXUNIVERSAL__ 
 270 #if defined(__WXMGL__) 
 272     if ( parser
.Found(OPTION_MODE
, &modeDesc
) ) 
 275         if ( wxSscanf(modeDesc
.c_str(), _T("%ux%u-%u"), &w
, &h
, &bpp
) != 3 ) 
 277             wxLogError(_("Invalid display mode specification '%s'."), modeDesc
.c_str()); 
 281         if ( !SetDisplayMode(wxVideoMode(w
, h
, bpp
)) ) 
 286     return wxAppConsole::OnCmdLineParsed(parser
); 
 289 #endif // wxUSE_CMDLINE_PARSER 
 291 // ---------------------------------------------------------------------------- 
 292 // main event loop implementation 
 293 // ---------------------------------------------------------------------------- 
 295 int wxAppBase::MainLoop() 
 297     wxEventLoopTiedPtr 
mainLoop(&m_mainLoop
, new wxEventLoop
); 
 299     return m_mainLoop
->Run(); 
 302 void wxAppBase::ExitMainLoop() 
 304     // we should exit from the main event loop, not just any currently active 
 305     // (e.g. modal dialog) event loop 
 306     if ( m_mainLoop 
&& m_mainLoop
->IsRunning() ) 
 312 bool wxAppBase::Pending() 
 314     // use the currently active message loop here, not m_mainLoop, because if 
 315     // we're showing a modal dialog (with its own event loop) currently the 
 316     // main event loop is not running anyhow 
 317     wxEventLoop 
* const loop 
= wxEventLoop::GetActive(); 
 319     return loop 
&& loop
->Pending(); 
 322 bool wxAppBase::Dispatch() 
 324     // see comment in Pending() 
 325     wxEventLoop 
* const loop 
= wxEventLoop::GetActive(); 
 327     return loop 
&& loop
->Dispatch(); 
 330 // ---------------------------------------------------------------------------- 
 332 // ---------------------------------------------------------------------------- 
 334 bool wxAppBase::OnInitGui() 
 336 #ifdef __WXUNIVERSAL__ 
 337     if ( !wxTheme::Get() && !wxTheme::CreateDefault() ) 
 339 #endif // __WXUNIVERSAL__ 
 344 int wxAppBase::OnRun() 
 346     // see the comment in ctor: if the initial value hasn't been changed, use 
 347     // the default Yes from now on 
 348     if ( m_exitOnFrameDelete 
== Later 
) 
 350         m_exitOnFrameDelete 
= Yes
; 
 352     //else: it has been changed, assume the user knows what he is doing 
 357 int wxAppBase::OnExit() 
 359 #ifdef __WXUNIVERSAL__ 
 360     delete wxTheme::Set(NULL
); 
 361 #endif // __WXUNIVERSAL__ 
 363     return wxAppConsole::OnExit(); 
 366 void wxAppBase::Exit() 
 371 wxAppTraits 
*wxAppBase::CreateTraits() 
 373     return new wxGUIAppTraits
; 
 376 // ---------------------------------------------------------------------------- 
 378 // ---------------------------------------------------------------------------- 
 380 void wxAppBase::SetActive(bool active
, wxWindow 
* WXUNUSED(lastFocus
)) 
 382     if ( active 
== m_isActive 
) 
 387     wxActivateEvent 
event(wxEVT_ACTIVATE_APP
, active
); 
 388     event
.SetEventObject(this); 
 390     (void)ProcessEvent(event
); 
 393 // ---------------------------------------------------------------------------- 
 395 // ---------------------------------------------------------------------------- 
 397 void wxAppBase::DeletePendingObjects() 
 399     wxList::compatibility_iterator node 
= wxPendingDelete
.GetFirst(); 
 402         wxObject 
*obj 
= node
->GetData(); 
 404         // remove it from the list first so that if we get back here somehow 
 405         // during the object deletion (e.g. wxYield called from its dtor) we 
 406         // wouldn't try to delete it the second time 
 407         if ( wxPendingDelete
.Member(obj
) ) 
 408             wxPendingDelete
.Erase(node
); 
 412         // Deleting one object may have deleted other pending 
 413         // objects, so start from beginning of list again. 
 414         node 
= wxPendingDelete
.GetFirst(); 
 418 // Returns true if more time is needed. 
 419 bool wxAppBase::ProcessIdle() 
 422     bool needMore 
= false; 
 423     wxWindowList::compatibility_iterator node 
= wxTopLevelWindows
.GetFirst(); 
 426         wxWindow
* win 
= node
->GetData(); 
 427         if (SendIdleEvents(win
, event
)) 
 429         node 
= node
->GetNext(); 
 432     event
.SetEventObject(this); 
 433     (void) ProcessEvent(event
); 
 434     if (event
.MoreRequested()) 
 437     wxUpdateUIEvent::ResetUpdateTime(); 
 442 // Send idle event to window and all subwindows 
 443 bool wxAppBase::SendIdleEvents(wxWindow
* win
, wxIdleEvent
& event
) 
 445     bool needMore 
= false; 
 447     win
->OnInternalIdle(); 
 449     if (wxIdleEvent::CanSend(win
)) 
 451         event
.SetEventObject(win
); 
 452         win
->GetEventHandler()->ProcessEvent(event
); 
 454         if (event
.MoreRequested()) 
 457     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
 460         wxWindow 
*child 
= node
->GetData(); 
 461         if (SendIdleEvents(child
, event
)) 
 464         node 
= node
->GetNext(); 
 470 void wxAppBase::OnIdle(wxIdleEvent
& WXUNUSED(event
)) 
 472     // If there are pending events, we must process them: pending events 
 473     // are either events to the threads other than main or events posted 
 474     // with wxPostEvent() functions 
 475     // GRG: I have moved this here so that all pending events are processed 
 476     //   before starting to delete any objects. This behaves better (in 
 477     //   particular, wrt wxPostEvent) and is coherent with wxGTK's current 
 478     //   behaviour. Changed Feb/2000 before 2.1.14 
 479     ProcessPendingEvents(); 
 481     // 'Garbage' collection of windows deleted with Close(). 
 482     DeletePendingObjects(); 
 485     // flush the logged messages if any 
 486     wxLog::FlushActive(); 
 491 // ---------------------------------------------------------------------------- 
 492 // exceptions support 
 493 // ---------------------------------------------------------------------------- 
 497 bool wxAppBase::OnExceptionInMainLoop() 
 501     // some compilers are too stupid to know that we never return after throw 
 502 #if defined(__DMC__) || (defined(_MSC_VER) && _MSC_VER < 1200) 
 507 #endif // wxUSE_EXCEPTIONS 
 509 // ---------------------------------------------------------------------------- 
 510 // wxGUIAppTraitsBase 
 511 // ---------------------------------------------------------------------------- 
 515 wxLog 
*wxGUIAppTraitsBase::CreateLogTarget() 
 520     // we must have something! 
 521     return new wxLogStderr
; 
 527 wxMessageOutput 
*wxGUIAppTraitsBase::CreateMessageOutput() 
 529     // The standard way of printing help on command line arguments (app --help) 
 530     // is (according to common practice): 
 531     //     - console apps: to stderr (on any platform) 
 532     //     - GUI apps: stderr on Unix platforms (!) 
 533     //                 message box under Windows and others 
 535     return new wxMessageOutputStderr
; 
 537     // wxMessageOutputMessageBox doesn't work under Motif 
 539         return new wxMessageOutputLog
; 
 541         return new wxMessageOutputMessageBox
; 
 543 #endif // __UNIX__/!__UNIX__ 
 548 wxFontMapper 
*wxGUIAppTraitsBase::CreateFontMapper() 
 550     return new wxFontMapper
; 
 553 #endif // wxUSE_FONTMAP 
 555 wxRendererNative 
*wxGUIAppTraitsBase::CreateRenderer() 
 557     // use the default native renderer by default 
 563 bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString
& msg
) 
 565     // under MSW we prefer to use the base class version using ::MessageBox() 
 566     // even if wxMessageBox() is available because it has less chances to 
 567     // double fault our app than our wxMessageBox() 
 568 #if defined(__WXMSW__) || !wxUSE_MSGDLG 
 569     return wxAppTraitsBase::ShowAssertDialog(msg
); 
 570 #else // wxUSE_MSGDLG 
 571     // this message is intentionally not translated -- it is for 
 573     wxString 
msgDlg(msg
); 
 574     msgDlg 
+= wxT("\nDo you want to stop the program?\n") 
 575               wxT("You can also choose [Cancel] to suppress ") 
 576               wxT("further warnings."); 
 578     switch ( wxMessageBox(msgDlg
, wxT("wxWidgets Debug Alert"), 
 579                           wxYES_NO 
| wxCANCEL 
| wxICON_STOP 
) ) 
 589         //case wxNO: nothing to do 
 593 #endif // !wxUSE_MSGDLG/wxUSE_MSGDLG 
 596 #endif // __WXDEBUG__ 
 598 bool wxGUIAppTraitsBase::HasStderr() 
 600     // we consider that under Unix stderr always goes somewhere, even if the 
 601     // user doesn't always see it under GUI desktops 
 609 void wxGUIAppTraitsBase::ScheduleForDestroy(wxObject 
*object
) 
 611     if ( !wxPendingDelete
.Member(object
) ) 
 612         wxPendingDelete
.Append(object
); 
 615 void wxGUIAppTraitsBase::RemoveFromPendingDelete(wxObject 
*object
) 
 617     wxPendingDelete
.DeleteObject(object
); 
 622 #if defined(__WINDOWS__) 
 623     #include "wx/msw/gsockmsw.h" 
 624 #elif defined(__UNIX__) || defined(__DARWIN__) || defined(__OS2__) 
 625     #include "wx/unix/gsockunx.h" 
 626 #elif defined(__WXMAC__) 
 627     #include <MacHeaders.c> 
 628     #define OTUNIXERRORS 1 
 629     #include <OpenTransport.h> 
 630     #include <OpenTransportProviders.h> 
 631     #include <OpenTptInternet.h> 
 633     #include "wx/mac/gsockmac.h" 
 635     #error "Must include correct GSocket header here" 
 638 GSocketGUIFunctionsTable
* wxGUIAppTraitsBase::GetSocketGUIFunctionsTable() 
 640 #if defined(__WXMAC__) && !defined(__DARWIN__) 
 641     // NB: wxMac CFM does not have any GUI-specific functions in gsocket.c and 
 642     //     so it doesn't need this table at all 
 644 #else // !__WXMAC__ || __DARWIN__ 
 645     static GSocketGUIFunctionsTableConcrete table
; 
 647 #endif // !__WXMAC__ || __DARWIN__