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