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" 
  35     #include "wx/wxcrtvararg.h" 
  38 #include "wx/apptrait.h" 
  39 #include "wx/cmdline.h" 
  40 #include "wx/msgout.h" 
  41 #include "wx/thread.h" 
  42 #include "wx/vidmode.h" 
  46         #include "wx/stackwalk.h" 
  47     #endif // wxUSE_STACKWALKER 
  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") 
  62 WXDLLIMPEXP_DATA_CORE(wxList
) wxPendingDelete
; 
  64 // ============================================================================ 
  65 // wxAppBase implementation 
  66 // ============================================================================ 
  68 // ---------------------------------------------------------------------------- 
  70 // ---------------------------------------------------------------------------- 
  72 wxAppBase::wxAppBase() 
  74     m_topWindow 
= (wxWindow 
*)NULL
; 
  76     m_useBestVisual 
= false; 
  77     m_forceTrueColour 
= false; 
  81     // We don't want to exit the app if the user code shows a dialog from its 
  82     // OnInit() -- but this is what would happen if we set m_exitOnFrameDelete 
  83     // to Yes initially as this dialog would be the last top level window. 
  84     // OTOH, if we set it to No initially we'll have to overwrite it with Yes 
  85     // when we enter our OnRun() because we do want the default behaviour from 
  86     // then on. But this would be a problem if the user code calls 
  87     // SetExitOnFrameDelete(false) from OnInit(). 
  89     // So we use the special "Later" value which is such that 
  90     // GetExitOnFrameDelete() returns false for it but which we know we can 
  91     // safely (i.e. without losing the effect of the users SetExitOnFrameDelete 
  92     // call) overwrite in OnRun() 
  93     m_exitOnFrameDelete 
= Later
; 
  96 bool wxAppBase::Initialize(int& argcOrig
, wxChar 
**argvOrig
) 
  98     if ( !wxAppConsole::Initialize(argcOrig
, argvOrig
) ) 
 101     wxInitializeStockLists(); 
 103     wxBitmap::InitStandardHandlers(); 
 108 // ---------------------------------------------------------------------------- 
 110 // ---------------------------------------------------------------------------- 
 112 wxAppBase::~wxAppBase() 
 114     // this destructor is required for Darwin 
 117 void wxAppBase::CleanUp() 
 119     // clean up all the pending objects 
 120     DeletePendingObjects(); 
 122     // and any remaining TLWs (they remove themselves from wxTopLevelWindows 
 123     // when destroyed, so iterate until none are left) 
 124     while ( !wxTopLevelWindows
.empty() ) 
 126         // do not use Destroy() here as it only puts the TLW in pending list 
 127         // but we want to delete them now 
 128         delete wxTopLevelWindows
.GetFirst()->GetData(); 
 131     // undo everything we did in Initialize() above 
 132     wxBitmap::CleanUpHandlers(); 
 134     wxStockGDI::DeleteAll(); 
 136     wxDeleteStockLists(); 
 138     delete wxTheColourDatabase
; 
 139     wxTheColourDatabase 
= NULL
; 
 143         // If we don't do the following, we get an apparent memory leak. 
 144         ((wxEvtHandler
&) wxDefaultValidator
).ClearEventLocker(); 
 145     #endif // wxUSE_VALIDATORS 
 146 #endif // wxUSE_THREADS 
 148     wxAppConsole::CleanUp(); 
 151 // ---------------------------------------------------------------------------- 
 153 // ---------------------------------------------------------------------------- 
 155 wxWindow
* wxAppBase::GetTopWindow() const 
 157     wxWindow
* window 
= m_topWindow
; 
 158     if (window 
== NULL 
&& wxTopLevelWindows
.GetCount() > 0) 
 159         window 
= wxTopLevelWindows
.GetFirst()->GetData(); 
 163 wxVideoMode 
wxAppBase::GetDisplayMode() const 
 165     return wxVideoMode(); 
 168 wxLayoutDirection 
