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