]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/app.cpp
Made tearoff menus work for gtk :-)
[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 148 while (wxTheApp->ProcessIdle()) { }
094637f6 149
1601ab7a 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 }
094637f6 178
acfd422a
RR
179 return TRUE;
180}
181
182gint wxapp_idle_callback( gpointer WXUNUSED(data) )
183{
184 if (!wxTheApp) return TRUE;
094637f6 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
094637f6 192
acfd422a
RR
193 /* sent idle event to all who request them */
194 while (wxTheApp->ProcessIdle()) { }
094637f6 195
acfd422a
RR
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;
094637f6 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 );
094637f6 224
acfd422a 225 g_isIdle = FALSE;
ff7b1510 226}
c801d85f 227
8dbf4589 228/*
6b3eb77a 229#if wxUSE_THREADS
7b90a8f2
RR
230static gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
231{
232 gtk_timeout_remove( wxTheApp->m_wakeUpTimerTag );
233 wxTheApp->m_wakeUpTimerTag = 0;
094637f6 234
86fdd27b 235#if (GTK_MINOR_VERSION > 0)
094637f6 236 // when getting called from GDK's time-out handler
8dbf4589
RR
237 // we are no longer within GDK's grab on the GUI
238 // thread so we must lock it here ourselves
7b90a8f2 239 GDK_THREADS_ENTER ();
86fdd27b 240#endif
094637f6 241
8dbf4589 242 // unblock other threads wishing to do some GUI things
7b90a8f2 243 wxMutexGuiLeave();
094637f6 244
8dbf4589 245 // wake up other threads
7b90a8f2 246 wxUsleep( 1 );
094637f6 247
8dbf4589 248 // block other thread again
7b90a8f2 249 wxMutexGuiEnter();
094637f6 250
86fdd27b 251#if (GTK_MINOR_VERSION > 0)
8dbf4589 252 // release lock again
7b90a8f2 253 GDK_THREADS_LEAVE ();
86fdd27b 254#endif
094637f6 255
db2d879a 256 wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 20, wxapp_wakeup_timerout_callback, (gpointer) NULL );
094637f6 257
7b90a8f2
RR
258 return TRUE;
259}
6b3eb77a 260#endif
8dbf4589 261*/
7b90a8f2 262
c801d85f
KB
263//-----------------------------------------------------------------------------
264// wxApp
265//-----------------------------------------------------------------------------
266
267IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
268
53010e52
RR
269BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
270 EVT_IDLE(wxApp::OnIdle)
271END_EVENT_TABLE()
272
c801d85f
KB
273wxApp::wxApp()
274{
0d2a2b60 275 wxTheApp = this;
60acb947 276
ec758a20
RR
277 m_topWindow = (wxWindow *) NULL;
278 m_exitOnFrameDelete = TRUE;
60acb947 279
0d2a2b60 280 m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
094637f6 281
8dbf4589 282/*
6b3eb77a 283#if wxUSE_THREADS
db2d879a 284 m_wakeUpTimerTag = gtk_timeout_add( 20, wxapp_wakeup_timerout_callback, (gpointer) NULL );
6b3eb77a 285#endif
8dbf4589 286*/
60acb947 287
f6fcbb63 288 m_colorCube = (unsigned char*) NULL;
ff7b1510 289}
c801d85f 290
60acb947 291wxApp::~wxApp()
c801d85f 292{
acfd422a 293 if (m_idleTag) gtk_idle_remove( m_idleTag );
60acb947 294
8dbf4589 295/*
6b3eb77a 296#if wxUSE_THREADS
7b90a8f2 297 if (m_wakeUpTimerTag) gtk_timeout_remove( m_wakeUpTimerTag );
6b3eb77a 298#endif
8dbf4589 299*/
094637f6 300
f6fcbb63 301 if (m_colorCube) free(m_colorCube);
ff7b1510 302}
c801d85f 303
0d2a2b60 304bool wxApp::OnInitGui()
c801d85f 305{
b134516c
RR
306 GdkVisual *visual = gdk_visual_get_system();
307
094637f6 308 /* on some machines, the default visual is just 256 colours, so
b134516c 309 we make sure we get the best. this can sometimes be wasteful,
7b280524 310 of course, but what do these guys pay $30.000 for? */
b134516c
RR
311/*
312 if (gdk_visual_get_best() != gdk_visual_get_system())
313 {
314 GdkVisual* vis = gdk_visual_get_best();
315 gtk_widget_set_default_visual( vis );
f6fcbb63 316
b134516c
RR
317 GdkColormap *colormap = gdk_colormap_new( vis, FALSE );
318 gtk_widget_set_default_colormap( colormap );
094637f6
VZ
319
320 visual = vis;
b134516c
RR
321 }
322*/
094637f6 323
7b280524 324 /* Nothing to do for 15, 16, 24, 32 bit displays */
f6fcbb63 325 if (visual->depth > 8) return TRUE;
60acb947 326
0d2a2b60
RR
327 /* this initiates the standard palette as defined by GdkImlib
328 in the GNOME libraries. it ensures that all GNOME applications
329 use the same 64 colormap entries on 8-bit displays so you
330 can use several rather graphics-heavy applications at the
331 same time.
8801832d 332 NOTE: this doesn't really seem to work this way... */
bbe0af5b 333
0d2a2b60
RR
334 /*
335 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
bbe0af5b 336
0d2a2b60
RR
337 for (int i = 0; i < 64; i++)
338 {
339 GdkColor col;
340 col.red = g_palette[i*3 + 0] << 8;
341 col.green = g_palette[i*3 + 1] << 8;
342 col.blue = g_palette[i*3 + 2] << 8;
343 col.pixel = 0;
344
345 gdk_color_alloc( cmap, &col );
346 }
60acb947 347
0d2a2b60
RR
348 gtk_widget_set_default_colormap( cmap );
349 */
60acb947 350
f6fcbb63 351 /* initialize color cube for 8-bit color reduction dithering */
60acb947 352
f6fcbb63 353 GdkColormap *cmap = gtk_widget_get_default_colormap();
60acb947 354
f6fcbb63
RR
355 m_colorCube = (unsigned char*)malloc(32 * 32 * 32);
356
f03fc89f
VZ
357 for (int r = 0; r < 32; r++)
358 {
8801832d
VZ
359 for (int g = 0; g < 32; g++)
360 {
361 for (int b = 0; b < 32; b++)
362 {
363 int rr = (r << 3) | (r >> 2);
364 int gg = (g << 3) | (g >> 2);
365 int bb = (b << 3) | (b >> 2);
60acb947 366
f03fc89f
VZ
367 int index = -1;
368
f6fcbb63 369 GdkColor *colors = cmap->colors;
ca26177c 370 if (colors)
f03fc89f
VZ
371 {
372 int max = 3 * 65536;
373
374 for (int i = 0; i < cmap->size; i++)
375 {
376 int rdiff = ((rr << 8) - colors[i].red);
377 int gdiff = ((gg << 8) - colors[i].green);
378 int bdiff = ((bb << 8) - colors[i].blue);
379 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
380 if (sum < max)
094637f6 381 {
f03fc89f
VZ
382 index = i; max = sum;
383 }
384 }
f6fcbb63 385 }
094637f6
VZ
386 else
387 {
58c7cd12 388#if (GTK_MINOR_VERSION > 0)
094637f6
VZ
389 /* assume 8-bit true or static colors. this really
390 exists. */
391 GdkVisual* vis = gdk_colormap_get_visual( cmap );
392 index = (r >> (5 - vis->red_prec)) << vis->red_shift;
393 index |= (g >> (5 - vis->green_prec)) << vis->green_shift;
394 index |= (b >> (5 - vis->blue_prec)) << vis->blue_shift;
58c7cd12
RR
395#else
396 wxFAIL_MSG( _T("Unsupported graphics hardware") );
397#endif
094637f6 398 }
8801832d
VZ
399 m_colorCube[ (r*1024) + (g*32) + b ] = index;
400 }
401 }
f6fcbb63 402 }
c801d85f 403
bbe0af5b
RR
404 return TRUE;
405}
406
60acb947 407bool wxApp::ProcessIdle()
53010e52 408{
ec758a20
RR
409 wxIdleEvent event;
410 event.SetEventObject( this );
411 ProcessEvent( event );
0cf2cb36 412
ec758a20 413 return event.MoreRequested();
ff7b1510 414}
53010e52
RR
415
416void wxApp::OnIdle( wxIdleEvent &event )
c801d85f 417{
ec758a20 418 static bool inOnIdle = FALSE;
53010e52 419
d524867f 420 /* Avoid recursion (via ProcessEvent default case) */
ec758a20
RR
421 if (inOnIdle)
422 return;
53010e52 423
ec758a20 424 inOnIdle = TRUE;
53010e52 425
d345e841 426#if wxUSE_THREADS
7214297d
GL
427 /* Resend in the main thread events which have been prepared in other
428 threads */
429 ProcessPendingEvents();
d345e841 430#endif
7214297d 431
d524867f 432 /* 'Garbage' collection of windows deleted with Close(). */
ec758a20 433 DeletePendingObjects();
53010e52 434
d524867f 435 /* flush the logged messages if any */
88ac883a 436#if wxUSE_LOG
d524867f
RR
437 wxLog *log = wxLog::GetActiveTarget();
438 if (log != NULL && log->HasPendingMessages())
439 log->Flush();
88ac883a 440#endif // wxUSE_LOG
53010e52 441
d524867f 442 /* Send OnIdle events to all windows */
ec758a20 443 bool needMore = SendIdleEvents();
53010e52 444
ec758a20
RR
445 if (needMore)
446 event.RequestMore(TRUE);
53010e52 447
ec758a20 448 inOnIdle = FALSE;
ff7b1510 449}
53010e52 450
60acb947 451bool wxApp::SendIdleEvents()
53010e52
RR
452{
453 bool needMore = FALSE;
e0253070 454
e146b8c8 455 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
ec758a20
RR
456 while (node)
457 {
e146b8c8 458 wxWindow* win = node->GetData();
f3855ef0 459 if (SendIdleEvents(win))
53010e52 460 needMore = TRUE;
e146b8c8 461 node = node->GetNext();
ec758a20 462 }
e146b8c8 463
53010e52 464 return needMore;
ff7b1510 465}
53010e52
RR
466
467bool wxApp::SendIdleEvents( wxWindow* win )
468{
469 bool needMore = FALSE;
470
8bbe427f
VZ
471 wxIdleEvent event;
472 event.SetEventObject(win);
60acb947 473
9390a202 474 win->OnInternalIdle();
60acb947 475
8bbe427f 476 win->ProcessEvent(event);
53010e52
RR
477
478 if (event.MoreRequested())
479 needMore = TRUE;
480
8bbe427f
VZ
481 wxNode* node = win->GetChildren().First();
482 while (node)
483 {
484 wxWindow* win = (wxWindow*) node->Data();
485 if (SendIdleEvents(win))
53010e52
RR
486 needMore = TRUE;
487
8bbe427f
VZ
488 node = node->Next();
489 }
53010e52 490 return needMore ;
ff7b1510 491}
c801d85f 492
60acb947 493int wxApp::MainLoop()
c801d85f 494{
ec758a20
RR
495 gtk_main();
496 return 0;
ff7b1510 497}
c801d85f 498
60acb947 499void wxApp::ExitMainLoop()
c801d85f 500{
ec758a20 501 gtk_main_quit();
ff7b1510 502}
c801d85f 503
60acb947 504bool wxApp::Initialized()
c801d85f 505{
ec758a20 506 return m_initialized;
ff7b1510 507}
c801d85f 508
60acb947 509bool wxApp::Pending()
c801d85f 510{
acfd422a 511 return (gtk_events_pending() > 0);
ff7b1510 512}
c801d85f 513
60acb947 514void wxApp::Dispatch()
c801d85f 515{
8801832d 516 gtk_main_iteration();
ff7b1510 517}
c801d85f 518
7214297d
GL
519#if wxUSE_THREADS
520void wxApp::ProcessPendingEvents()
521{
4d3a259a
GL
522 wxNode *node = wxPendingEvents->First();
523 wxCriticalSectionLocker locker(*wxPendingEventsLocker);
7214297d
GL
524
525 while (node)
526 {
527 wxEvtHandler *handler = (wxEvtHandler *)node->Data();
528
529 handler->ProcessPendingEvents();
e146b8c8 530
7214297d
GL
531 delete node;
532
4d3a259a 533 node = wxPendingEvents->First();
7214297d
GL
534 }
535}
8801832d 536#endif // wxUSE_THREADS
7214297d 537
60acb947 538void wxApp::DeletePendingObjects()
c801d85f 539{
ec758a20
RR
540 wxNode *node = wxPendingDelete.First();
541 while (node)
542 {
543 wxObject *obj = (wxObject *)node->Data();
0cf2cb36 544
ec758a20 545 delete obj;
c801d85f 546
f03fc89f
VZ
547 if (wxPendingDelete.Find(obj))
548 delete node;
c801d85f 549
ec758a20
RR
550 node = wxPendingDelete.First();
551 }
ff7b1510 552}
c801d85f 553
60acb947 554bool wxApp::Initialize()
c801d85f 555{
9cc7a35d 556 wxBuffer = new wxChar[BUFSIZ + 512];
0d2a2b60
RR
557
558 wxClassInfo::InitializeClasses();
60acb947 559
0d2a2b60 560 wxSystemSettings::Init();
60acb947 561
4d3a259a
GL
562 // GL: I'm annoyed ... I don't know where to put this and I don't want to
563 // create a module for that as it's part of the core.
564#if wxUSE_THREADS
565 wxPendingEvents = new wxList();
566 wxPendingEventsLocker = new wxCriticalSection();
567#endif
568
36b3b54a 569/*
0d2a2b60
RR
570 wxTheFontNameDirectory = new wxFontNameDirectory;
571 wxTheFontNameDirectory->Initialize();
36b3b54a 572*/
c801d85f 573
0d2a2b60
RR
574 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
575 wxTheColourDatabase->Initialize();
a3622daa 576
0d2a2b60
RR
577 wxInitializeStockLists();
578 wxInitializeStockObjects();
c801d85f 579
06cfab17 580#if wxUSE_WX_RESOURCES
0d2a2b60 581 wxTheResourceCache = new wxResourceCache( wxKEY_STRING );
60acb947 582
0d2a2b60 583 wxInitializeResourceSystem();
f5abe911 584#endif
0cf2cb36 585
0d2a2b60 586 wxImage::InitStandardHandlers();
e0253070 587
0d2a2b60
RR
588 wxModule::RegisterModules();
589 if (!wxModule::InitializeModules()) return FALSE;
60acb947 590
0d2a2b60 591 return TRUE;
ff7b1510 592}
c801d85f 593
60acb947 594void wxApp::CleanUp()
c801d85f 595{
0d2a2b60 596 wxModule::CleanUpModules();
0cf2cb36 597
06cfab17 598#if wxUSE_WX_RESOURCES
ec758a20 599 wxFlushResources();
a3622daa 600
60acb947
VZ
601 if (wxTheResourceCache)
602 delete wxTheResourceCache;
bbe0af5b 603 wxTheResourceCache = (wxResourceCache*) NULL;
60acb947 604
f5abe911
RR
605 wxCleanUpResourceSystem();
606#endif
a3622daa 607
60acb947
VZ
608 if (wxTheColourDatabase)
609 delete wxTheColourDatabase;
0d2a2b60 610 wxTheColourDatabase = (wxColourDatabase*) NULL;
60acb947 611
36b3b54a 612/*
0d2a2b60
RR
613 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
614 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
36b3b54a 615*/
60acb947 616
0d2a2b60
RR
617 wxDeleteStockObjects();
618
ec758a20 619 wxDeleteStockLists();
a3622daa 620
ec758a20 621 wxImage::CleanUpHandlers();
0cf2cb36 622
0d2a2b60
RR
623 delete wxTheApp;
624 wxTheApp = (wxApp*) NULL;
625
4d3a259a
GL
626 // GL: I'm annoyed ... I don't know where to put this and I don't want to
627 // create a module for that as it's part of the core.
628#if wxUSE_THREADS
629 delete wxPendingEvents;
630 delete wxPendingEventsLocker;
631#endif
632
3e61c765 633 wxSystemSettings::Done();
60acb947 634
3e61c765
RR
635 delete[] wxBuffer;
636
637 wxClassInfo::CleanUpClasses();
60acb947
VZ
638
639 // check for memory leaks
0d2a2b60
RR
640#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
641 if (wxDebugContext::CountObjectsLeft() > 0)
642 {
9cc7a35d 643 wxLogDebug(_T("There were memory leaks.\n"));
0d2a2b60
RR
644 wxDebugContext::Dump();
645 wxDebugContext::PrintStatistics();
646 }
8801832d 647#endif // Debug
0d2a2b60 648
88ac883a 649#if wxUSE_LOG
60acb947 650 // do this as the very last thing because everything else can log messages
0d2a2b60 651 wxLog::DontCreateOnDemand();
60acb947 652
0d2a2b60 653 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
60acb947
VZ
654 if (oldLog)
655 delete oldLog;
ff7b1510 656}
0cf2cb36 657
88ac883a 658#endif // wxUSE_LOG
c801d85f
KB
659
660//-----------------------------------------------------------------------------
661// wxEntry
662//-----------------------------------------------------------------------------
663
664int wxEntry( int argc, char *argv[] )
665{
0d2a2b60 666 gtk_set_locale();
c801d85f 667
dcf924a3 668 if (!wxOKlibc()) wxConvCurrent = &wxConvLocal;
002f4218 669
0d2a2b60 670 gtk_init( &argc, &argv );
0cf2cb36 671
f0492f7d 672 wxSetDetectableAutoRepeat( TRUE );
094637f6 673
60acb947
VZ
674 if (!wxApp::Initialize())
675 return -1;
0cf2cb36 676
ec758a20 677 if (!wxTheApp)
c801d85f 678 {
60acb947 679 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
9cc7a35d 680 _T("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
0cf2cb36 681
ec758a20 682 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
0cf2cb36 683
ec758a20 684 wxObject *test_app = app_ini();
0cf2cb36 685
ec758a20
RR
686 wxTheApp = (wxApp*) test_app;
687 }
0cf2cb36 688
9cc7a35d 689 wxCHECK_MSG( wxTheApp, -1, _T("wxWindows error: no application object") );
c801d85f 690
ec758a20
RR
691 wxTheApp->argc = argc;
692 wxTheApp->argv = argv;
0cf2cb36 693
8801832d 694 wxString name(wxFileNameFromPath(argv[0]));
ec758a20
RR
695 wxStripExtension( name );
696 wxTheApp->SetAppName( name );
e0253070 697
0151c3eb
VZ
698 int retValue = 0;
699
700 if ( !wxTheApp->OnInitGui() )
701 retValue = -1;
c801d85f 702
8801832d
VZ
703 // Here frames insert themselves automatically into wxTopLevelWindows by
704 // getting created in OnInit().
0151c3eb
VZ
705 if ( retValue == 0 )
706 {
707 if ( !wxTheApp->OnInit() )
708 retValue = -1;
709 }
0cf2cb36 710
0151c3eb
VZ
711 if ( retValue == 0 )
712 {
cfb50f14 713 /* delete pending toplevel windows (typically a single
094637f6
VZ
714 dialog) so that, if there isn't any left, we don't
715 call OnRun() */
cfb50f14 716 wxTheApp->DeletePendingObjects();
094637f6 717
0151c3eb 718 wxTheApp->m_initialized = wxTopLevelWindows.GetCount() != 0;
0cf2cb36 719
0151c3eb 720 if (wxTheApp->Initialized())
094637f6 721 {
0151c3eb 722 retValue = wxTheApp->OnRun();
0cf2cb36 723
cfb50f14
RR
724 wxWindow *topWindow = wxTheApp->GetTopWindow();
725 if (topWindow)
0151c3eb 726 {
cfb50f14
RR
727 /* Forcibly delete the window. */
728 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
729 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
730 {
731 topWindow->Close( TRUE );
732 wxTheApp->DeletePendingObjects();
733 }
734 else
735 {
736 delete topWindow;
737 wxTheApp->SetTopWindow( (wxWindow*) NULL );
738 }
094637f6 739 }
cfb50f14 740 wxTheApp->OnExit();
0d2a2b60 741 }
0151c3eb 742 }
0cf2cb36 743
88ac883a 744#if wxUSE_LOG
60acb947 745 // flush the logged messages if any
0d2a2b60
RR
746 wxLog *log = wxLog::GetActiveTarget();
747 if (log != NULL && log->HasPendingMessages())
748 log->Flush();
749
60acb947
VZ
750 // continuing to use user defined log target is unsafe from now on because
751 // some resources may be already unavailable, so replace it by something
752 // more safe
753 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
754 if ( oldlog )
755 delete oldlog;
88ac883a 756#endif // wxUSE_LOG
60acb947 757
0d2a2b60 758 wxApp::CleanUp();
184b5d99 759
ec758a20 760 return retValue;
ff7b1510 761}
1a56f55c 762
094637f6
VZ
763#include "wx/gtk/info.xpm"
764#include "wx/gtk/error.xpm"
765#include "wx/gtk/question.xpm"
766#include "wx/gtk/warning.xpm"
767
ebea0891
KB
768wxIcon
769wxApp::GetStdIcon(int which) const
770{
094637f6
VZ
771 switch(which)
772 {
773 case wxICON_INFORMATION:
774 return wxIcon(info_xpm);
775
776 case wxICON_QUESTION:
777 return wxIcon(question_xpm);
778
779 case wxICON_EXCLAMATION:
780 return wxIcon(warning_xpm);
781
782 default:
783 wxFAIL_MSG("requested non existent standard icon");
784 // still fall through
785
786 case wxICON_HAND:
787 return wxIcon(error_xpm);
788 }
ebea0891 789}