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