]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/app.cpp
Added more '#pragma implementation' for gcc.
[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 /* we don't want any more idle events until the next event is
142 sent to wxGTK */
53a8af59 143 gtk_idle_remove( wxTheApp->m_idleTag );
acfd422a
RR
144 wxTheApp->m_idleTag = 0;
145
146 /* indicate that we are now in idle mode - even so deeply
147 in idle mode that we don't get any idle events anymore.
148 this is like wxMSW where an idle event is sent only
149 once each time after the event queue has been completely
150 emptied */
151 g_isIdle = TRUE;
094637f6 152
ea451729
RR
153 /* sent idle event to all who request them */
154 while (wxTheApp->ProcessIdle()) { }
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;
ea451729 355
d524867f 356 /* Avoid recursion (via ProcessEvent default case) */
956dbab1 357 if (s_inOnIdle)
ec758a20 358 return;
ea451729 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 /* Send OnIdle events to all windows */
ec758a20 370 bool needMore = SendIdleEvents();
53010e52 371
ec758a20
RR
372 if (needMore)
373 event.RequestMore(TRUE);
53010e52 374
956dbab1 375 s_inOnIdle = FALSE;
ea451729
RR
376
377 /* flush the logged messages if any */
378#if wxUSE_LOG
379 wxLog *log = wxLog::GetActiveTarget();
380 if (log != NULL && log->HasPendingMessages())
381 log->Flush();
382#endif // wxUSE_LOG
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 560#if wxUSE_THREADS
8f75cb6c
RR
561 /* GTK 1.2 up to version 1.2.3 has broken threads */
562 if ((gtk_major_version == 1) &&
563 (gtk_minor_version == 2) &&
564 (gtk_micro_version < 4))
565 {
566 printf( "wxWindows warning: Disabled GUI threading due to outdated GTK version\n" );
567 }
568 else
569 {
570 g_thread_init(NULL);
571 }
924ef850
RR
572#endif
573
0d2a2b60 574 gtk_set_locale();
c801d85f 575
fd9811b1 576#if wxUSE_WCHAR_T
dcf924a3 577 if (!wxOKlibc()) wxConvCurrent = &wxConvLocal;
fd9811b1
RR
578#else
579 if (!wxOKlibc()) wxConvCurrent = (wxMBConv*) NULL;
580#endif
002f4218 581
924ef850
RR
582 gdk_threads_enter();
583
0d2a2b60 584 gtk_init( &argc, &argv );
0cf2cb36 585
f0492f7d 586 wxSetDetectableAutoRepeat( TRUE );
094637f6 587
60acb947 588 if (!wxApp::Initialize())
924ef850
RR
589 {
590 gdk_threads_leave();
60acb947 591 return -1;
924ef850 592 }
0cf2cb36 593
ec758a20 594 if (!wxTheApp)
c801d85f 595 {
60acb947 596 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
223d09f6 597 wxT("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
0cf2cb36 598
ec758a20 599 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
0cf2cb36 600
ec758a20 601 wxObject *test_app = app_ini();
0cf2cb36 602
ec758a20
RR
603 wxTheApp = (wxApp*) test_app;
604 }
0cf2cb36 605
223d09f6 606 wxCHECK_MSG( wxTheApp, -1, wxT("wxWindows error: no application object") );
c801d85f 607
ec758a20 608 wxTheApp->argc = argc;
6de92826
OK
609#if wxUSE_UNICODE
610 wxTheApp->argv = new wxChar*[argc+1];
611 int mb_argc = 0;
924ef850
RR
612 while (mb_argc < argc)
613 {
614 wxTheApp->argv[mb_argc] = wxStrdup(wxConvLibc.cMB2WX(argv[mb_argc]));
615 mb_argc++;
6de92826
OK
616 }
617 wxTheApp->argv[mb_argc] = (wxChar *)NULL;
618#else
ec758a20 619 wxTheApp->argv = argv;
6de92826 620#endif
0cf2cb36 621
8801832d 622 wxString name(wxFileNameFromPath(argv[0]));
ec758a20
RR
623 wxStripExtension( name );
624 wxTheApp->SetAppName( name );
e0253070 625
0151c3eb
VZ
626 int retValue = 0;
627
628 if ( !wxTheApp->OnInitGui() )
629 retValue = -1;
c801d85f 630
8801832d
VZ
631 // Here frames insert themselves automatically into wxTopLevelWindows by
632 // getting created in OnInit().
0151c3eb
VZ
633 if ( retValue == 0 )
634 {
635 if ( !wxTheApp->OnInit() )
636 retValue = -1;
637 }
0cf2cb36 638
0151c3eb
VZ
639 if ( retValue == 0 )
640 {
cfb50f14 641 /* delete pending toplevel windows (typically a single
094637f6
VZ
642 dialog) so that, if there isn't any left, we don't
643 call OnRun() */
cfb50f14 644 wxTheApp->DeletePendingObjects();
094637f6 645
0151c3eb 646 wxTheApp->m_initialized = wxTopLevelWindows.GetCount() != 0;
0cf2cb36 647
0151c3eb 648 if (wxTheApp->Initialized())
094637f6 649 {
0151c3eb 650 retValue = wxTheApp->OnRun();
0cf2cb36 651
cfb50f14
RR
652 wxWindow *topWindow = wxTheApp->GetTopWindow();
653 if (topWindow)
0151c3eb 654 {
cfb50f14
RR
655 /* Forcibly delete the window. */
656 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
657 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
658 {
659 topWindow->Close( TRUE );
660 wxTheApp->DeletePendingObjects();
661 }
662 else
663 {
664 delete topWindow;
665 wxTheApp->SetTopWindow( (wxWindow*) NULL );
666 }
094637f6 667 }
cfb50f14 668 wxTheApp->OnExit();
0d2a2b60 669 }
0151c3eb 670 }
0cf2cb36 671
88ac883a 672#if wxUSE_LOG
60acb947 673 // flush the logged messages if any
0d2a2b60
RR
674 wxLog *log = wxLog::GetActiveTarget();
675 if (log != NULL && log->HasPendingMessages())
676 log->Flush();
677
60acb947
VZ
678 // continuing to use user defined log target is unsafe from now on because
679 // some resources may be already unavailable, so replace it by something
680 // more safe
681 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
682 if ( oldlog )
683 delete oldlog;
88ac883a 684#endif // wxUSE_LOG
60acb947 685
0d2a2b60 686 wxApp::CleanUp();
184b5d99 687
924ef850
RR
688 gdk_threads_leave();
689
ec758a20 690 return retValue;
ff7b1510 691}
1a56f55c 692
094637f6
VZ
693#include "wx/gtk/info.xpm"
694#include "wx/gtk/error.xpm"
695#include "wx/gtk/question.xpm"
696#include "wx/gtk/warning.xpm"
697
ebea0891
KB
698wxIcon
699wxApp::GetStdIcon(int which) const
700{
094637f6
VZ
701 switch(which)
702 {
703 case wxICON_INFORMATION:
704 return wxIcon(info_xpm);
705
706 case wxICON_QUESTION:
707 return wxIcon(question_xpm);
708
709 case wxICON_EXCLAMATION:
710 return wxIcon(warning_xpm);
711
712 default:
223d09f6 713 wxFAIL_MSG(wxT("requested non existent standard icon"));
094637f6
VZ
714 // still fall through
715
716 case wxICON_HAND:
717 return wxIcon(error_xpm);
718 }
ebea0891 719}