wxAppBase::GetLayoutDirection() const 
 171     const wxLocale 
*const locale 
= wxGetLocale(); 
 174         const wxLanguageInfo 
*const 
 175             info 
= wxLocale::GetLanguageInfo(locale
->GetLanguage()); 
 178             return info
->LayoutDirection
; 
 183     return wxLayout_Default
; 
 186 #if wxUSE_CMDLINE_PARSER 
 188 // ---------------------------------------------------------------------------- 
 189 // GUI-specific command line options handling 
 190 // ---------------------------------------------------------------------------- 
 192 #define OPTION_THEME   _T("theme") 
 193 #define OPTION_MODE    _T("mode") 
 195 void wxAppBase::OnInitCmdLine(wxCmdLineParser
& parser
) 
 197     // first add the standard non GUI options 
 198     wxAppConsole::OnInitCmdLine(parser
); 
 200     // the standard command line options 
 201     static const wxCmdLineEntryDesc cmdLineGUIDesc
[] = 
 203 #ifdef __WXUNIVERSAL__ 
 208             gettext_noop("specify the theme to use"), 
 209             wxCMD_LINE_VAL_STRING
, 
 212 #endif // __WXUNIVERSAL__ 
 214 #if defined(__WXMGL__) 
 215         // VS: this is not specific to wxMGL, all fullscreen (framebuffer) ports 
 216         //     should provide this option. That's why it is in common/appcmn.cpp 
 217         //     and not mgl/app.cpp 
 222             gettext_noop("specify display mode to use (e.g. 640x480-16)"), 
 223             wxCMD_LINE_VAL_STRING
, 
 239     parser
.SetDesc(cmdLineGUIDesc
); 
 242 bool wxAppBase::OnCmdLineParsed(wxCmdLineParser
& parser
) 
 244 #ifdef __WXUNIVERSAL__ 
 246     if ( parser
.Found(OPTION_THEME
, &themeName
) ) 
 248         wxTheme 
*theme 
= wxTheme::Create(themeName
); 
 251             wxLogError(_("Unsupported theme '%s'."), themeName
.c_str()); 
 255         // Delete the defaultly created theme and set the new theme. 
 256         delete wxTheme::Get(); 
 259 #endif // __WXUNIVERSAL__ 
 261 #if defined(__WXMGL__) 
 263     if ( parser
.Found(OPTION_MODE
, &modeDesc
) ) 
 266         if ( wxSscanf(modeDesc
.c_str(), _T("%ux%u-%u"), &w
, &h
, &bpp
) != 3 ) 
 268             wxLogError(_("Invalid display mode specification '%s'."), modeDesc
.c_str()); 
 272         if ( !SetDisplayMode(wxVideoMode(w
, h
, bpp
)) ) 
 277     return wxAppConsole::OnCmdLineParsed(parser
); 
 280 #endif // wxUSE_CMDLINE_PARSER 
 282 // ---------------------------------------------------------------------------- 
 284 // ---------------------------------------------------------------------------- 
 286 bool wxAppBase::OnInitGui() 
 288 #ifdef __WXUNIVERSAL__ 
 289     if ( !wxTheme::Get() && !wxTheme::CreateDefault() ) 
 291 #endif // __WXUNIVERSAL__ 
 296 int wxAppBase::OnRun() 
 298     // see the comment in ctor: if the initial value hasn't been changed, use 
 299     // the default Yes from now on 
 300     if ( m_exitOnFrameDelete 
== Later 
) 
 302         m_exitOnFrameDelete 
= Yes
; 
 304     //else: it has been changed, assume the user knows what he is doing 
 306     return wxAppConsole::OnRun(); 
 309 int wxAppBase::OnExit() 
 311 #ifdef __WXUNIVERSAL__ 
 312     delete wxTheme::Set(NULL
); 
 313 #endif // __WXUNIVERSAL__ 
 315     return wxAppConsole::OnExit(); 
 318 wxAppTraits 
