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