]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/app.cpp
Added test for no-change in crollwin.
[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
bf9e3e73
RR
121 if (g_isIdle)
122 wxapp_install_idle_handler();
924ef850
RR
123
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();
3ac8d3bc
RR
207
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();
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;
8480b297
RR
253
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? */
d76fe38b 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
RR
287
288 wxRootWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
289 gtk_widget_realize( wxRootWindow );
094637f6 290
7b280524 291 /* Nothing to do for 15, 16, 24, 32 bit displays */
f6fcbb63 292 if (visual->depth > 8) return TRUE;
60acb947 293
f6fcbb63 294 /* initialize color cube for 8-bit color reduction dithering */
60acb947 295
f6fcbb63 296 GdkColormap *cmap = gtk_widget_get_default_colormap();
60acb947 297
f6fcbb63
RR
298 m_colorCube = (unsigned char*)malloc(32 * 32 * 32);
299
f03fc89f
VZ
300 for (int r = 0; r < 32; r++)
301 {
8801832d
VZ
302 for (int g = 0; g < 32; g++)
303 {
304 for (int b = 0; b < 32; b++)
305 {
306 int rr = (r << 3) | (r >> 2);
307 int gg = (g << 3) | (g >> 2);
308 int bb = (b << 3) | (b >> 2);
60acb947 309
f03fc89f
VZ
310 int index = -1;
311
f6fcbb63 312 GdkColor *colors = cmap->colors;
ca26177c 313 if (colors)
f03fc89f
VZ
314 {
315 int max = 3 * 65536;
316
317 for (int i = 0; i < cmap->size; i++)
318 {
319 int rdiff = ((rr << 8) - colors[i].red);
320 int gdiff = ((gg << 8) - colors[i].green);
321 int bdiff = ((bb << 8) - colors[i].blue);
322 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
323 if (sum < max)
094637f6 324 {
f03fc89f
VZ
325 index = i; max = sum;
326 }
327 }
f6fcbb63 328 }
094637f6
VZ
329 else
330 {
58c7cd12 331#if (GTK_MINOR_VERSION > 0)
094637f6
VZ
332 /* assume 8-bit true or static colors. this really
333 exists. */
334 GdkVisual* vis = gdk_colormap_get_visual( cmap );
335 index = (r >> (5 - vis->red_prec)) << vis->red_shift;
336 index |= (g >> (5 - vis->green_prec)) << vis->green_shift;
337 index |= (b >> (5 - vis->blue_prec)) << vis->blue_shift;
58c7cd12 338#else
223d09f6 339 wxFAIL_MSG( wxT("Unsupported graphics hardware") );
58c7cd12 340#endif
094637f6 341 }
8801832d
VZ
342 m_colorCube[ (r*1024) + (g*32) + b ] = index;
343 }
344 }
f6fcbb63 345 }
c801d85f 346
bbe0af5b
RR
347 return TRUE;
348}
349
60acb947 350bool wxApp::ProcessIdle()
53010e52 351{
ec758a20
RR
352 wxIdleEvent event;
353 event.SetEventObject( this );
354 ProcessEvent( event );
0cf2cb36 355
ec758a20 356 return event.MoreRequested();
ff7b1510 357}
53010e52
RR
358
359void wxApp::OnIdle( wxIdleEvent &event )
c801d85f 360{
956dbab1 361 static bool s_inOnIdle = FALSE;
ea451729 362
d524867f 363 /* Avoid recursion (via ProcessEvent default case) */
956dbab1 364 if (s_inOnIdle)
ec758a20 365 return;
ea451729 366
956dbab1 367 s_inOnIdle = TRUE;
53010e52 368
7214297d
GL
369 /* Resend in the main thread events which have been prepared in other
370 threads */
371 ProcessPendingEvents();
372
d524867f 373 /* 'Garbage' collection of windows deleted with Close(). */
ec758a20 374 DeletePendingObjects();
53010e52 375
d524867f 376 /* Send OnIdle events to all windows */
ec758a20 377 bool needMore = SendIdleEvents();
53010e52 378
ec758a20
RR
379 if (needMore)
380 event.RequestMore(TRUE);
53010e52 381
956dbab1 382 s_inOnIdle = FALSE;
ea451729
RR
383
384 /* flush the logged messages if any */
385#if wxUSE_LOG
386 wxLog *log = wxLog::GetActiveTarget();
387 if (log != NULL && log->HasPendingMessages())
388 log->Flush();
389#endif // wxUSE_LOG
ff7b1510 390}
53010e52 391
60acb947 392bool wxApp::SendIdleEvents()
53010e52
RR
393{
394 bool needMore = FALSE;
e0253070 395
e146b8c8 396 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
ec758a20
RR
397 while (node)
398 {
e146b8c8 399 wxWindow* win = node->GetData();
f3855ef0 400 if (SendIdleEvents(win))
53010e52 401 needMore = TRUE;
e146b8c8 402 node = node->GetNext();
ec758a20 403 }
e146b8c8 404
53010e52 405 return needMore;
ff7b1510 406}
53010e52
RR
407
408bool wxApp::SendIdleEvents( wxWindow* win )
409{
410 bool needMore = FALSE;
411
8bbe427f
VZ
412 wxIdleEvent event;
413 event.SetEventObject(win);
60acb947 414
8bbe427f 415 win->ProcessEvent(event);
53010e52 416
e70f5e13 417 win->OnInternalIdle();
e90c1d2a 418
53010e52
RR
419 if (event.MoreRequested())
420 needMore = TRUE;
421
8bbe427f
VZ
422 wxNode* node = win->GetChildren().First();
423 while (node)
424 {
425 wxWindow* win = (wxWindow*) node->Data();
426 if (SendIdleEvents(win))
53010e52
RR
427 needMore = TRUE;
428
8bbe427f
VZ
429 node = node->Next();
430 }
53010e52 431 return needMore ;
ff7b1510 432}
c801d85f 433
60acb947 434int wxApp::MainLoop()
c801d85f 435{
ec758a20
RR
436 gtk_main();
437 return 0;
ff7b1510 438}
c801d85f 439
60acb947 440void wxApp::ExitMainLoop()
c801d85f 441{
7ec2881a
RR
442 if (gtk_main_level() > 0)
443 gtk_main_quit();
ff7b1510 444}
c801d85f 445
60acb947 446bool wxApp::Initialized()
c801d85f 447{
ec758a20 448 return m_initialized;
ff7b1510 449}
c801d85f 450
60acb947 451bool wxApp::Pending()
c801d85f 452{
acfd422a 453 return (gtk_events_pending() > 0);
ff7b1510 454}
c801d85f 455
60acb947 456void wxApp::Dispatch()
c801d85f 457{
8801832d 458 gtk_main_iteration();
ff7b1510 459}
c801d85f 460
60acb947 461void wxApp::DeletePendingObjects()
c801d85f 462{
ec758a20
RR
463 wxNode *node = wxPendingDelete.First();
464 while (node)
465 {
466 wxObject *obj = (wxObject *)node->Data();
0cf2cb36 467
ec758a20 468 delete obj;
c801d85f 469
f03fc89f
VZ
470 if (wxPendingDelete.Find(obj))
471 delete node;
c801d85f 472
ec758a20
RR
473 node = wxPendingDelete.First();
474 }
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
0d2a2b60
RR
492 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
493 wxTheColourDatabase->Initialize();
a3622daa 494
0d2a2b60
RR
495 wxInitializeStockLists();
496 wxInitializeStockObjects();
c801d85f 497
4a0c68a7
RR
498#if wxUSE_WX_RESOURCES
499 wxInitializeResourceSystem();
500#endif
501
0d2a2b60
RR
502 wxModule::RegisterModules();
503 if (!wxModule::InitializeModules()) return FALSE;
60acb947 504
0d2a2b60 505 return TRUE;
ff7b1510 506}
c801d85f 507
60acb947 508void wxApp::CleanUp()
c801d85f 509{
0d2a2b60 510 wxModule::CleanUpModules();
0cf2cb36 511
4a0c68a7
RR
512#if wxUSE_WX_RESOURCES
513 wxCleanUpResourceSystem();
514#endif
515
60acb947
VZ
516 if (wxTheColourDatabase)
517 delete wxTheColourDatabase;
4a0c68a7 518
0d2a2b60 519 wxTheColourDatabase = (wxColourDatabase*) NULL;
60acb947 520
0d2a2b60
RR
521 wxDeleteStockObjects();
522
ec758a20 523 wxDeleteStockLists();
a3622daa 524
0d2a2b60
RR
525 delete wxTheApp;
526 wxTheApp = (wxApp*) NULL;
527
4d3a259a
GL
528 // GL: I'm annoyed ... I don't know where to put this and I don't want to
529 // create a module for that as it's part of the core.
530#if wxUSE_THREADS
531 delete wxPendingEvents;
532 delete wxPendingEventsLocker;
533#endif
534
3e61c765 535 wxSystemSettings::Done();
60acb947 536
3e61c765
RR
537 delete[] wxBuffer;
538
539 wxClassInfo::CleanUpClasses();
60acb947
VZ
540
541 // check for memory leaks
0d2a2b60
RR
542#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
543 if (wxDebugContext::CountObjectsLeft() > 0)
544 {
223d09f6 545 wxLogDebug(wxT("There were memory leaks.\n"));
0d2a2b60
RR
546 wxDebugContext::Dump();
547 wxDebugContext::PrintStatistics();
548 }
8801832d 549#endif // Debug
0d2a2b60 550
88ac883a 551#if wxUSE_LOG
60acb947 552 // do this as the very last thing because everything else can log messages
0d2a2b60 553 wxLog::DontCreateOnDemand();
60acb947 554
0d2a2b60 555 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
60acb947
VZ
556 if (oldLog)
557 delete oldLog;
88ac883a 558#endif // wxUSE_LOG
c19c1ca9 559}
c801d85f
KB
560
561//-----------------------------------------------------------------------------
562// wxEntry
563//-----------------------------------------------------------------------------
564
565int wxEntry( int argc, char *argv[] )
566{
924ef850 567#if wxUSE_THREADS
8f75cb6c
RR
568 /* GTK 1.2 up to version 1.2.3 has broken threads */
569 if ((gtk_major_version == 1) &&
570 (gtk_minor_version == 2) &&
571 (gtk_micro_version < 4))
572 {
573 printf( "wxWindows warning: Disabled GUI threading due to outdated GTK version\n" );
574 }
575 else
576 {
577 g_thread_init(NULL);
578 }
924ef850
RR
579#endif
580
0d2a2b60 581 gtk_set_locale();
c801d85f 582
fd9811b1 583#if wxUSE_WCHAR_T
dcf924a3 584 if (!wxOKlibc()) wxConvCurrent = &wxConvLocal;
fd9811b1
RR
585#else
586 if (!wxOKlibc()) wxConvCurrent = (wxMBConv*) NULL;
587#endif
002f4218 588
924ef850
RR
589 gdk_threads_enter();
590
0d2a2b60 591 gtk_init( &argc, &argv );
0cf2cb36 592
f0492f7d 593 wxSetDetectableAutoRepeat( TRUE );
094637f6 594
60acb947 595 if (!wxApp::Initialize())
924ef850
RR
596 {
597 gdk_threads_leave();
60acb947 598 return -1;
924ef850 599 }
0cf2cb36 600
ec758a20 601 if (!wxTheApp)
c801d85f 602 {
60acb947 603 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
223d09f6 604 wxT("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
223d09f6 613 wxCHECK_MSG( wxTheApp, -1, wxT("wxWindows error: no application object") );
c801d85f 614
ec758a20 615 wxTheApp->argc = argc;
6de92826
OK
616#if wxUSE_UNICODE
617 wxTheApp->argv = new wxChar*[argc+1];
618 int mb_argc = 0;
924ef850
RR
619 while (mb_argc < argc)
620 {
621 wxTheApp->argv[mb_argc] = wxStrdup(wxConvLibc.cMB2WX(argv[mb_argc]));
622 mb_argc++;
6de92826
OK
623 }
624 wxTheApp->argv[mb_argc] = (wxChar *)NULL;
625#else
ec758a20 626 wxTheApp->argv = argv;
6de92826 627#endif
0cf2cb36 628
8801832d 629 wxString name(wxFileNameFromPath(argv[0]));
ec758a20
RR
630 wxStripExtension( name );
631 wxTheApp->SetAppName( name );
e0253070 632
0151c3eb
VZ
633 int retValue = 0;
634
635 if ( !wxTheApp->OnInitGui() )
636 retValue = -1;
c801d85f 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 {
0151c3eb 657 retValue = 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 }
cfb50f14 675 wxTheApp->OnExit();
0d2a2b60 676 }
0151c3eb 677 }
0cf2cb36 678
88ac883a 679#if wxUSE_LOG
60acb947 680 // flush the logged messages if any
0d2a2b60
RR
681 wxLog *log = wxLog::GetActiveTarget();
682 if (log != NULL && log->HasPendingMessages())
683 log->Flush();
684
60acb947
VZ
685 // continuing to use user defined log target is unsafe from now on because
686 // some resources may be already unavailable, so replace it by something
687 // more safe
688 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
689 if ( oldlog )
690 delete oldlog;
88ac883a 691#endif // wxUSE_LOG
60acb947 692
0d2a2b60 693 wxApp::CleanUp();
184b5d99 694
924ef850
RR
695 gdk_threads_leave();
696
ec758a20 697 return retValue;
ff7b1510 698}
1a56f55c 699
094637f6
VZ
700#include "wx/gtk/info.xpm"
701#include "wx/gtk/error.xpm"
702#include "wx/gtk/question.xpm"
703#include "wx/gtk/warning.xpm"
704
ebea0891
KB
705wxIcon
706wxApp::GetStdIcon(int which) const
707{
094637f6
VZ
708 switch(which)
709 {
710 case wxICON_INFORMATION:
711 return wxIcon(info_xpm);
712
713 case wxICON_QUESTION:
714 return wxIcon(question_xpm);
715
716 case wxICON_EXCLAMATION:
717 return wxIcon(warning_xpm);
718
719 default:
223d09f6 720 wxFAIL_MSG(wxT("requested non existent standard icon"));
094637f6
VZ
721 // still fall through
722
723 case wxICON_HAND:
724 return wxIcon(error_xpm);
725 }
ebea0891 726}