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