]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/app.cpp
now we can even edit again
[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
f3855ef0 31#include "wx/thread.h"
afb74891 32
c801d85f
KB
33#include "unistd.h"
34
afb74891
VZ
35#include <glib.h>
36#include <gdk/gdk.h>
37#include <gtk/gtk.h>
24178e4a 38
83624f79
RR
39#include "wx/gtk/win_gtk.h"
40
c801d85f
KB
41//-----------------------------------------------------------------------------
42// global data
43//-----------------------------------------------------------------------------
44
c67daf87 45wxApp *wxTheApp = (wxApp *) NULL;
c801d85f
KB
46wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL;
47
7214297d 48#if wxUSE_THREADS
4d3a259a
GL
49extern wxList *wxPendingEvents;
50extern wxCriticalSection *wxPendingEventsLocker;
7214297d 51#endif
a3622daa 52extern wxResourceCache *wxTheResourceCache;
acfd422a 53extern bool g_isIdle;
c801d85f 54
01111366
RR
55unsigned char g_palette[64*3] =
56{
57 0x0, 0x0, 0x0,
58 0xff, 0xff, 0xff,
59 0xff, 0x0, 0x0,
60 0xff, 0xff, 0x0,
61 0x0, 0xff, 0x0,
62 0x0, 0x0, 0xff,
63 0x0, 0xff, 0xff,
64 0x99, 0x99, 0x99,
65 0xff, 0x88, 0x0,
66 0x88, 0x0, 0x0,
67 0x0, 0x88, 0x88,
68 0x88, 0x88, 0x0,
69 0xff, 0xcc, 0x97,
70 0xbb, 0xbb, 0xbb,
71 0x9f, 0x6b, 0x42,
72 0x55, 0x55, 0x55,
73 0xdd, 0xdd, 0xdd,
74 0x77, 0x77, 0x77,
75 0x33, 0x33, 0x33,
76 0xcc, 0x0, 0x0,
77 0xff, 0x44, 0x0,
78 0xff, 0xcc, 0x0,
79 0xcc, 0xcc, 0x0,
80 0x60, 0x60, 0x0,
81 0x0, 0x43, 0x0,
82 0x0, 0x7f, 0x0,
83 0x0, 0xcc, 0x0,
84 0x0, 0x44, 0x44,
85 0x0, 0x0, 0x44,
86 0x0, 0x0, 0x88,
87 0xef, 0xb1, 0x7b,
88 0xdf, 0x98, 0x5f,
89 0xbf, 0x87, 0x56,
90 0x7f, 0x57, 0x26,
91 0x5f, 0x39, 0xc,
92 0x3f, 0x1c, 0x0,
93 0x21, 0x0, 0x0,
94 0x0, 0x43, 0x87,
95 0x2d, 0x70, 0xaf,
96 0x5a, 0x9e, 0xd7,
97 0x87, 0xcc, 0xff,
98 0xff, 0xe0, 0xba,
99 0x21, 0x43, 0xf,
100 0x3d, 0x5d, 0x25,
101 0x59, 0x78, 0x3a,
102 0x75, 0x93, 0x4f,
103 0x91, 0xae, 0x64,
104 0xad, 0xc8, 0x7a,
e0253070 105 0xf0, 0xa8, 0xef,
01111366
RR
106 0xd0, 0x88, 0xd0,
107 0xaf, 0x66, 0xaf,
108 0x8e, 0x44, 0x8e,
109 0x6d, 0x22, 0x6d,
e0253070 110 0x4b, 0x0, 0x4b,
01111366
RR
111 0xff, 0xc0, 0xbc,
112 0xff, 0x93, 0x91,
113 0xff, 0x66, 0x67,
114 0xd8, 0xf2, 0xbf,
115 0xff, 0xc9, 0x68,
116 0xff, 0x96, 0x67,
117 0xa5, 0x60, 0xff,
118 0x51, 0xff, 0x99,
119 0x3f, 0xa5, 0x63,
120 0x98, 0x90, 0x67
121};
122
c801d85f
KB
123//-----------------------------------------------------------------------------
124// local functions
125//-----------------------------------------------------------------------------
126
127extern void wxFlushResources(void);
128
129//-----------------------------------------------------------------------------
130// global functions
131//-----------------------------------------------------------------------------
132
60acb947 133void wxExit()
c801d85f 134{
ec758a20 135 gtk_main_quit();
ff7b1510 136}
c801d85f 137
acfd422a 138/* forward declaration */
53a8af59
KB
139gint wxapp_idle_callback( gpointer WXUNUSED(data) );
140
60acb947 141bool wxYield()
c801d85f 142{
5f12ae5c
VZ
143 // it's necessary to call ProcessIdle() to update the frames sizes which
144 // might have been changed (it also will update other things set from
145 // OnUpdateUI() which is a nice (and desired) side effect)
e146b8c8 146 for ( wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
5f12ae5c
VZ
147 node;
148 node = node->GetNext() )
149 {
e146b8c8 150 wxWindow *win = node->GetData();
5f12ae5c
VZ
151 win->OnInternalIdle();
152 }
153
acfd422a
RR
154 if (wxTheApp->m_idleTag)
155 {
156 /* We need to temporarily remove idle callbacks or the loop will
157 never finish. */
158 gtk_idle_remove( wxTheApp->m_idleTag );
159 wxTheApp->m_idleTag = 0;
160
161 while (gtk_events_pending())
162 gtk_main_iteration();
163
164 /* re-add idle handler */
165 wxTheApp->m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
166 }
167 else
168 {
169 while (gtk_events_pending())
170 gtk_main_iteration();
171 }
172
173 return TRUE;
174}
175
176gint wxapp_idle_callback( gpointer WXUNUSED(data) )
177{
178 if (!wxTheApp) return TRUE;
179
180 /* sent idle event to all who request them */
181 while (wxTheApp->ProcessIdle()) { }
182
183 /* we don't want any more idle events until the next event is
184 sent to wxGTK */
53a8af59 185 gtk_idle_remove( wxTheApp->m_idleTag );
acfd422a
RR
186 wxTheApp->m_idleTag = 0;
187
188 /* indicate that we are now in idle mode - even so deeply
189 in idle mode that we don't get any idle events anymore.
190 this is like wxMSW where an idle event is sent only
191 once each time after the event queue has been completely
192 emptied */
193 g_isIdle = TRUE;
194
b9a535f5
RR
195 /* wake up other threads */
196 wxMutexGuiLeave();
197 wxUsleep(0);
198 wxMutexGuiEnter();
acfd422a
RR
199
200 return TRUE;
201}
8801832d 202
acfd422a
RR
203void wxapp_install_idle_handler()
204{
205 /* this routine gets called by all event handlers
206 indicating that the idle is over. */
5f12ae5c 207
53a8af59 208 wxTheApp->m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
acfd422a
RR
209
210 g_isIdle = FALSE;
ff7b1510 211}
c801d85f
KB
212
213//-----------------------------------------------------------------------------
214// wxApp
215//-----------------------------------------------------------------------------
216
217IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
218
53010e52
RR
219BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
220 EVT_IDLE(wxApp::OnIdle)
221END_EVENT_TABLE()
222
c801d85f
KB
223wxApp::wxApp()
224{
0d2a2b60 225 wxTheApp = this;
60acb947 226
ec758a20
RR
227 m_topWindow = (wxWindow *) NULL;
228 m_exitOnFrameDelete = TRUE;
60acb947 229
0d2a2b60 230 m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
60acb947 231
f6fcbb63 232 m_colorCube = (unsigned char*) NULL;
ff7b1510 233}
c801d85f 234
60acb947 235wxApp::~wxApp()
c801d85f 236{
acfd422a 237 if (m_idleTag) gtk_idle_remove( m_idleTag );
60acb947 238
f6fcbb63 239 if (m_colorCube) free(m_colorCube);
ff7b1510 240}
c801d85f 241
0d2a2b60 242bool wxApp::OnInitGui()
c801d85f 243{
f6fcbb63
RR
244 /* Nothing to do for 15, 16, 24, 32 bit displays */
245
246 GdkVisual *visual = gdk_visual_get_system();
247 if (visual->depth > 8) return TRUE;
60acb947 248
0d2a2b60
RR
249 /* this initiates the standard palette as defined by GdkImlib
250 in the GNOME libraries. it ensures that all GNOME applications
251 use the same 64 colormap entries on 8-bit displays so you
252 can use several rather graphics-heavy applications at the
253 same time.
8801832d 254 NOTE: this doesn't really seem to work this way... */
bbe0af5b 255
0d2a2b60
RR
256 /*
257 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
bbe0af5b 258
0d2a2b60
RR
259 for (int i = 0; i < 64; i++)
260 {
261 GdkColor col;
262 col.red = g_palette[i*3 + 0] << 8;
263 col.green = g_palette[i*3 + 1] << 8;
264 col.blue = g_palette[i*3 + 2] << 8;
265 col.pixel = 0;
266
267 gdk_color_alloc( cmap, &col );
268 }
60acb947 269
0d2a2b60
RR
270 gtk_widget_set_default_colormap( cmap );
271 */
60acb947 272
f6fcbb63 273 /* initialize color cube for 8-bit color reduction dithering */
60acb947 274
f6fcbb63 275 GdkColormap *cmap = gtk_widget_get_default_colormap();
60acb947 276
f6fcbb63
RR
277 m_colorCube = (unsigned char*)malloc(32 * 32 * 32);
278
f03fc89f
VZ
279 for (int r = 0; r < 32; r++)
280 {
8801832d
VZ
281 for (int g = 0; g < 32; g++)
282 {
283 for (int b = 0; b < 32; b++)
284 {
285 int rr = (r << 3) | (r >> 2);
286 int gg = (g << 3) | (g >> 2);
287 int bb = (b << 3) | (b >> 2);
60acb947 288
f03fc89f
VZ
289 int index = -1;
290
f6fcbb63 291 GdkColor *colors = cmap->colors;
f03fc89f
VZ
292 if(colors)
293 {
294 int max = 3 * 65536;
295
296 for (int i = 0; i < cmap->size; i++)
297 {
298 int rdiff = ((rr << 8) - colors[i].red);
299 int gdiff = ((gg << 8) - colors[i].green);
300 int bdiff = ((bb << 8) - colors[i].blue);
301 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
302 if (sum < max)
303 {
304 index = i; max = sum;
305 }
306 }
f6fcbb63 307 }
f03fc89f 308
8801832d
VZ
309 m_colorCube[ (r*1024) + (g*32) + b ] = index;
310 }
311 }
f6fcbb63 312 }
c801d85f 313
bbe0af5b
RR
314 return TRUE;
315}
316
60acb947 317bool wxApp::ProcessIdle()
53010e52 318{
ec758a20
RR
319 wxIdleEvent event;
320 event.SetEventObject( this );
321 ProcessEvent( event );
0cf2cb36 322
ec758a20 323 return event.MoreRequested();
ff7b1510 324}
53010e52
RR
325
326void wxApp::OnIdle( wxIdleEvent &event )
c801d85f 327{
ec758a20 328 static bool inOnIdle = FALSE;
53010e52 329
d524867f 330 /* Avoid recursion (via ProcessEvent default case) */
ec758a20
RR
331 if (inOnIdle)
332 return;
53010e52 333
ec758a20 334 inOnIdle = TRUE;
53010e52 335
d345e841 336#if wxUSE_THREADS
7214297d
GL
337 /* Resend in the main thread events which have been prepared in other
338 threads */
339 ProcessPendingEvents();
d345e841 340#endif
7214297d 341
d524867f 342 /* 'Garbage' collection of windows deleted with Close(). */
ec758a20 343 DeletePendingObjects();
53010e52 344
d524867f
RR
345 /* flush the logged messages if any */
346 wxLog *log = wxLog::GetActiveTarget();
347 if (log != NULL && log->HasPendingMessages())
348 log->Flush();
53010e52 349
d524867f 350 /* Send OnIdle events to all windows */
ec758a20 351 bool needMore = SendIdleEvents();
53010e52 352
ec758a20
RR
353 if (needMore)
354 event.RequestMore(TRUE);
53010e52 355
ec758a20 356 inOnIdle = FALSE;
ff7b1510 357}
53010e52 358
60acb947 359bool wxApp::SendIdleEvents()
53010e52
RR
360{
361 bool needMore = FALSE;
e0253070 362
e146b8c8 363 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
ec758a20
RR
364 while (node)
365 {
e146b8c8 366 wxWindow* win = node->GetData();
f3855ef0 367 if (SendIdleEvents(win))
53010e52 368 needMore = TRUE;
e146b8c8 369 node = node->GetNext();
ec758a20 370 }
e146b8c8 371
53010e52 372 return needMore;
ff7b1510 373}
53010e52
RR
374
375bool wxApp::SendIdleEvents( wxWindow* win )
376{
377 bool needMore = FALSE;
378
8bbe427f
VZ
379 wxIdleEvent event;
380 event.SetEventObject(win);
60acb947 381
9390a202 382 win->OnInternalIdle();
60acb947 383
8bbe427f 384 win->ProcessEvent(event);
53010e52
RR
385
386 if (event.MoreRequested())
387 needMore = TRUE;
388
8bbe427f
VZ
389 wxNode* node = win->GetChildren().First();
390 while (node)
391 {
392 wxWindow* win = (wxWindow*) node->Data();
393 if (SendIdleEvents(win))
53010e52
RR
394 needMore = TRUE;
395
8bbe427f
VZ
396 node = node->Next();
397 }
53010e52 398 return needMore ;
ff7b1510 399}
c801d85f 400
60acb947 401int wxApp::MainLoop()
c801d85f 402{
ec758a20
RR
403 gtk_main();
404 return 0;
ff7b1510 405}
c801d85f 406
60acb947 407void wxApp::ExitMainLoop()
c801d85f 408{
ec758a20 409 gtk_main_quit();
ff7b1510 410}
c801d85f 411
60acb947 412bool wxApp::Initialized()
c801d85f 413{
ec758a20 414 return m_initialized;
ff7b1510 415}
c801d85f 416
60acb947 417bool wxApp::Pending()
c801d85f 418{
acfd422a 419 return (gtk_events_pending() > 0);
ff7b1510 420}
c801d85f 421
60acb947 422void wxApp::Dispatch()
c801d85f 423{
8801832d 424 gtk_main_iteration();
ff7b1510 425}
c801d85f 426
7214297d
GL
427#if wxUSE_THREADS
428void wxApp::ProcessPendingEvents()
429{
4d3a259a
GL
430 wxNode *node = wxPendingEvents->First();
431 wxCriticalSectionLocker locker(*wxPendingEventsLocker);
7214297d
GL
432
433 while (node)
434 {
435 wxEvtHandler *handler = (wxEvtHandler *)node->Data();
436
437 handler->ProcessPendingEvents();
e146b8c8 438
7214297d
GL
439 delete node;
440
4d3a259a 441 node = wxPendingEvents->First();
7214297d
GL
442 }
443}
8801832d 444#endif // wxUSE_THREADS
7214297d 445
60acb947 446void wxApp::DeletePendingObjects()
c801d85f 447{
ec758a20
RR
448 wxNode *node = wxPendingDelete.First();
449 while (node)
450 {
451 wxObject *obj = (wxObject *)node->Data();
0cf2cb36 452
ec758a20 453 delete obj;
c801d85f 454
f03fc89f
VZ
455 if (wxPendingDelete.Find(obj))
456 delete node;
c801d85f 457
ec758a20
RR
458 node = wxPendingDelete.First();
459 }
ff7b1510 460}
c801d85f 461
60acb947 462wxWindow *wxApp::GetTopWindow()
c801d85f 463{
e146b8c8
VZ
464 if (m_topWindow)
465 return m_topWindow;
466 else if (wxTopLevelWindows.GetCount() > 0)
467 return wxTopLevelWindows.GetFirst()->GetData();
468 else
469 return NULL;
ff7b1510 470}
c801d85f
KB
471
472void wxApp::SetTopWindow( wxWindow *win )
473{
ec758a20 474 m_topWindow = win;
ff7b1510 475}
c801d85f 476
60acb947 477bool wxApp::Initialize()
c801d85f 478{
9cc7a35d 479 wxBuffer = new wxChar[BUFSIZ + 512];
0d2a2b60
RR
480
481 wxClassInfo::InitializeClasses();
60acb947 482
0d2a2b60 483 wxSystemSettings::Init();
60acb947 484
4d3a259a
GL
485 // GL: I'm annoyed ... I don't know where to put this and I don't want to
486 // create a module for that as it's part of the core.
487#if wxUSE_THREADS
488 wxPendingEvents = new wxList();
489 wxPendingEventsLocker = new wxCriticalSection();
490#endif
491
36b3b54a 492/*
0d2a2b60
RR
493 wxTheFontNameDirectory = new wxFontNameDirectory;
494 wxTheFontNameDirectory->Initialize();
36b3b54a 495*/
c801d85f 496
0d2a2b60
RR
497 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
498 wxTheColourDatabase->Initialize();
a3622daa 499
0d2a2b60
RR
500 wxInitializeStockLists();
501 wxInitializeStockObjects();
c801d85f 502
06cfab17 503#if wxUSE_WX_RESOURCES
0d2a2b60 504 wxTheResourceCache = new wxResourceCache( wxKEY_STRING );
60acb947 505
0d2a2b60 506 wxInitializeResourceSystem();
f5abe911 507#endif
0cf2cb36 508
0d2a2b60 509 wxImage::InitStandardHandlers();
e0253070 510
0d2a2b60
RR
511 /* no global cursor under X
512 g_globalCursor = new wxCursor; */
60acb947 513
0d2a2b60
RR
514 wxModule::RegisterModules();
515 if (!wxModule::InitializeModules()) return FALSE;
60acb947 516
0d2a2b60 517 return TRUE;
ff7b1510 518}
c801d85f 519
60acb947 520void wxApp::CleanUp()
c801d85f 521{
0d2a2b60 522 wxModule::CleanUpModules();
0cf2cb36 523
06cfab17 524#if wxUSE_WX_RESOURCES
ec758a20 525 wxFlushResources();
a3622daa 526
60acb947
VZ
527 if (wxTheResourceCache)
528 delete wxTheResourceCache;
bbe0af5b 529 wxTheResourceCache = (wxResourceCache*) NULL;
60acb947 530
f5abe911
RR
531 wxCleanUpResourceSystem();
532#endif
a3622daa 533
60acb947
VZ
534 if (wxTheColourDatabase)
535 delete wxTheColourDatabase;
0d2a2b60 536 wxTheColourDatabase = (wxColourDatabase*) NULL;
60acb947 537
36b3b54a 538/*
0d2a2b60
RR
539 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
540 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
36b3b54a 541*/
60acb947 542
0d2a2b60
RR
543 wxDeleteStockObjects();
544
ec758a20 545 wxDeleteStockLists();
a3622daa 546
ec758a20 547 wxImage::CleanUpHandlers();
0cf2cb36 548
0d2a2b60
RR
549 delete wxTheApp;
550 wxTheApp = (wxApp*) NULL;
551
4d3a259a
GL
552 // GL: I'm annoyed ... I don't know where to put this and I don't want to
553 // create a module for that as it's part of the core.
554#if wxUSE_THREADS
555 delete wxPendingEvents;
556 delete wxPendingEventsLocker;
557#endif
558
3e61c765 559 wxSystemSettings::Done();
60acb947 560
3e61c765
RR
561 delete[] wxBuffer;
562
563 wxClassInfo::CleanUpClasses();
60acb947
VZ
564
565 // check for memory leaks
0d2a2b60
RR
566#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
567 if (wxDebugContext::CountObjectsLeft() > 0)
568 {
9cc7a35d 569 wxLogDebug(_T("There were memory leaks.\n"));
0d2a2b60
RR
570 wxDebugContext::Dump();
571 wxDebugContext::PrintStatistics();
572 }
8801832d 573#endif // Debug
0d2a2b60 574
60acb947 575 // do this as the very last thing because everything else can log messages
0d2a2b60 576 wxLog::DontCreateOnDemand();
60acb947 577
0d2a2b60 578 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
60acb947
VZ
579 if (oldLog)
580 delete oldLog;
ff7b1510 581}
0cf2cb36 582
c801d85f
KB
583wxLog *wxApp::CreateLogTarget()
584{
0d2a2b60 585 return new wxLogGui;
c801d85f
KB
586}
587
588//-----------------------------------------------------------------------------
589// wxEntry
590//-----------------------------------------------------------------------------
591
592int wxEntry( int argc, char *argv[] )
593{
0d2a2b60 594 gtk_set_locale();
c801d85f 595
0d2a2b60 596 gtk_init( &argc, &argv );
0cf2cb36 597
60acb947
VZ
598 if (!wxApp::Initialize())
599 return -1;
0cf2cb36 600
ec758a20 601 if (!wxTheApp)
c801d85f 602 {
60acb947 603 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
9cc7a35d 604 _T("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
0cf2cb36 605
ec758a20 606 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
0cf2cb36 607
ec758a20 608 wxObject *test_app = app_ini();
0cf2cb36 609
ec758a20
RR
610 wxTheApp = (wxApp*) test_app;
611 }
0cf2cb36 612
9cc7a35d 613 wxCHECK_MSG( wxTheApp, -1, _T("wxWindows error: no application object") );
c801d85f 614
ec758a20
RR
615 wxTheApp->argc = argc;
616 wxTheApp->argv = argv;
0cf2cb36 617
8801832d 618 wxString name(wxFileNameFromPath(argv[0]));
ec758a20
RR
619 wxStripExtension( name );
620 wxTheApp->SetAppName( name );
e0253070 621
0151c3eb
VZ
622 int retValue = 0;
623
624 if ( !wxTheApp->OnInitGui() )
625 retValue = -1;
c801d85f 626
8801832d
VZ
627 // Here frames insert themselves automatically into wxTopLevelWindows by
628 // getting created in OnInit().
0151c3eb
VZ
629 if ( retValue == 0 )
630 {
631 if ( !wxTheApp->OnInit() )
632 retValue = -1;
633 }
0cf2cb36 634
0151c3eb
VZ
635 if ( retValue == 0 )
636 {
637 wxTheApp->m_initialized = wxTopLevelWindows.GetCount() != 0;
0cf2cb36 638
0151c3eb
VZ
639 if (wxTheApp->Initialized())
640 retValue = wxTheApp->OnRun();
0cf2cb36 641
0151c3eb
VZ
642 wxWindow *topWindow = wxTheApp->GetTopWindow();
643 if (topWindow)
0d2a2b60 644 {
0151c3eb
VZ
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 }
0d2a2b60 657 }
e0253070 658
0151c3eb
VZ
659 wxTheApp->OnExit();
660 }
0cf2cb36 661
60acb947 662 // flush the logged messages if any
0d2a2b60
RR
663 wxLog *log = wxLog::GetActiveTarget();
664 if (log != NULL && log->HasPendingMessages())
665 log->Flush();
666
60acb947
VZ
667 // continuing to use user defined log target is unsafe from now on because
668 // some resources may be already unavailable, so replace it by something
669 // more safe
670 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
671 if ( oldlog )
672 delete oldlog;
673
0d2a2b60 674 wxApp::CleanUp();
184b5d99 675
ec758a20 676 return retValue;
ff7b1510 677}
1a56f55c 678