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