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