*wxAppBase::CreateTraits() 
 320     return new wxGUIAppTraits
; 
 323 // ---------------------------------------------------------------------------- 
 325 // ---------------------------------------------------------------------------- 
 327 void wxAppBase::SetActive(bool active
, wxWindow 
* WXUNUSED(lastFocus
)) 
 329     if ( active 
== m_isActive 
) 
 334     wxActivateEvent 
event(wxEVT_ACTIVATE_APP
, active
); 
 335     event
.SetEventObject(this); 
 337     (void)ProcessEvent(event
); 
 340 // ---------------------------------------------------------------------------- 
 342 // ---------------------------------------------------------------------------- 
 344 void wxAppBase::DeletePendingObjects() 
 346     wxList::compatibility_iterator node 
= wxPendingDelete
.GetFirst(); 
 349         wxObject 
*obj 
= node
->GetData(); 
 351         // remove it from the list first so that if we get back here somehow 
 352         // during the object deletion (e.g. wxYield called from its dtor) we 
 353         // wouldn't try to delete it the second time 
 354         if ( wxPendingDelete
.Member(obj
) ) 
 355             wxPendingDelete
.Erase(node
); 
 359         // Deleting one object may have deleted other pending 
 360         // objects, so start from beginning of list again. 
 361         node 
= wxPendingDelete
.GetFirst(); 
 365 // Returns true if more time is needed. 
 366 bool wxAppBase::ProcessIdle() 
 368     // process pending wx events before sending idle events 
 369     ProcessPendingEvents(); 
 372     bool needMore 
= false; 
 373     wxWindowList::compatibility_iterator node 
= wxTopLevelWindows
.GetFirst(); 
 376         wxWindow
* win 
= node
->GetData(); 
 377         if (SendIdleEvents(win
, event
)) 
 379         node 
= node
->GetNext(); 
 382     if (wxAppConsole::ProcessIdle()) 
 385     // 'Garbage' collection of windows deleted with Close(). 
 386     DeletePendingObjects(); 
 389     // flush the logged messages if any 
 390     wxLog::FlushActive(); 
 393     wxUpdateUIEvent::ResetUpdateTime(); 
 398 // Send idle event to window and all subwindows 
 399 bool wxAppBase::SendIdleEvents(wxWindow
* win
, wxIdleEvent
& event
) 
 401     bool needMore 
= false; 
 403     win
->OnInternalIdle(); 
 405     // should we send idle event to this window? 
 406     if ( wxIdleEvent::GetMode() == wxIDLE_PROCESS_ALL 
|| 
 407             win
->HasExtraStyle(wxWS_EX_PROCESS_IDLE
) ) 
 409         event
.SetEventObject(win
); 
 410         win
->GetEventHandler()->ProcessEvent(event
); 
 412         if (event
.MoreRequested()) 
 415     wxWindowList::compatibility_iterator node 
= win
->GetChildren().GetFirst(); 
 418         wxWindow 
*child 
= node
->GetData(); 
 419         if (SendIdleEvents(child
, event
)) 
 422         node 
= node
->GetNext(); 
 428 // ---------------------------------------------------------------------------- 
 429 // wxGUIAppTraitsBase 
 430 // ---------------------------------------------------------------------------- 
 434 wxLog 
*wxGUIAppTraitsBase::CreateLogTarget() 
 439     // we must have something! 
 440     return new wxLogStderr
; 
 446 wxMessageOutput 
*wxGUIAppTraitsBase::CreateMessageOutput() 
 448     // The standard way of printing help on command line arguments (app --help) 
 449     // is (according to common practice): 
 450     //     - console apps: to stderr (on any platform) 
 451     //     - GUI apps: stderr on Unix platforms (!) 
 452     //                 message box under Windows and others 
 454     return new wxMessageOutputStderr
; 
 456     // wxMessageOutputMessageBox doesn't work under Motif 
 458         return new wxMessageOutputLog
