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