]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/app.cpp
Fixed a notebook crash and added more tests to 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
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{
7b90a8f2
RR
216 wxASSERT_MSG( wxTheApp->m_idleTag == 0, "attempt to install idle handler twice" );
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
RR
252
253 wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 10, wxapp_wakeup_timerout_callback, (gpointer) NULL );
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
7b90a8f2 279 m_wakeUpTimerTag = gtk_timeout_add( 10, 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;
f03fc89f
VZ
346 if(colors)
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 }
f03fc89f 362
8801832d
VZ
363 m_colorCube[ (r*1024) + (g*32) + b ] = index;
364 }
365 }
f6fcbb63 366 }
c801d85f 367
bbe0af5b
RR
368 return TRUE;
369}
370
60acb947 371bool wxApp::ProcessIdle()
53010e52 372{
ec758a20
RR
373 wxIdleEvent event;
374 event.SetEventObject( this );
375 ProcessEvent( event );
0cf2cb36 376
ec758a20 377 return event.MoreRequested();
ff7b1510 378}
53010e52
RR
379
380void wxApp::OnIdle( wxIdleEvent &event )
c801d85f 381{
ec758a20 382 static bool inOnIdle = FALSE;
53010e52 383
d524867f 384 /* Avoid recursion (via ProcessEvent default case) */
ec758a20
RR
385 if (inOnIdle)
386 return;
53010e52 387
ec758a20 388 inOnIdle = TRUE;
53010e52 389
d345e841 390#if wxUSE_THREADS
7214297d
GL
391 /* Resend in the main thread events which have been prepared in other
392 threads */
393 ProcessPendingEvents();
d345e841 394#endif
7214297d 395
d524867f 396 /* 'Garbage' collection of windows deleted with Close(). */
ec758a20 397 DeletePendingObjects();
53010e52 398
d524867f
RR
399 /* flush the logged messages if any */
400 wxLog *log = wxLog::GetActiveTarget();
401 if (log != NULL && log->HasPendingMessages())
402 log->Flush();
53010e52 403
d524867f 404 /* Send OnIdle events to all windows */
ec758a20 405 bool needMore = SendIdleEvents();
53010e52 406
ec758a20
RR
407 if (needMore)
408 event.RequestMore(TRUE);
53010e52 409
ec758a20 410 inOnIdle = FALSE;
ff7b1510 411}
53010e52 412
60acb947 413bool wxApp::SendIdleEvents()
53010e52
RR
414{
415 bool needMore = FALSE;
e0253070 416
e146b8c8 417 wxWindowList::Node* node = wxTopLevelWindows.GetFirst();
ec758a20
RR
418 while (node)
419 {
e146b8c8 420 wxWindow* win = node->GetData();
f3855ef0 421 if (SendIdleEvents(win))
53010e52 422 needMore = TRUE;
e146b8c8 423 node = node->GetNext();
ec758a20 424 }
e146b8c8 425
53010e52 426 return needMore;
ff7b1510 427}
53010e52
RR
428
429bool wxApp::SendIdleEvents( wxWindow* win )
430{
431 bool needMore = FALSE;
432
8bbe427f
VZ
433 wxIdleEvent event;
434 event.SetEventObject(win);
60acb947 435
9390a202 436 win->OnInternalIdle();
60acb947 437
8bbe427f 438 win->ProcessEvent(event);
53010e52
RR
439
440 if (event.MoreRequested())
441 needMore = TRUE;
442
8bbe427f
VZ
443 wxNode* node = win->GetChildren().First();
444 while (node)
445 {
446 wxWindow* win = (wxWindow*) node->Data();
447 if (SendIdleEvents(win))
53010e52
RR
448 needMore = TRUE;
449
8bbe427f
VZ
450 node = node->Next();
451 }
53010e52 452 return needMore ;
ff7b1510 453}
c801d85f 454
60acb947 455int wxApp::MainLoop()
c801d85f 456{
ec758a20
RR
457 gtk_main();
458 return 0;
ff7b1510 459}
c801d85f 460
60acb947 461void wxApp::ExitMainLoop()
c801d85f 462{
ec758a20 463 gtk_main_quit();
ff7b1510 464}
c801d85f 465
60acb947 466bool wxApp::Initialized()
c801d85f 467{
ec758a20 468 return m_initialized;
ff7b1510 469}
c801d85f 470
60acb947 471bool wxApp::Pending()
c801d85f 472{
acfd422a 473 return (gtk_events_pending() > 0);
ff7b1510 474}
c801d85f 475
60acb947 476void wxApp::Dispatch()
c801d85f 477{
8801832d 478 gtk_main_iteration();
ff7b1510 479}
c801d85f 480
7214297d
GL
481#if wxUSE_THREADS
482void wxApp::ProcessPendingEvents()
483{
4d3a259a
GL
484 wxNode *node = wxPendingEvents->First();
485 wxCriticalSectionLocker locker(*wxPendingEventsLocker);
7214297d
GL
486
487 while (node)
488 {
489 wxEvtHandler *handler = (wxEvtHandler *)node->Data();
490
491 handler->ProcessPendingEvents();
e146b8c8 492
7214297d
GL
493 delete node;
494
4d3a259a 495 node = wxPendingEvents->First();
7214297d
GL
496 }
497}
8801832d 498#endif // wxUSE_THREADS
7214297d 499
60acb947 500void wxApp::DeletePendingObjects()
c801d85f 501{
ec758a20
RR
502 wxNode *node = wxPendingDelete.First();
503 while (node)
504 {
505 wxObject *obj = (wxObject *)node->Data();
0cf2cb36 506
ec758a20 507 delete obj;
c801d85f 508
f03fc89f
VZ
509 if (wxPendingDelete.Find(obj))
510 delete node;
c801d85f 511
ec758a20
RR
512 node = wxPendingDelete.First();
513 }
ff7b1510 514}
c801d85f 515
60acb947 516wxWindow *wxApp::GetTopWindow()
c801d85f 517{
e146b8c8
VZ
518 if (m_topWindow)
519 return m_topWindow;
520 else if (wxTopLevelWindows.GetCount() > 0)
521 return wxTopLevelWindows.GetFirst()->GetData();
522 else
523 return NULL;
ff7b1510 524}
c801d85f
KB
525
526void wxApp::SetTopWindow( wxWindow *win )
527{
ec758a20 528 m_topWindow = win;
ff7b1510 529}
c801d85f 530
60acb947 531bool wxApp::Initialize()
c801d85f 532{
9cc7a35d 533 wxBuffer = new wxChar[BUFSIZ + 512];
0d2a2b60
RR
534
535 wxClassInfo::InitializeClasses();
60acb947 536
0d2a2b60 537 wxSystemSettings::Init();
60acb947 538
4d3a259a
GL
539 // GL: I'm annoyed ... I don't know where to put this and I don't want to
540 // create a module for that as it's part of the core.
541#if wxUSE_THREADS
542 wxPendingEvents = new wxList();
543 wxPendingEventsLocker = new wxCriticalSection();
544#endif
545
36b3b54a 546/*
0d2a2b60
RR
547 wxTheFontNameDirectory = new wxFontNameDirectory;
548 wxTheFontNameDirectory->Initialize();
36b3b54a 549*/
c801d85f 550
0d2a2b60
RR
551 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
552 wxTheColourDatabase->Initialize();
a3622daa 553
0d2a2b60
RR
554 wxInitializeStockLists();
555 wxInitializeStockObjects();
c801d85f 556
06cfab17 557#if wxUSE_WX_RESOURCES
0d2a2b60 558 wxTheResourceCache = new wxResourceCache( wxKEY_STRING );
60acb947 559
0d2a2b60 560 wxInitializeResourceSystem();
f5abe911 561#endif
0cf2cb36 562
0d2a2b60 563 wxImage::InitStandardHandlers();
e0253070 564
0d2a2b60
RR
565 /* no global cursor under X
566 g_globalCursor = new wxCursor; */
60acb947 567
0d2a2b60
RR
568 wxModule::RegisterModules();
569 if (!wxModule::InitializeModules()) return FALSE;
60acb947 570
0d2a2b60 571 return TRUE;
ff7b1510 572}
c801d85f 573
60acb947 574void wxApp::CleanUp()
c801d85f 575{
0d2a2b60 576 wxModule::CleanUpModules();
0cf2cb36 577
06cfab17 578#if wxUSE_WX_RESOURCES
ec758a20 579 wxFlushResources();
a3622daa 580
60acb947
VZ
581 if (wxTheResourceCache)
582 delete wxTheResourceCache;
bbe0af5b 583 wxTheResourceCache = (wxResourceCache*) NULL;
60acb947 584
f5abe911
RR
585 wxCleanUpResourceSystem();
586#endif
a3622daa 587
60acb947
VZ
588 if (wxTheColourDatabase)
589 delete wxTheColourDatabase;
0d2a2b60 590 wxTheColourDatabase = (wxColourDatabase*) NULL;
60acb947 591
36b3b54a 592/*
0d2a2b60
RR
593 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
594 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
36b3b54a 595*/
60acb947 596
0d2a2b60
RR
597 wxDeleteStockObjects();
598
ec758a20 599 wxDeleteStockLists();
a3622daa 600
ec758a20 601 wxImage::CleanUpHandlers();
0cf2cb36 602
0d2a2b60
RR
603 delete wxTheApp;
604 wxTheApp = (wxApp*) NULL;
605
4d3a259a
GL
606 // GL: I'm annoyed ... I don't know where to put this and I don't want to
607 // create a module for that as it's part of the core.
608#if wxUSE_THREADS
609 delete wxPendingEvents;
610 delete wxPendingEventsLocker;
611#endif
612
3e61c765 613 wxSystemSettings::Done();
60acb947 614
3e61c765
RR
615 delete[] wxBuffer;
616
617 wxClassInfo::CleanUpClasses();
60acb947
VZ
618
619 // check for memory leaks
0d2a2b60
RR
620#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
621 if (wxDebugContext::CountObjectsLeft() > 0)
622 {
9cc7a35d 623 wxLogDebug(_T("There were memory leaks.\n"));
0d2a2b60
RR
624 wxDebugContext::Dump();
625 wxDebugContext::PrintStatistics();
626 }
8801832d 627#endif // Debug
0d2a2b60 628
60acb947 629 // do this as the very last thing because everything else can log messages
0d2a2b60 630 wxLog::DontCreateOnDemand();
60acb947 631
0d2a2b60 632 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
60acb947
VZ
633 if (oldLog)
634 delete oldLog;
ff7b1510 635}
0cf2cb36 636
c801d85f
KB
637wxLog *wxApp::CreateLogTarget()
638{
0d2a2b60 639 return new wxLogGui;
c801d85f
KB
640}
641
642//-----------------------------------------------------------------------------
643// wxEntry
644//-----------------------------------------------------------------------------
645
646int wxEntry( int argc, char *argv[] )
647{
0d2a2b60 648 gtk_set_locale();
c801d85f 649
0d2a2b60 650 gtk_init( &argc, &argv );
0cf2cb36 651
f0492f7d
RR
652 wxSetDetectableAutoRepeat( TRUE );
653
60acb947
VZ
654 if (!wxApp::Initialize())
655 return -1;
0cf2cb36 656
ec758a20 657 if (!wxTheApp)
c801d85f 658 {
60acb947 659 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
9cc7a35d 660 _T("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
0cf2cb36 661
ec758a20 662 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
0cf2cb36 663
ec758a20 664 wxObject *test_app = app_ini();
0cf2cb36 665
ec758a20
RR
666 wxTheApp = (wxApp*) test_app;
667 }
0cf2cb36 668
9cc7a35d 669 wxCHECK_MSG( wxTheApp, -1, _T("wxWindows error: no application object") );
c801d85f 670
ec758a20
RR
671 wxTheApp->argc = argc;
672 wxTheApp->argv = argv;
0cf2cb36 673
8801832d 674 wxString name(wxFileNameFromPath(argv[0]));
ec758a20
RR
675 wxStripExtension( name );
676 wxTheApp->SetAppName( name );
e0253070 677
0151c3eb
VZ
678 int retValue = 0;
679
680 if ( !wxTheApp->OnInitGui() )
681 retValue = -1;
c801d85f 682
8801832d
VZ
683 // Here frames insert themselves automatically into wxTopLevelWindows by
684 // getting created in OnInit().
0151c3eb
VZ
685 if ( retValue == 0 )
686 {
687 if ( !wxTheApp->OnInit() )
688 retValue = -1;
689 }
0cf2cb36 690
0151c3eb
VZ
691 if ( retValue == 0 )
692 {
cfb50f14
RR
693 /* delete pending toplevel windows (typically a single
694 dialog) so that, if there isn't any left, we don't
695 call OnRun() */
696 wxTheApp->DeletePendingObjects();
697
0151c3eb 698 wxTheApp->m_initialized = wxTopLevelWindows.GetCount() != 0;
0cf2cb36 699
0151c3eb 700 if (wxTheApp->Initialized())
cfb50f14 701 {
0151c3eb 702 retValue = wxTheApp->OnRun();
0cf2cb36 703
cfb50f14
RR
704 wxWindow *topWindow = wxTheApp->GetTopWindow();
705 if (topWindow)
0151c3eb 706 {
cfb50f14
RR
707 /* Forcibly delete the window. */
708 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
709 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
710 {
711 topWindow->Close( TRUE );
712 wxTheApp->DeletePendingObjects();
713 }
714 else
715 {
716 delete topWindow;
717 wxTheApp->SetTopWindow( (wxWindow*) NULL );
718 }
719 }
720 wxTheApp->OnExit();
0d2a2b60 721 }
0151c3eb 722 }
0cf2cb36 723
60acb947 724 // flush the logged messages if any
0d2a2b60
RR
725 wxLog *log = wxLog::GetActiveTarget();
726 if (log != NULL && log->HasPendingMessages())
727 log->Flush();
728
60acb947
VZ
729 // continuing to use user defined log target is unsafe from now on because
730 // some resources may be already unavailable, so replace it by something
731 // more safe
732 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
733 if ( oldlog )
734 delete oldlog;
735
0d2a2b60 736 wxApp::CleanUp();
184b5d99 737
ec758a20 738 return retValue;
ff7b1510 739}
1a56f55c 740