; 
 460         return new wxMessageOutputMessageBox
; 
 462 #endif // __UNIX__/!__UNIX__ 
 467 wxFontMapper 
*wxGUIAppTraitsBase::CreateFontMapper() 
 469     return new wxFontMapper
; 
 472 #endif // wxUSE_FONTMAP 
 474 wxRendererNative 
*wxGUIAppTraitsBase::CreateRenderer() 
 476     // use the default native renderer by default 
 482 bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString
& msg
) 
 484 #if defined(__WXMSW__) || !wxUSE_MSGDLG 
 485     // under MSW we prefer to use the base class version using ::MessageBox() 
 486     // even if wxMessageBox() is available because it has less chances to 
 487     // double fault our app than our wxMessageBox() 
 488     return wxAppTraitsBase::ShowAssertDialog(msg
); 
 489 #else // wxUSE_MSGDLG 
 490     wxString msgDlg 
= msg
; 
 492 #if wxUSE_STACKWALKER 
 493     // on Unix stack frame generation may take some time, depending on the 
 494     // size of the executable mainly... warn the user that we are working 
 495     wxFprintf(stderr
, wxT("[Debug] Generating a stack trace... please wait")); 
 498     const wxString stackTrace 
= GetAssertStackTrace(); 
 499     if ( !stackTrace
.empty() ) 
 500         msgDlg 
<< _T("\n\nCall stack:\n") << stackTrace
; 
 501 #endif // wxUSE_STACKWALKER 
 503     // this message is intentionally not translated -- it is for 
 505     msgDlg 
+= wxT("\nDo you want to stop the program?\n") 
 506               wxT("You can also choose [Cancel] to suppress ") 
 507               wxT("further warnings."); 
 509     switch ( wxMessageBox(msgDlg
, wxT("wxWidgets Debug Alert"), 
 510                           wxYES_NO 
| wxCANCEL 
| wxICON_STOP 
) ) 
 520         //case wxNO: nothing to do 
 524 #endif // !wxUSE_MSGDLG/wxUSE_MSGDLG 
 527 #endif // __WXDEBUG__ 
 529 bool wxGUIAppTraitsBase::HasStderr() 
 531     // we consider that under Unix stderr always goes somewhere, even if the 
 532     // user doesn't always see it under GUI desktops 
 540 void wxGUIAppTraitsBase::ScheduleForDestroy(wxObject 
*object
) 
 542     if ( !wxPendingDelete
.Member(object
) ) 
 543         wxPendingDelete
.Append(object
); 
 546 void wxGUIAppTraitsBase::RemoveFromPendingDelete(wxObject 
*object
) 
 548     wxPendingDelete
.DeleteObject(object
); 
 553 #if defined(__WINDOWS__) 
 554     #include "wx/msw/gsockmsw.h" 
 555 #elif defined(__UNIX__) || defined(__DARWIN__) || defined(__OS2__) 
 556     #include "wx/unix/gsockunx.h" 
 557 #elif defined(__WXMAC__) 
 558     #include <MacHeaders.c> 
 559     #define OTUNIXERRORS 1 
 560     #include <OpenTransport.h> 
 561     #include <OpenTransportProviders.h> 
 562     #include <OpenTptInternet.h> 
 564     #include "wx/mac/gsockmac.h" 
 566     #error "Must include correct GSocket header here" 
 569 GSocketGUIFunctionsTable
* wxGUIAppTraitsBase::GetSocketGUIFunctionsTable() 
 571 #if defined(__WXMAC__) && !defined(__DARWIN__) 
 572     // NB: wxMac CFM does not have any GUI-specific functions in gsocket.c and 
 573     //     so it doesn't need this table at all 
 575 #else // !__WXMAC__ || __DARWIN__ 
 576     static GSocketGUIFunctionsTableConcrete table
; 
 578 #endif // !__WXMAC__ || __DARWIN__