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