]> git.saurik.com Git - wxWidgets.git/blame - src/common/appcmn.cpp
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / src / common / appcmn.cpp
CommitLineData
72cdf4c9 1/////////////////////////////////////////////////////////////////////////////
127eab18 2// Name: src/common/appcmn.cpp
90e15296 3// Purpose: wxAppBase methods common to all platforms
72cdf4c9
VZ
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 18.10.99
72cdf4c9 7// Copyright: (c) Vadim Zeitlin
65571936 8// Licence: wxWindows licence
72cdf4c9
VZ
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ---------------------------------------------------------------------------
16// headers
17// ---------------------------------------------------------------------------
18
72cdf4c9
VZ
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#if defined(__BORLANDC__)
23 #pragma hdrstop
24#endif
25
26#ifndef WX_PRECOMP
27 #include "wx/app.h"
5ff14574 28 #include "wx/window.h"
b2e972ec 29 #include "wx/bitmap.h"
46446cc2 30 #include "wx/log.h"
e2478fde 31 #include "wx/msgdlg.h"
b3dfbbc9 32 #include "wx/confbase.h"
de6185e2 33 #include "wx/utils.h"
193d0c93 34 #include "wx/wxcrtvararg.h"
72cdf4c9
VZ
35#endif
36
e2478fde 37#include "wx/apptrait.h"
b913d3ed 38#include "wx/cmdline.h"
e2478fde 39#include "wx/msgout.h"
72cdf4c9 40#include "wx/thread.h"
5ff14574 41#include "wx/vidmode.h"
dde19c21 42#include "wx/evtloop.h"
a5f1fd3e 43
1c193821
JS
44#if wxUSE_FONTMAP
45 #include "wx/fontmap.h"
46#endif // wxUSE_FONTMAP
47
34fdf762
VS
48// DLL options compatibility check:
49#include "wx/build.h"
50WX_CHECK_BUILD_OPTIONS("wxCore")
51
e2478fde
VZ
52// ============================================================================
53// wxAppBase implementation
54// ============================================================================
d54598dd 55
bf188f1a 56// ----------------------------------------------------------------------------
94826170 57// initialization
bf188f1a
VZ
58// ----------------------------------------------------------------------------
59
090a6d7a 60wxAppBase::wxAppBase()
697c5f51 61{
d3b9f782 62 m_topWindow = NULL;
b46b1d59 63
4629016d 64 m_useBestVisual = false;
515a31bf 65 m_forceTrueColour = false;
1cbee0b4 66
b46b1d59 67 m_isActive = true;
1bf77ee5 68
1cbee0b4
VZ
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
4629016d 75 // SetExitOnFrameDelete(false) from OnInit().
1cbee0b4
VZ
76 //
77 // So we use the special "Later" value which is such that
4629016d 78 // GetExitOnFrameDelete() returns false for it but which we know we can
1cbee0b4
VZ
79 // safely (i.e. without losing the effect of the users SetExitOnFrameDelete
80 // call) overwrite in OnRun()
81 m_exitOnFrameDelete = Later;
1e6feb95
VZ
82}
83
a54930e0 84bool wxAppBase::Initialize(int& argcOrig, wxChar **argvOrig)
94826170 85{
9e9574fe
VZ
86#ifdef __WXOSX__
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)
91 //
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.
95 if ( argcOrig > 1 )
96 {
97 static const wxChar *ARG_PSN = wxT("-psn_");
98 if ( wxStrncmp(argvOrig[1], ARG_PSN, wxStrlen(ARG_PSN)) == 0 )
99 {
100 // remove this argument
101 --argcOrig;
102 memmove(argvOrig + 1, argvOrig + 2, argcOrig * sizeof(wxChar*));
103 }
104 }
105#endif // __WXOSX__
106
a54930e0 107 if ( !wxAppConsole::Initialize(argcOrig, argvOrig) )
94826170
VZ
108 return false;
109
94826170 110 wxInitializeStockLists();
94826170
VZ
111
112 wxBitmap::InitStandardHandlers();
113
1f2f7329
FM
114 // for compatibility call the old initialization function too
115 if ( !OnInitGui() )
116 return false;
117
94826170
VZ
118 return true;
119}
120
121// ----------------------------------------------------------------------------
122// cleanup
123// ----------------------------------------------------------------------------
124
799ea011
GD
125wxAppBase::~wxAppBase()
126{
127 // this destructor is required for Darwin
128}
129
94826170
VZ
130void wxAppBase::CleanUp()
131{
07460370 132 // clean up all the pending objects
94826170
VZ
133 DeletePendingObjects();
134
07460370
VZ
135 // and any remaining TLWs (they remove themselves from wxTopLevelWindows
136 // when destroyed, so iterate until none are left)
137 while ( !wxTopLevelWindows.empty() )
138 {
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();
142 }
4055ed82 143
07460370 144 // undo everything we did in Initialize() above
94826170
VZ
145 wxBitmap::CleanUpHandlers();
146
f516d986 147 wxStockGDI::DeleteAll();
94826170
VZ
148
149 wxDeleteStockLists();
150
5276b0a5 151 wxDELETE(wxTheColourDatabase);
94826170 152
68d2c3be 153 wxAppConsole::CleanUp();
94826170
VZ
154}
155
475a93b7
VZ
156// ----------------------------------------------------------------------------
157// various accessors
5ff14574
PC
158// ----------------------------------------------------------------------------
159
160wxWindow* wxAppBase::GetTopWindow() const
161{
162 wxWindow* window = m_topWindow;
163 if (window == NULL && wxTopLevelWindows.GetCount() > 0)
164 window = wxTopLevelWindows.GetFirst()->GetData();
165 return window;
166}
167
168wxVideoMode wxAppBase::GetDisplayMode() const
169{
170 return wxVideoMode();
171}
172
475a93b7
VZ
173wxLayoutDirection wxAppBase::GetLayoutDirection() const
174{
175#if wxUSE_INTL
176 const wxLocale *const locale = wxGetLocale();
177 if ( locale )
178 {
179 const wxLanguageInfo *const
180 info = wxLocale::GetLanguageInfo(locale->GetLanguage());
181
182 if ( info )
183 return info->LayoutDirection;
184 }
185#endif // wxUSE_INTL
186
187 // we don't know
188 return wxLayout_Default;
189}
190
b913d3ed
VZ
191#if wxUSE_CMDLINE_PARSER
192
193// ----------------------------------------------------------------------------
194// GUI-specific command line options handling
195// ----------------------------------------------------------------------------
196
c2e45372
VZ
197#define OPTION_THEME "theme"
198#define OPTION_MODE "mode"
b913d3ed
VZ
199
200void wxAppBase::OnInitCmdLine(wxCmdLineParser& parser)
201{
9c13e5ef
VZ
202 // first add the standard non GUI options
203 wxAppConsole::OnInitCmdLine(parser);
204
b913d3ed
VZ
205 // the standard command line options
206 static const wxCmdLineEntryDesc cmdLineGUIDesc[] =
207 {
208#ifdef __WXUNIVERSAL__
209 {
210 wxCMD_LINE_OPTION,
0d5ab92f 211 NULL,
b913d3ed
VZ
212 OPTION_THEME,
213 gettext_noop("specify the theme to use"),
214 wxCMD_LINE_VAL_STRING,
215 0x0
216 },
217#endif // __WXUNIVERSAL__
218
0e1f8ea4
VZ
219#if defined(__WXDFB__)
220 // VS: this is not specific to wxDFB, all fullscreen (framebuffer) ports
b913d3ed 221 // should provide this option. That's why it is in common/appcmn.cpp
0e1f8ea4 222 // and not dfb/app.cpp
b913d3ed
VZ
223 {
224 wxCMD_LINE_OPTION,
0d5ab92f 225 NULL,
b913d3ed
VZ
226 OPTION_MODE,
227 gettext_noop("specify display mode to use (e.g. 640x480-16)"),
228 wxCMD_LINE_VAL_STRING,
229 0x0
230 },
0e1f8ea4 231#endif // __WXDFB__
b913d3ed
VZ
232
233 // terminator
0d5ab92f 234 wxCMD_LINE_DESC_END
b913d3ed
VZ
235 };
236
237 parser.SetDesc(cmdLineGUIDesc);
238}
239
240bool wxAppBase::OnCmdLineParsed(wxCmdLineParser& parser)
241{
242#ifdef __WXUNIVERSAL__
243 wxString themeName;
244 if ( parser.Found(OPTION_THEME, &themeName) )
245 {
246 wxTheme *theme = wxTheme::Create(themeName);
247 if ( !theme )
248 {
249 wxLogError(_("Unsupported theme '%s'."), themeName.c_str());
4629016d 250 return false;
b913d3ed
VZ
251 }
252
253 // Delete the defaultly created theme and set the new theme.
254 delete wxTheme::Get();
255 wxTheme::Set(theme);
256 }
257#endif // __WXUNIVERSAL__
258
0e1f8ea4 259#if defined(__WXDFB__)
b913d3ed
VZ
260 wxString modeDesc;
261 if ( parser.Found(OPTION_MODE, &modeDesc) )
262 {
263 unsigned w, h, bpp;
9a83f860 264 if ( wxSscanf(modeDesc.c_str(), wxT("%ux%u-%u"), &w, &h, &bpp) != 3 )
b913d3ed
VZ
265 {
266 wxLogError(_("Invalid display mode specification '%s'."), modeDesc.c_str());
4629016d 267 return false;
b913d3ed
VZ
268 }
269
1c53456f 270 if ( !SetDisplayMode(wxVideoMode(w, h, bpp)) )
4629016d 271 return false;
b913d3ed 272 }
0e1f8ea4 273#endif // __WXDFB__
b913d3ed
VZ
274
275 return wxAppConsole::OnCmdLineParsed(parser);
276}
277
278#endif // wxUSE_CMDLINE_PARSER
279
94826170
VZ
280// ----------------------------------------------------------------------------
281// OnXXX() hooks
282// ----------------------------------------------------------------------------
283
1e6feb95
VZ
284bool wxAppBase::OnInitGui()
285{
286#ifdef __WXUNIVERSAL__
bf188f1a 287 if ( !wxTheme::Get() && !wxTheme::CreateDefault() )
4629016d 288 return false;
1e6feb95
VZ
289#endif // __WXUNIVERSAL__
290
4629016d 291 return true;
1e6feb95 292}
1e6feb95 293
1cbee0b4
VZ
294int wxAppBase::OnRun()
295{
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 )
299 {
300 m_exitOnFrameDelete = Yes;
301 }
302 //else: it has been changed, assume the user knows what he is doing
303
b46b1d59 304 return wxAppConsole::OnRun();
1cbee0b4
VZ
305}
306
b913d3ed
VZ
307int wxAppBase::OnExit()
308{
309#ifdef __WXUNIVERSAL__
310 delete wxTheme::Set(NULL);
311#endif // __WXUNIVERSAL__
312
313 return wxAppConsole::OnExit();
314}
315
e2478fde 316wxAppTraits *wxAppBase::CreateTraits()
a69be60b 317{
7843d11b 318 return new wxGUIAppTraits;
72cdf4c9
VZ
319}
320
1e6feb95
VZ
321// ----------------------------------------------------------------------------
322// misc
323// ----------------------------------------------------------------------------
324
6e169cf3 325void wxAppBase::SetActive(bool active, wxWindow * WXUNUSED(lastFocus))
7beba2fc 326{
66dfed9b
VZ
327 if ( active == m_isActive )
328 return;
329
1e6feb95 330 m_isActive = active;
66dfed9b
VZ
331
332 wxActivateEvent event(wxEVT_ACTIVATE_APP, active);
333 event.SetEventObject(this);
334
335 (void)ProcessEvent(event);
7beba2fc 336}
1e6feb95 337
d48b06bd
FM
338bool wxAppBase::SafeYield(wxWindow *win, bool onlyIfNeeded)
339{
340 wxWindowDisabler wd(win);
341
dde19c21
FM
342 wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
343
344 return loop && loop->Yield(onlyIfNeeded);
d48b06bd
FM
345}
346
347bool wxAppBase::SafeYieldFor(wxWindow *win, long eventsToProcess)
348{
349 wxWindowDisabler wd(win);
350
dde19c21
FM
351 wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
352
353 return loop && loop->YieldFor(eventsToProcess);
d48b06bd
FM
354}
355
356
2dc62891
VZ
357// ----------------------------------------------------------------------------
358// idle handling
359// ----------------------------------------------------------------------------
360
4629016d 361// Returns true if more time is needed.
e39af974
JS
362bool wxAppBase::ProcessIdle()
363{
3185abc2
VZ
364 // call the base class version first to send the idle event to wxTheApp
365 // itself
14eb37a0 366 bool needMore = wxAppConsoleBase::ProcessIdle();
5109ae5d 367 wxIdleEvent event;
222ed1d6 368 wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
e39af974
JS
369 while (node)
370 {
371 wxWindow* win = node->GetData();
9df70d79
VZ
372
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) )
4629016d 376 needMore = true;
e39af974
JS
377 node = node->GetNext();
378 }
379
e39af974 380 wxUpdateUIEvent::ResetUpdateTime();
4629016d 381
5109ae5d 382 return needMore;
e39af974
JS
383}
384
bf188f1a 385// ----------------------------------------------------------------------------
e2478fde 386// wxGUIAppTraitsBase
bf188f1a
VZ
387// ----------------------------------------------------------------------------
388
bf188f1a 389#if wxUSE_LOG
bf188f1a 390
e2478fde
VZ
391wxLog *wxGUIAppTraitsBase::CreateLogTarget()
392{
d30ef769 393#if wxUSE_LOGGUI
a3f78ceb 394#ifndef __WXOSX_IPHONE__
e2478fde 395 return new wxLogGui;
a3f78ceb
SC
396#else
397 return new wxLogStderr;
398#endif
461dae94 399#else
fa6416df 400 // we must have something!
461dae94
VZ
401 return new wxLogStderr;
402#endif
bf188f1a
VZ
403}
404
bf188f1a
VZ
405#endif // wxUSE_LOG
406
e2478fde 407wxMessageOutput *wxGUIAppTraitsBase::CreateMessageOutput()
bf188f1a 408{
e2478fde
VZ
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 (!)
784ee7d5
VZ
413 // stderr if available and message box otherwise on others
414 // (currently stderr only Windows if app running from console)
e2478fde
VZ
415#ifdef __UNIX__
416 return new wxMessageOutputStderr;
417#else // !__UNIX__
418 // wxMessageOutputMessageBox doesn't work under Motif
419 #ifdef __WXMOTIF__
420 return new wxMessageOutputLog;
a8ff046b 421 #elif wxUSE_MSGDLG
784ee7d5 422 return new wxMessageOutputBest(wxMSGOUT_PREFER_STDERR);
a8ff046b
VZ
423 #else
424 return new wxMessageOutputStderr;
e2478fde
VZ
425 #endif
426#endif // __UNIX__/!__UNIX__
bf188f1a
VZ
427}
428
e2478fde 429#if wxUSE_FONTMAP
bf188f1a 430
e2478fde
VZ
431wxFontMapper *wxGUIAppTraitsBase::CreateFontMapper()
432{
433 return new wxFontMapper;
bf188f1a
VZ
434}
435
e2478fde 436#endif // wxUSE_FONTMAP
bf188f1a 437
f0244295
VZ
438wxRendererNative *wxGUIAppTraitsBase::CreateRenderer()
439{
440 // use the default native renderer by default
441 return NULL;
442}
443
e2478fde
VZ
444bool wxGUIAppTraitsBase::ShowAssertDialog(const wxString& msg)
445{
2d8e0096 446#if wxDEBUG_LEVEL
e2478fde
VZ
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()
19a67f39
VZ
450 //
451 // under DFB the message dialog is not always functional right now
452 //
453 // and finally we can't use wxMessageBox() if it wasn't compiled in, of
454 // course
2d8e0096
VZ
455#if !defined(__WXMSW__) && !defined(__WXDFB__) && wxUSE_MSGDLG
456
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() )
460 {
461 wxString msgDlg = msg;
db9febdf
RR
462
463#if wxUSE_STACKWALKER
2d8e0096
VZ
464 const wxString stackTrace = GetAssertStackTrace();
465 if ( !stackTrace.empty() )
466 msgDlg << wxT("\n\nCall stack:\n") << stackTrace;
db9febdf
RR
467#endif // wxUSE_STACKWALKER
468
2d8e0096
VZ
469 // this message is intentionally not translated -- it is for
470 // developpers only
471 msgDlg += wxT("\nDo you want to stop the program?\n")
472 wxT("You can also choose [Cancel] to suppress ")
473 wxT("further warnings.");
e2478fde 474
2d8e0096
VZ
475 switch ( wxMessageBox(msgDlg, wxT("wxWidgets Debug Alert"),
476 wxYES_NO | wxCANCEL | wxICON_STOP ) )
477 {
478 case wxYES:
479 wxTrap();
480 break;
481
482 case wxCANCEL:
483 // no more asserts
484 return true;
090a6d7a 485
2d8e0096
VZ
486 //case wxNO: nothing to do
487 }
a5f1fd3e 488
2d8e0096 489 return false;
090a6d7a 490 }
2d8e0096
VZ
491#endif // wxUSE_MSGDLG
492#endif // wxDEBUG_LEVEL
090a6d7a 493
2d8e0096 494 return wxAppTraitsBase::ShowAssertDialog(msg);
a5f1fd3e
VZ
495}
496
e2478fde 497bool wxGUIAppTraitsBase::HasStderr()
a5f1fd3e 498{
e2478fde
VZ
499 // we consider that under Unix stderr always goes somewhere, even if the
500 // user doesn't always see it under GUI desktops
501#ifdef __UNIX__
502 return true;
a5f1fd3e 503#else
e2478fde 504 return false;
a5f1fd3e 505#endif
a5f1fd3e
VZ
506}
507