]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/app.cpp
Small doc updates, mainly wxDropTarget,
[wxWidgets.git] / src / gtk / app.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: app.cpp
3// Purpose:
4// Author: Robert Roebling
32e9da8b 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling, Julian Smart
8bbe427f 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
afb74891 11 #pragma implementation "app.h"
c801d85f
KB
12#endif
13
14#include "wx/app.h"
15#include "wx/gdicmn.h"
16#include "wx/utils.h"
c801d85f
KB
17#include "wx/intl.h"
18#include "wx/log.h"
46dc76ba 19#include "wx/memory.h"
a3622daa
VZ
20#include "wx/font.h"
21#include "wx/settings.h"
0d2a2b60 22#include "wx/dialog.h"
afb74891 23
06cfab17 24#if wxUSE_WX_RESOURCES
afb74891 25 #include "wx/resource.h"
f5abe911 26#endif
afb74891 27
031b2a7b 28#include "wx/module.h"
4bc67cc5 29#include "wx/image.h"
afb74891 30
91b8de8d 31#if wxUSE_THREADS
f3855ef0 32#include "wx/thread.h"
91b8de8d 33#endif
afb74891 34
20e05ffb 35#include <unistd.h>
c801d85f 36
20e05ffb
RR
37#include <glib.h>
38#include <gdk/gdk.h>
39#include <gtk/gtk.h>
24178e4a 40
83624f79
RR
41#include "wx/gtk/win_gtk.h"
42
c801d85f
KB
43//-----------------------------------------------------------------------------
44// global data
45//-----------------------------------------------------------------------------
46
c67daf87 47wxApp *wxTheApp = (wxApp *) NULL;
32d4bfd1 48wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
c801d85f 49
acfd422a 50extern bool g_isIdle;
c801d85f
KB
51
52//-----------------------------------------------------------------------------
53// local functions
54//-----------------------------------------------------------------------------
55
bf9e3e73 56/* forward declaration */
c4fda16b
RR
57gint wxapp_idle_callback( gpointer WXUNUSED(data) );
58void wxapp_install_idle_handler();
59
60#if wxUSE_THREADS
61gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) );
62#endif
bf9e3e73 63
c801d85f 64//-----------------------------------------------------------------------------
bf9e3e73 65// wxExit
c801d85f
KB
66//-----------------------------------------------------------------------------
67
60acb947 68void wxExit()
c801d85f 69{
ec758a20 70 gtk_main_quit();
ff7b1510 71}
c801d85f 72
bf9e3e73
RR
73//-----------------------------------------------------------------------------
74// wxYield
75//-----------------------------------------------------------------------------
53a8af59 76
60acb947 77bool wxYield()
c801d85f 78{
956dbab1 79 bool has_idle = (wxTheApp->m_idleTag != 0);
e90c1d2a 80
956dbab1 81 if (has_idle)
acfd422a
RR
82 {
83 /* We need to temporarily remove idle callbacks or the loop will
84 never finish. */
85 gtk_idle_remove( wxTheApp->m_idleTag );
86 wxTheApp->m_idleTag = 0;
956dbab1 87 }
acfd422a 88
956dbab1
RR
89 while (gtk_events_pending())
90 gtk_main_iteration();
acfd422a 91
956dbab1
RR
92 /* it's necessary to call ProcessIdle() to update the frames sizes which
93 might have been changed (it also will update other things set from
94 OnUpdateUI() which is a nice (and desired) side effect) */
95 while (wxTheApp->ProcessIdle()) { }
e90c1d2a 96
956dbab1
RR
97 if (has_idle)
98 {
acfd422a
RR
99 /* re-add idle handler */
100 wxTheApp->m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
101 }
e90c1d2a 102
acfd422a
RR
103 return TRUE;
104}
105
bf9e3e73
RR
106//-----------------------------------------------------------------------------
107// wxWakeUpIdle
108//-----------------------------------------------------------------------------
109
110void wxWakeUpIdle()
111{
112 if (g_isIdle)
113 wxapp_install_idle_handler();
114}
115
116//-----------------------------------------------------------------------------
117// local functions
118//-----------------------------------------------------------------------------
119
acfd422a
RR
120gint wxapp_idle_callback( gpointer WXUNUSED(data) )
121{
122 if (!wxTheApp) return TRUE;
e90c1d2a 123
86fdd27b 124#if (GTK_MINOR_VERSION > 0)
7b90a8f2
RR
125 /* when getting called from GDK's idle handler we
126 are no longer within GDK's grab on the GUI
127 thread so we must lock it here ourselves */
128 GDK_THREADS_ENTER ();
86fdd27b 129#endif
094637f6 130
acfd422a
RR
131 /* sent idle event to all who request them */
132 while (wxTheApp->ProcessIdle()) { }
094637f6 133
acfd422a
RR
134 /* we don't want any more idle events until the next event is
135 sent to wxGTK */
53a8af59 136 gtk_idle_remove( wxTheApp->m_idleTag );
acfd422a
RR
137 wxTheApp->m_idleTag = 0;
138
139 /* indicate that we are now in idle mode - even so deeply
140 in idle mode that we don't get any idle events anymore.
141 this is like wxMSW where an idle event is sent only
142 once each time after the event queue has been completely
143 emptied */
144 g_isIdle = TRUE;
094637f6 145
86fdd27b 146#if (GTK_MINOR_VERSION > 0)
7b90a8f2
RR
147 /* release lock again */
148 GDK_THREADS_LEAVE ();
86fdd27b 149#endif
acfd422a
RR
150
151 return TRUE;
152}
8801832d 153
acfd422a
RR
154void wxapp_install_idle_handler()
155{
223d09f6 156 wxASSERT_MSG( wxTheApp->m_idleTag == 0, wxT("attempt to install idle handler twice") );
7b90a8f2 157
7941ba11
RR
158 /* This routine gets called by all event handlers
159 indicating that the idle is over. It may also
160 get called from other thread for sending events
161 to the main thread (and processing these in
162 idle time). */
163
164#if wxUSE_THREADS
165 if (!wxThread::IsMain())
166 GDK_THREADS_ENTER ();
167#endif
5f12ae5c 168
53a8af59 169 wxTheApp->m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
094637f6 170
acfd422a 171 g_isIdle = FALSE;
7941ba11
RR
172
173#if wxUSE_THREADS
174 if (!wxThread::IsMain())
175 GDK_THREADS_LEAVE ();
176#endif
ff7b1510 177}
c801d85f 178
6b3eb77a 179#if wxUSE_THREADS
b453e1b2 180
b453e1b2 181void wxapp_install_thread_wakeup()
7b90a8f2 182{
b453e1b2 183 if (wxTheApp->m_wakeUpTimerTag) return;
e90c1d2a 184
b453e1b2
RR
185 wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 100, wxapp_wakeup_timerout_callback, (gpointer) NULL );
186}
187
188void wxapp_uninstall_thread_wakeup()
189{
190 if (!wxTheApp->m_wakeUpTimerTag) return;
e90c1d2a 191
7b90a8f2
RR
192 gtk_timeout_remove( wxTheApp->m_wakeUpTimerTag );
193 wxTheApp->m_wakeUpTimerTag = 0;
b453e1b2
RR
194}
195
c4fda16b 196gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
b453e1b2
RR
197{
198 wxapp_uninstall_thread_wakeup();
094637f6 199
86fdd27b 200#if (GTK_MINOR_VERSION > 0)
094637f6 201 // when getting called from GDK's time-out handler
8dbf4589
RR
202 // we are no longer within GDK's grab on the GUI
203 // thread so we must lock it here ourselves
7b90a8f2 204 GDK_THREADS_ENTER ();
86fdd27b 205#endif
094637f6 206
8dbf4589 207 // unblock other threads wishing to do some GUI things
7b90a8f2 208 wxMutexGuiLeave();
094637f6 209
8dbf4589 210 // wake up other threads
7b90a8f2 211 wxUsleep( 1 );
094637f6 212
8dbf4589 213 // block other thread again
7b90a8f2 214 wxMutexGuiEnter();
094637f6 215
86fdd27b 216#if (GTK_MINOR_VERSION > 0)
8dbf4589 217 // release lock again
7b90a8f2 218 GDK_THREADS_LEAVE ();
86fdd27b 219#endif
094637f6 220
b453e1b2 221 wxapp_install_thread_wakeup();
094637f6 222
7b90a8f2
RR
223 return TRUE;
224}
8e193f38 225
c19c1ca9 226#endif // wxUSE_THREADS
7b90a8f2 227
c801d85f
KB
228//-----------------------------------------------------------------------------
229// wxApp
230//-----------------------------------------------------------------------------
231
232IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
233
53010e52
RR
234BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
235 EVT_IDLE(wxApp::OnIdle)
236END_EVENT_TABLE()
237
c801d85f
KB
238wxApp::wxApp()
239{
0d2a2b60 240 wxTheApp = this;
60acb947 241
ec758a20
RR
242 m_topWindow = (wxWindow *) NULL;
243 m_exitOnFrameDelete = TRUE;
60acb947 244
0d2a2b60 245 m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
094637f6 246
6b3eb77a 247#if wxUSE_THREADS
b453e1b2
RR
248 m_wakeUpTimerTag = 0;
249 wxapp_install_thread_wakeup();
6b3eb77a 250#endif
60acb947 251
f6fcbb63 252 m_colorCube = (unsigned char*) NULL;
ff7b1510 253}
c801d85f 254
60acb947 255wxApp::~wxApp()
c801d85f 256{
acfd422a 257 if (m_idleTag) gtk_idle_remove( m_idleTag );
60acb947 258
6b3eb77a 259#if wxUSE_THREADS
b453e1b2 260 wxapp_uninstall_thread_wakeup();
6b3eb77a 261#endif
094637f6 262
f6fcbb63 263 if (m_colorCube) free(m_colorCube);
ff7b1510 264}
c801d85f 265
0d2a2b60 266bool wxApp::OnInitGui()
c801d85f 267{
b134516c
RR
268 GdkVisual *visual = gdk_visual_get_system();
269
094637f6 270 /* on some machines, the default visual is just 256 colours, so
b134516c 271 we make sure we get the best. this can sometimes be wasteful,
7b280524 272 of course, but what do these guys pay $30.000 for? */
b134516c
RR
273/*
274 if (gdk_visual_get_best() != gdk_visual_get_system())
275 {
276 GdkVisual* vis = gdk_visual_get_best();
277 gtk_widget_set_default_visual( vis );
f6fcbb63 278
b134516c
RR
279 GdkColormap *colormap = gdk_colormap_new( vis, FALSE );
280 gtk_widget_set_default_colormap( colormap );
094637f6
VZ
281
282 visual = vis;
b134516c
RR
283 }
284*/
094637f6 285
7b280524 286 /* Nothing to do for 15, 16, 24, 32 bit displays */
f6fcbb63 287 if (visual->depth > 8) return TRUE;
60acb947 288
f6fcbb63 289 /* initialize color cube for 8-bit color reduction dithering */
60acb947 290
f6fcbb63 291 GdkColormap *cmap = gtk_widget_get_default_colormap();
60acb947 292
f6fcbb63
RR
293 m_colorCube = (unsigned char*)malloc(32 * 32 * 32);
294
f03fc89f
VZ
295 for (int r = 0; r < 32; r++)
296 {
8801832d
VZ
297 for (int g = 0; g < 32; g++)
298 {
299 for (int b = 0; b < 32; b++)
300 {
301 int rr = (r << 3) | (r >> 2);
302 int gg = (g << 3) | (g >> 2);
303 int bb = (b << 3) | (b >> 2);
60acb947 304
f03fc89f
VZ
305 int index = -1;
306
f6fcbb63 307 GdkColor *colors = cmap->colors;
ca26177c 308 if (colors)
f03fc89f
VZ
309 {
310 int max = 3 * 65536;
311
312 for (int i = 0; i < cmap->size; i++)
313 {
314 int rdiff = ((rr << 8) - colors[i].red);
315 int gdiff = ((gg << 8) - colors[i].green);
316 int bdiff = ((bb << 8) - colors[i].blue);
317 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
318 if (sum < max)
094637f6 319 {
f03fc89f
VZ
320 index = i; max = sum;
321 }
322 }
f6fcbb63 323 }
094637f6
VZ
324 else
325 {
58c7cd12 326#if (GTK_MINOR_VERSION > 0)
094637f6
VZ
327 /* assume 8-bit true or static colors. this really
328 exists. */
329 GdkVisual* vis = gdk_colormap_get_visual( cmap );
330 index = (r >> (5 - vis->red_prec)) << vis->red_shift;
331 index |= (g >> (5 - vis->green_prec)) << vis->green_shift;
332 index |= (b >> (5 - vis->blue_prec)) << vis->blue_shift;
58c7cd12 333#else
223d09f6 334 wxFAIL_MSG( wxT("Unsupported graphics hardware") );
58c7cd12 335#endif
094637f6 336 }
8801832d
VZ
337 m_colorCube[ (r*1024) + (g*32) + b ] = index;
338 }
339 }
f6fcbb63 340 }
c801d85f 341
bbe0af5b
RR
342 return TRUE;
343}
344
60acb947 345bool wxApp::ProcessIdle()
53010e52 346{
ec758a20
RR
347 wxIdleEvent event;
348 event.SetEventObject( this );
349 ProcessEvent( event );
0cf2cb36 350
ec758a20 351 return event.MoreRequested();
ff7b1510 352}
53010e52
RR
353
354void wxApp::OnIdle( wxIdleEvent &event )
c801d85f 355{
956dbab1 356 static bool s_inOnIdle = FALSE;
53010e52 357
d524867f 358 /* Avoid recursion (via ProcessEvent default case) */
956dbab1 359 if (s_inOnIdle)
ec758a20 360 return;
53010e52 361
956dbab1 362 s_inOnIdle = TRUE;
53010e52 363
7214297d
GL
364 /* Resend in the main thread events which have been prepared in other
365 threads */
366 ProcessPendingEvents();
367
d524867f 368 /* 'Garbage' collection of windows deleted with Close(). */
ec758a20 369 DeletePendingObjects();
53010e52 370
d524867f 371 /* flush the logged messages if any */
88ac883a 372#if wxUSE_LOG
d524867f
RR
373 wxLog *log = wxLog::GetActiveTarget();
374 if (log != NULL && log->HasPendingMessages())
375 log->Flush();
88ac883a 376#endif // wxUSE_LOG
53010e52 377
d524867f 378 /* Send OnIdle events to all windows */
ec758a20 379 bool needMore = SendIdleEvents();
53010e52 380
ec758a20
RR
381 if (needMore)
382 event.RequestMore(TRUE);
53010e52 383
956dbab1 384 s_inOnIdle = FALSE;
ff7b1510 385}
53010e52 386
60acb947 387bool wxApp::SendIdleEvents()
53010e52
RR
388{
389 bool needMore = FALSE;
e0253070 390
e146b8c8 391 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
ec758a20
RR
392 while (node)
393 {
e146b8c8 394 wxWindow* win = node->GetData();
f3855ef0 395 if (SendIdleEvents(win))
53010e52 396 needMore = TRUE;
e146b8c8 397 node = node->GetNext();
ec758a20 398 }
e146b8c8 399
53010e52 400 return needMore;
ff7b1510 401}
53010e52
RR
402
403bool wxApp::SendIdleEvents( wxWindow* win )
404{
405 bool needMore = FALSE;
406
8bbe427f
VZ
407 wxIdleEvent event;
408 event.SetEventObject(win);
60acb947 409
8bbe427f 410 win->ProcessEvent(event);
53010e52 411
e70f5e13 412 win->OnInternalIdle();
e90c1d2a 413
53010e52
RR
414 if (event.MoreRequested())
415 needMore = TRUE;
416
8bbe427f
VZ
417 wxNode* node = win->GetChildren().First();
418 while (node)
419 {
420 wxWindow* win = (wxWindow*) node->Data();
421 if (SendIdleEvents(win))
53010e52
RR
422 needMore = TRUE;
423
8bbe427f
VZ
424 node = node->Next();
425 }
53010e52 426 return needMore ;
ff7b1510 427}
c801d85f 428
60acb947 429int wxApp::MainLoop()
c801d85f 430{
ec758a20
RR
431 gtk_main();
432 return 0;
ff7b1510 433}
c801d85f 434
60acb947 435void wxApp::ExitMainLoop()
c801d85f 436{
7ec2881a
RR
437 if (gtk_main_level() > 0)
438 gtk_main_quit();
ff7b1510 439}
c801d85f 440
60acb947 441bool wxApp::Initialized()
c801d85f 442{
ec758a20 443 return m_initialized;
ff7b1510 444}
c801d85f 445
60acb947 446bool wxApp::Pending()
c801d85f 447{
acfd422a 448 return (gtk_events_pending() > 0);
ff7b1510 449}
c801d85f 450
60acb947 451void wxApp::Dispatch()
c801d85f 452{
8801832d 453 gtk_main_iteration();
ff7b1510 454}
c801d85f 455
60acb947 456void wxApp::DeletePendingObjects()
c801d85f 457{
ec758a20
RR
458 wxNode *node = wxPendingDelete.First();
459 while (node)
460 {
461 wxObject *obj = (wxObject *)node->Data();
0cf2cb36 462
ec758a20 463 delete obj;
c801d85f 464
f03fc89f
VZ
465 if (wxPendingDelete.Find(obj))
466 delete node;
c801d85f 467
ec758a20
RR
468 node = wxPendingDelete.First();
469 }
ff7b1510 470}
c801d85f 471
60acb947 472bool wxApp::Initialize()
c801d85f 473{
9cc7a35d 474 wxBuffer = new wxChar[BUFSIZ + 512];
0d2a2b60
RR
475
476 wxClassInfo::InitializeClasses();
60acb947 477
0d2a2b60 478 wxSystemSettings::Init();
60acb947 479
4d3a259a
GL
480 // GL: I'm annoyed ... I don't know where to put this and I don't want to
481 // create a module for that as it's part of the core.
482#if wxUSE_THREADS
483 wxPendingEvents = new wxList();
484 wxPendingEventsLocker = new wxCriticalSection();
485#endif
486
36b3b54a 487/*
0d2a2b60
RR
488 wxTheFontNameDirectory = new wxFontNameDirectory;
489 wxTheFontNameDirectory->Initialize();
36b3b54a 490*/
c801d85f 491
0d2a2b60
RR
492 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
493 wxTheColourDatabase->Initialize();
a3622daa 494
0d2a2b60
RR
495 wxInitializeStockLists();
496 wxInitializeStockObjects();
c801d85f 497
0d2a2b60
RR
498 wxModule::RegisterModules();
499 if (!wxModule::InitializeModules()) return FALSE;
60acb947 500
0d2a2b60 501 return TRUE;
ff7b1510 502}
c801d85f 503
60acb947 504void wxApp::CleanUp()
c801d85f 505{
0d2a2b60 506 wxModule::CleanUpModules();
0cf2cb36 507
60acb947
VZ
508 if (wxTheColourDatabase)
509 delete wxTheColourDatabase;
0d2a2b60 510 wxTheColourDatabase = (wxColourDatabase*) NULL;
60acb947 511
36b3b54a 512/*
0d2a2b60
RR
513 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
514 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
36b3b54a 515*/
60acb947 516
0d2a2b60
RR
517 wxDeleteStockObjects();
518
ec758a20 519 wxDeleteStockLists();
a3622daa 520
0d2a2b60
RR
521 delete wxTheApp;
522 wxTheApp = (wxApp*) NULL;
523
4d3a259a
GL
524 // GL: I'm annoyed ... I don't know where to put this and I don't want to
525 // create a module for that as it's part of the core.
526#if wxUSE_THREADS
527 delete wxPendingEvents;
528 delete wxPendingEventsLocker;
529#endif
530
3e61c765 531 wxSystemSettings::Done();
60acb947 532
3e61c765
RR
533 delete[] wxBuffer;
534
535 wxClassInfo::CleanUpClasses();
60acb947
VZ
536
537 // check for memory leaks
0d2a2b60
RR
538#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
539 if (wxDebugContext::CountObjectsLeft() > 0)
540 {
223d09f6 541 wxLogDebug(wxT("There were memory leaks.\n"));
0d2a2b60
RR
542 wxDebugContext::Dump();
543 wxDebugContext::PrintStatistics();
544 }
8801832d 545#endif // Debug
0d2a2b60 546
88ac883a 547#if wxUSE_LOG
60acb947 548 // do this as the very last thing because everything else can log messages
0d2a2b60 549 wxLog::DontCreateOnDemand();
60acb947 550
0d2a2b60 551 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
60acb947
VZ
552 if (oldLog)
553 delete oldLog;
88ac883a 554#endif // wxUSE_LOG
c19c1ca9 555}
c801d85f
KB
556
557//-----------------------------------------------------------------------------
558// wxEntry
559//-----------------------------------------------------------------------------
560
561int wxEntry( int argc, char *argv[] )
562{
0d2a2b60 563 gtk_set_locale();
c801d85f 564
fd9811b1 565#if wxUSE_WCHAR_T
dcf924a3 566 if (!wxOKlibc()) wxConvCurrent = &wxConvLocal;
fd9811b1
RR
567#else
568 if (!wxOKlibc()) wxConvCurrent = (wxMBConv*) NULL;
569#endif
002f4218 570
0d2a2b60 571 gtk_init( &argc, &argv );
0cf2cb36 572
f0492f7d 573 wxSetDetectableAutoRepeat( TRUE );
094637f6 574
60acb947
VZ
575 if (!wxApp::Initialize())
576 return -1;
0cf2cb36 577
ec758a20 578 if (!wxTheApp)
c801d85f 579 {
60acb947 580 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
223d09f6 581 wxT("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
0cf2cb36 582
ec758a20 583 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
0cf2cb36 584
ec758a20 585 wxObject *test_app = app_ini();
0cf2cb36 586
ec758a20
RR
587 wxTheApp = (wxApp*) test_app;
588 }
0cf2cb36 589
223d09f6 590 wxCHECK_MSG( wxTheApp, -1, wxT("wxWindows error: no application object") );
c801d85f 591
ec758a20 592 wxTheApp->argc = argc;
6de92826
OK
593#if wxUSE_UNICODE
594 wxTheApp->argv = new wxChar*[argc+1];
595 int mb_argc = 0;
596 while (mb_argc < argc) {
597 wxTheApp->argv[mb_argc] = wxStrdup(wxConvLibc.cMB2WX(argv[mb_argc]));
598 mb_argc++;
599 }
600 wxTheApp->argv[mb_argc] = (wxChar *)NULL;
601#else
ec758a20 602 wxTheApp->argv = argv;
6de92826 603#endif
0cf2cb36 604
8801832d 605 wxString name(wxFileNameFromPath(argv[0]));
ec758a20
RR
606 wxStripExtension( name );
607 wxTheApp->SetAppName( name );
e0253070 608
0151c3eb
VZ
609 int retValue = 0;
610
611 if ( !wxTheApp->OnInitGui() )
612 retValue = -1;
c801d85f 613
8801832d
VZ
614 // Here frames insert themselves automatically into wxTopLevelWindows by
615 // getting created in OnInit().
0151c3eb
VZ
616 if ( retValue == 0 )
617 {
618 if ( !wxTheApp->OnInit() )
619 retValue = -1;
620 }
0cf2cb36 621
0151c3eb
VZ
622 if ( retValue == 0 )
623 {
cfb50f14 624 /* delete pending toplevel windows (typically a single
094637f6
VZ
625 dialog) so that, if there isn't any left, we don't
626 call OnRun() */
cfb50f14 627 wxTheApp->DeletePendingObjects();
094637f6 628
0151c3eb 629 wxTheApp->m_initialized = wxTopLevelWindows.GetCount() != 0;
0cf2cb36 630
0151c3eb 631 if (wxTheApp->Initialized())
094637f6 632 {
0151c3eb 633 retValue = wxTheApp->OnRun();
0cf2cb36 634
cfb50f14
RR
635 wxWindow *topWindow = wxTheApp->GetTopWindow();
636 if (topWindow)
0151c3eb 637 {
cfb50f14
RR
638 /* Forcibly delete the window. */
639 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
640 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
641 {
642 topWindow->Close( TRUE );
643 wxTheApp->DeletePendingObjects();
644 }
645 else
646 {
647 delete topWindow;
648 wxTheApp->SetTopWindow( (wxWindow*) NULL );
649 }
094637f6 650 }
cfb50f14 651 wxTheApp->OnExit();
0d2a2b60 652 }
0151c3eb 653 }
0cf2cb36 654
88ac883a 655#if wxUSE_LOG
60acb947 656 // flush the logged messages if any
0d2a2b60
RR
657 wxLog *log = wxLog::GetActiveTarget();
658 if (log != NULL && log->HasPendingMessages())
659 log->Flush();
660
60acb947
VZ
661 // continuing to use user defined log target is unsafe from now on because
662 // some resources may be already unavailable, so replace it by something
663 // more safe
664 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
665 if ( oldlog )
666 delete oldlog;
88ac883a 667#endif // wxUSE_LOG
60acb947 668
0d2a2b60 669 wxApp::CleanUp();
184b5d99 670
ec758a20 671 return retValue;
ff7b1510 672}
1a56f55c 673
094637f6
VZ
674#include "wx/gtk/info.xpm"
675#include "wx/gtk/error.xpm"
676#include "wx/gtk/question.xpm"
677#include "wx/gtk/warning.xpm"
678
ebea0891
KB
679wxIcon
680wxApp::GetStdIcon(int which) const
681{
094637f6
VZ
682 switch(which)
683 {
684 case wxICON_INFORMATION:
685 return wxIcon(info_xpm);
686
687 case wxICON_QUESTION:
688 return wxIcon(question_xpm);
689
690 case wxICON_EXCLAMATION:
691 return wxIcon(warning_xpm);
692
693 default:
223d09f6 694 wxFAIL_MSG(wxT("requested non existent standard icon"));
094637f6
VZ
695 // still fall through
696
697 case wxICON_HAND:
698 return wxIcon(error_xpm);
699 }
ebea0891 700}