]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/app.cpp
Add some "USE" defs that were missing.
[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
0d2a2b60
RR
479 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
480 wxTheColourDatabase->Initialize();
a3622daa 481
0d2a2b60
RR
482 wxInitializeStockLists();
483 wxInitializeStockObjects();
c801d85f 484
4a0c68a7
RR
485#if wxUSE_WX_RESOURCES
486 wxInitializeResourceSystem();
487#endif
488
0d2a2b60
RR
489 wxModule::RegisterModules();
490 if (!wxModule::InitializeModules()) return FALSE;
60acb947 491
0d2a2b60 492 return TRUE;
ff7b1510 493}
c801d85f 494
60acb947 495void wxApp::CleanUp()
c801d85f 496{
0d2a2b60 497 wxModule::CleanUpModules();
0cf2cb36 498
4a0c68a7
RR
499#if wxUSE_WX_RESOURCES
500 wxCleanUpResourceSystem();
501#endif
502
60acb947
VZ
503 if (wxTheColourDatabase)
504 delete wxTheColourDatabase;
4a0c68a7 505
0d2a2b60 506 wxTheColourDatabase = (wxColourDatabase*) NULL;
60acb947 507
0d2a2b60
RR
508 wxDeleteStockObjects();
509
ec758a20 510 wxDeleteStockLists();
a3622daa 511
0d2a2b60
RR
512 delete wxTheApp;
513 wxTheApp = (wxApp*) NULL;
514
4d3a259a
GL
515 // GL: I'm annoyed ... I don't know where to put this and I don't want to
516 // create a module for that as it's part of the core.
517#if wxUSE_THREADS
518 delete wxPendingEvents;
519 delete wxPendingEventsLocker;
520#endif
521
3e61c765 522 wxSystemSettings::Done();
60acb947 523
3e61c765
RR
524 delete[] wxBuffer;
525
526 wxClassInfo::CleanUpClasses();
60acb947
VZ
527
528 // check for memory leaks
0d2a2b60
RR
529#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
530 if (wxDebugContext::CountObjectsLeft() > 0)
531 {
223d09f6 532 wxLogDebug(wxT("There were memory leaks.\n"));
0d2a2b60
RR
533 wxDebugContext::Dump();
534 wxDebugContext::PrintStatistics();
535 }
8801832d 536#endif // Debug
0d2a2b60 537
88ac883a 538#if wxUSE_LOG
60acb947 539 // do this as the very last thing because everything else can log messages
0d2a2b60 540 wxLog::DontCreateOnDemand();
60acb947 541
0d2a2b60 542 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
60acb947
VZ
543 if (oldLog)
544 delete oldLog;
88ac883a 545#endif // wxUSE_LOG
c19c1ca9 546}
c801d85f
KB
547
548//-----------------------------------------------------------------------------
549// wxEntry
550//-----------------------------------------------------------------------------
551
552int wxEntry( int argc, char *argv[] )
553{
924ef850
RR
554#if wxUSE_THREADS
555 g_thread_init(NULL);
556#endif
557
0d2a2b60 558 gtk_set_locale();
c801d85f 559
fd9811b1 560#if wxUSE_WCHAR_T
dcf924a3 561 if (!wxOKlibc()) wxConvCurrent = &wxConvLocal;
fd9811b1
RR
562#else
563 if (!wxOKlibc()) wxConvCurrent = (wxMBConv*) NULL;
564#endif
002f4218 565
924ef850
RR
566 gdk_threads_enter();
567
0d2a2b60 568 gtk_init( &argc, &argv );
0cf2cb36 569
f0492f7d 570 wxSetDetectableAutoRepeat( TRUE );
094637f6 571
60acb947 572 if (!wxApp::Initialize())
924ef850
RR
573 {
574 gdk_threads_leave();
60acb947 575 return -1;
924ef850 576 }
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;
924ef850
RR
596 while (mb_argc < argc)
597 {
598 wxTheApp->argv[mb_argc] = wxStrdup(wxConvLibc.cMB2WX(argv[mb_argc]));
599 mb_argc++;
6de92826
OK
600 }
601 wxTheApp->argv[mb_argc] = (wxChar *)NULL;
602#else
ec758a20 603 wxTheApp->argv = argv;
6de92826 604#endif
0cf2cb36 605
8801832d 606 wxString name(wxFileNameFromPath(argv[0]));
ec758a20
RR
607 wxStripExtension( name );
608 wxTheApp->SetAppName( name );
e0253070 609
0151c3eb
VZ
610 int retValue = 0;
611
612 if ( !wxTheApp->OnInitGui() )
613 retValue = -1;
c801d85f 614
8801832d
VZ
615 // Here frames insert themselves automatically into wxTopLevelWindows by
616 // getting created in OnInit().
0151c3eb
VZ
617 if ( retValue == 0 )
618 {
619 if ( !wxTheApp->OnInit() )
620 retValue = -1;
621 }
0cf2cb36 622
0151c3eb
VZ
623 if ( retValue == 0 )
624 {
cfb50f14 625 /* delete pending toplevel windows (typically a single
094637f6
VZ
626 dialog) so that, if there isn't any left, we don't
627 call OnRun() */
cfb50f14 628 wxTheApp->DeletePendingObjects();
094637f6 629
0151c3eb 630 wxTheApp->m_initialized = wxTopLevelWindows.GetCount() != 0;
0cf2cb36 631
0151c3eb 632 if (wxTheApp->Initialized())
094637f6 633 {
0151c3eb 634 retValue = wxTheApp->OnRun();
0cf2cb36 635
cfb50f14
RR
636 wxWindow *topWindow = wxTheApp->GetTopWindow();
637 if (topWindow)
0151c3eb 638 {
cfb50f14
RR
639 /* Forcibly delete the window. */
640 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
641 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
642 {
643 topWindow->Close( TRUE );
644 wxTheApp->DeletePendingObjects();
645 }
646 else
647 {
648 delete topWindow;
649 wxTheApp->SetTopWindow( (wxWindow*) NULL );
650 }
094637f6 651 }
cfb50f14 652 wxTheApp->OnExit();
0d2a2b60 653 }
0151c3eb 654 }
0cf2cb36 655
88ac883a 656#if wxUSE_LOG
60acb947 657 // flush the logged messages if any
0d2a2b60
RR
658 wxLog *log = wxLog::GetActiveTarget();
659 if (log != NULL && log->HasPendingMessages())
660 log->Flush();
661
60acb947
VZ
662 // continuing to use user defined log target is unsafe from now on because
663 // some resources may be already unavailable, so replace it by something
664 // more safe
665 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
666 if ( oldlog )
667 delete oldlog;
88ac883a 668#endif // wxUSE_LOG
60acb947 669
0d2a2b60 670 wxApp::CleanUp();
184b5d99 671
924ef850
RR
672 gdk_threads_leave();
673
ec758a20 674 return retValue;
ff7b1510 675}
1a56f55c 676
094637f6
VZ
677#include "wx/gtk/info.xpm"
678#include "wx/gtk/error.xpm"
679#include "wx/gtk/question.xpm"
680#include "wx/gtk/warning.xpm"
681
ebea0891
KB
682wxIcon
683wxApp::GetStdIcon(int which) const
684{
094637f6
VZ
685 switch(which)
686 {
687 case wxICON_INFORMATION:
688 return wxIcon(info_xpm);
689
690 case wxICON_QUESTION:
691 return wxIcon(question_xpm);
692
693 case wxICON_EXCLAMATION:
694 return wxIcon(warning_xpm);
695
696 default:
223d09f6 697 wxFAIL_MSG(wxT("requested non existent standard icon"));
094637f6
VZ
698 // still fall through
699
700 case wxICON_HAND:
701 return wxIcon(error_xpm);
702 }
ebea0891 703}