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