1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/appcmn.cpp
3 // Purpose: wxAppBase methods common to all platforms
4 // Author: Vadim Zeitlin
7 // Copyright: (c) Vadim Zeitlin
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ---------------------------------------------------------------------------
17 // ---------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
22 #if defined(__BORLANDC__)
28 #include "wx/window.h"
29 #include "wx/bitmap.h"
31 #include "wx/msgdlg.h"
32 #include "wx/confbase.h"
34 #include "wx/wxcrtvararg.h"
37 #include "wx/apptrait.h"
38 #include "wx/cmdline.h"
39 #include "wx/msgout.h"
40 #include "wx/thread.h"
41 #include "wx/vidmode.h"
42 #include "wx/evtloop.h"
45 #include "wx/fontmap.h"
46 #endif // wxUSE_FONTMAP
48 // DLL options compatibility check:
50 WX_CHECK_BUILD_OPTIONS("wxCore")
52 // ============================================================================
53 // wxAppBase implementation
54 // ============================================================================
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 wxAppBase::wxAppBase()
64 m_useBestVisual
= false;
65 m_forceTrueColour
= false;
69 // We don't want to exit the app if the user code shows a dialog from its
70 // OnInit() -- but this is what would happen if we set m_exitOnFrameDelete
71 // to Yes initially as this dialog would be the last top level window.
72 // OTOH, if we set it to No initially we'll have to overwrite it with Yes
73 // when we enter our OnRun() because we do want the default behaviour from
74 // then on. But this would be a problem if the user code calls
75 // SetExitOnFrameDelete(false) from OnInit().
77 // So we use the special "Later" value which is such that
78 // GetExitOnFrameDelete() returns false for it but which we know we can
79 // safely (i.e. without losing the effect of the users SetExitOnFrameDelete
80 // call) overwrite in OnRun()
81 m_exitOnFrameDelete
= Later
;
84 bool wxAppBase::Initialize(int& argcOrig
, wxChar
**argvOrig
)
87 // Mac OS X passes a process serial number command line argument when
88 // the application is launched from the Finder. This argument must be
89 // removed from the command line arguments before being handled by the
90 // application (otherwise applications would need to handle it)
92 // Notice that this has to be done for all ports that can be used under OS
93 // X (e.g. wxGTK) and not just wxOSX itself, hence this code is here and
94 // not in a port-specific file.
97 static const wxChar
*ARG_PSN
= wxT("-psn_");
98 if ( wxStrncmp(argvOrig
[1], ARG_PSN
, wxStrlen(ARG_PSN
)) == 0 )
100 // remove this argument
102 memmove(argvOrig
+ 1, argvOrig
+ 2, argcOrig
* sizeof(wxChar
*));
107 if ( !wxAppConsole::Initialize(argcOrig
, argvOrig
) )
110 wxInitializeStockLists();
112 wxBitmap::InitStandardHandlers();
114 // for compatibility call the old initialization function too
121 // ----------------------------------------------------------------------------
123 // ----------------------------------------------------------------------------
125 wxAppBase::~wxAppBase()
127 // this destructor is required for Darwin
130 void wxAppBase::CleanUp()
132 // clean up all the pending objects
133 DeletePendingObjects();
135 // and any remaining TLWs (they remove themselves from wxTopLevelWindows
136 // when destroyed, so iterate until none are left)
137 while ( !wxTopLevelWindows
.empty() )
139 // do not use Destroy() here as it only puts the TLW in pending list
140 // but we want to delete them now
141 delete wxTopLevelWindows
.GetFirst()->GetData();
144 // undo everything we did in Initialize() above
145 wxBitmap::CleanUpHandlers();
147 wxStockGDI::DeleteAll();
149 wxDeleteStockLists();
151 wxDELETE(wxTheColourDatabase
);
153 wxAppConsole::CleanUp();
156 // ----------------------------------------------------------------------------
158 // ----------------------------------------------------------------------------
160 wxWindow
* wxAppBase::GetTopWindow() const
162 wxWindow
* window
= m_topWindow
;
163 if (window
== NULL
&& wxTopLevelWindows
.GetCount() > 0)
164 window
= wxTopLevelWindows
.GetFirst()->GetData();
168 wxVideoMode
wxAppBase::GetDisplayMode() const
170 return wxVideoMode();
173 wxLayoutDirection
wxAppBase::GetLayoutDirection() const
176 const wxLocale
*const locale
= wxGetLocale();
179 const wxLanguageInfo
*const
180 info
= wxLocale::GetLanguageInfo(locale
->GetLanguage());
183 return info
->LayoutDirection
;
188 return wxLayout_Default
;
191 #if wxUSE_CMDLINE_PARSER
193 // ----------------------------------------------------------------------------
194 // GUI-specific command line options handling
195 // ----------------------------------------------------------------------------
197 #define OPTION_THEME "theme"
198 #define OPTION_MODE "mode"
200 void wxAppBase::OnInitCmdLine(wxCmdLineParser
& parser
)
202 // first add the standard non GUI options
203 wxAppConsole::OnInitCmdLine(parser
);
205 // the standard command line options
206 static const wxCmdLineEntryDesc cmdLineGUIDesc
[] =
208 #ifdef __WXUNIVERSAL__
213 gettext_noop("specify the theme to use"),
214 wxCMD_LINE_VAL_STRING
,
217 #endif // __WXUNIVERSAL__
219 #if defined(__WXDFB__)
220 // VS: this is not specific to wxDFB, all fullscreen (framebuffer) ports
221 // should provide this option. That's why it is in common/appcmn.cpp
222 // and not dfb/app.cpp
227 gettext_noop("specify display mode to use (e.g. 640x480-16)"),
228 wxCMD_LINE_VAL_STRING
,
237 parser
.SetDesc(cmdLineGUIDesc
);
240 bool wxAppBase::OnCmdLineParsed(wxCmdLineParser
& parser
)
242 #ifdef __WXUNIVERSAL__
244 if ( parser
.Found(OPTION_THEME
, &themeName
) )
246 wxTheme
*theme
= wxTheme::Create(themeName
);
249 wxLogError(_("Unsupported theme '%s'."), themeName
.c_str());
253 // Delete the defaultly created theme and set the new theme.
254 delete wxTheme::Get();
257 #endif // __WXUNIVERSAL__
259 #if defined(__WXDFB__)
261 if ( parser
.Found(OPTION_MODE
, &modeDesc
) )
264 if ( wxSscanf(modeDesc
.c_str(), wxT("%ux%u-%u"), &w
, &h
, &bpp
) != 3 )
266 wxLogError(_("Invalid display mode specification '%s'."), modeDesc
.c_str());
270 if ( !SetDisplayMode(wxVideoMode(w
, h
, bpp
)) )
275 return wxAppConsole::OnCmdLineParsed(parser
);
278 #endif // wxUSE_CMDLINE_PARSER
280 // ----------------------------------------------------------------------------
282 // ----------------------------------------------------------------------------
284 bool wxAppBase::OnInitGui()
286 #ifdef __WXUNIVERSAL__
287 if ( !wxTheme::Get() && !wxTheme::CreateDefault() )
289 #endif // __WXUNIVERSAL__
294 int wxAppBase::OnRun()
296 // see the comment in ctor: if the initial value hasn't been changed, use
297 // the default Yes from now on
298 if ( m_exitOnFrameDelete
== Later
)
300 m_exitOnFrameDelete
= Yes
;
302 //else: it has been changed, assume the user knows what he is doing
304 return wxAppConsole::OnRun();
307 int wxAppBase::OnExit()
309 #ifdef __WXUNIVERSAL__
310 delete wxTheme::Set(NULL
);
311 #endif // __WXUNIVERSAL__
313 return wxAppConsole::OnExit();
316 wxAppTraits
*wxAppBase::CreateTraits()
318 return new wxGUIAppTraits
;
321 // ----------------------------------------------------------------------------
323 // ----------------------------------------------------------------------------
325 void wxAppBase::SetActive(bool active
, wxWindow
* WXUNUSED(lastFocus
))
327 if ( active
== m_isActive
)
332 wxActivateEvent
event(wxEVT_ACTIVATE_APP
, active
);
333 event
.SetEventObject(this);
335 (void)ProcessEvent(event
);
338 bool wxAppBase::SafeYield(wxWindow
*win
, bool onlyIfNeeded
)
340 wxWindowDisabler
wd(win
);
342 wxEventLoopBase
* const loop
= wxEventLoopBase::GetActive();
344 return loop
&& loop
->Yield(onlyIfNeeded
);
347 bool wxAppBase::SafeYieldFor(wxWindow
*win
, long eventsToProcess
)
349 wxWindowDisabler
wd(win
);
351 wxEventLoopBase
* const loop
= wxEventLoopBase::GetActive();
353 return loop
&& loop
->YieldFor(eventsToProcess
);
357 // ----------------------------------------------------------------------------
359 // ----------------------------------------------------------------------------
361 // Returns true if more time is needed.
362 bool wxAppBase::ProcessIdle()
364 // call the base class version first to send the idle event to wxTheApp
366 bool needMore
= wxAppConsoleBase::ProcessIdle();
368 wxWindowList::compatibility_iterator node
= wxTopLevelWindows
.GetFirst();
371 wxWindow
* win
= node
->GetData();
373 // Don't send idle events to the windows that are about to be destroyed
374 // anyhow, this is wasteful and unexpected.
375 if ( !wxPendingDelete
.Member(win
) && win
->SendIdleEvents(event
) )
377 node
= node
->GetNext();
380 wxUpdateUIEvent::ResetUpdateTime();
385 // ----------------------------------------------------------------------------
386 // wxGUIAppTraitsBase
387 // ----------------------------------------------------------------------------
391 wxLog
*wxGUIAppTraitsBase::CreateLogTarget()
394 #ifndef __WXOSX_IPHONE__
397 return new wxLogStderr
;
400 // we must have something!
401 return new wxLogStderr
;
407 wxMessageOutput
*wxGUIAppTraitsBase::CreateMessageOutput()
409 // The standard way of printing help on command line arguments (app --help)
410 // is (according to common practice):
411 // - console apps: to stderr (on any platform)
412 // - GUI apps: stderr on Unix platforms (!)
413 // stderr if available and message box otherwise on others
414 // (currently stderr only Windows if app running from console)
416 return new wxMessageOutputStderr
;
418 // wxMessageOutputMessageBox doesn't work under Motif
420 return new wxMessageOutputLog
;
422 return new wxMessageOutputBest(wxMSGOUT_PREFER_STDERR
);
424 return new wxMessageOutputStderr
;
426 #endif // __UNIX__/!__UNIX__
431 wxFontMapper
*wxGUIAppTraitsBase::CreateFontMapper()
433 return new wxFontMapper
;
436 #endif // wxUSE_FONTMAP
438 wxRendererNative
*wxGUIAppTraitsBase::CreateRenderer()
440 // use the default native renderer by default
444 bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString
& msg
)
447 // under MSW we prefer to use the base class version using ::MessageBox()
448 // even if wxMessageBox() is available because it has less chances to
449 // double fault our app than our wxMessageBox()
451 // under DFB the message dialog is not always functional right now
453 // and finally we can't use wxMessageBox() if it wasn't compiled in, of
455 #if !defined(__WXMSW__) && !defined(__WXDFB__) && wxUSE_MSGDLG
457 // we can't (safely) show the GUI dialog from another thread, only do it
458 // for the asserts in the main thread
459 if ( wxIsMainThread() )
461 wxString msgDlg
= msg
;
463 #if wxUSE_STACKWALKER
464 const wxString stackTrace
= GetAssertStackTrace();
465 if ( !stackTrace
.empty() )
466 msgDlg
<< wxT("\n\nCall stack:\n") << stackTrace
;
467 #endif // wxUSE_STACKWALKER
469 // this message is intentionally not translated -- it is for
471 msgDlg
+= wxT("\nDo you want to stop the program?\n")
472 wxT("You can also choose [Cancel] to suppress ")
473 wxT("further warnings.");
475 switch ( wxMessageBox(msgDlg
, wxT("wxWidgets Debug Alert"),
476 wxYES_NO
| wxCANCEL
| wxICON_STOP
) )
486 //case wxNO: nothing to do
491 #endif // wxUSE_MSGDLG
492 #endif // wxDEBUG_LEVEL
494 return wxAppTraitsBase::ShowAssertDialog(msg
);
497 bool wxGUIAppTraitsBase::HasStderr()
499 // we consider that under Unix stderr always goes somewhere, even if the
500 // user doesn't always see it under GUI desktops