]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/app.cpp
warnings suppressed
[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__
11#pragma implementation "app.h"
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"
06cfab17 23#if wxUSE_WX_RESOURCES
8d71b555 24#include "wx/resource.h"
f5abe911 25#endif
031b2a7b 26#include "wx/module.h"
4bc67cc5 27#include "wx/image.h"
06cfab17 28#if wxUSE_THREADS
f3855ef0 29#include "wx/thread.h"
ac57418f 30#endif
c801d85f
KB
31#include "unistd.h"
32
539dae52
VZ
33// many versions of Unices have this function, but it is not defined in system
34// headers - please add your system here if it is the case for your OS.
35// SunOS < 5.6 (i.e. Solaris < 2.6) and DG-UX are like this.
36#if (defined(__SUN__) && !defined(__SunOs_5_6) && \
37 !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \
38 defined(__osf__)
60acb947 39 extern "C"
539dae52 40 {
60acb947 41 void usleep(unsigned long usec);
539dae52
VZ
42 };
43#endif // Unices without usleep()
24178e4a 44
83624f79
RR
45#include "glib.h"
46#include "gdk/gdk.h"
47#include "gtk/gtk.h"
48#include "wx/gtk/win_gtk.h"
49
69919241
KB
50#include <unistd.h> // usleep() on solaris
51
c801d85f
KB
52//-----------------------------------------------------------------------------
53// global data
54//-----------------------------------------------------------------------------
55
c67daf87 56wxApp *wxTheApp = (wxApp *) NULL;
c801d85f
KB
57wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL;
58
59extern wxList wxPendingDelete;
a3622daa 60extern wxResourceCache *wxTheResourceCache;
c801d85f 61
01111366
RR
62unsigned char g_palette[64*3] =
63{
64 0x0, 0x0, 0x0,
65 0xff, 0xff, 0xff,
66 0xff, 0x0, 0x0,
67 0xff, 0xff, 0x0,
68 0x0, 0xff, 0x0,
69 0x0, 0x0, 0xff,
70 0x0, 0xff, 0xff,
71 0x99, 0x99, 0x99,
72 0xff, 0x88, 0x0,
73 0x88, 0x0, 0x0,
74 0x0, 0x88, 0x88,
75 0x88, 0x88, 0x0,
76 0xff, 0xcc, 0x97,
77 0xbb, 0xbb, 0xbb,
78 0x9f, 0x6b, 0x42,
79 0x55, 0x55, 0x55,
80 0xdd, 0xdd, 0xdd,
81 0x77, 0x77, 0x77,
82 0x33, 0x33, 0x33,
83 0xcc, 0x0, 0x0,
84 0xff, 0x44, 0x0,
85 0xff, 0xcc, 0x0,
86 0xcc, 0xcc, 0x0,
87 0x60, 0x60, 0x0,
88 0x0, 0x43, 0x0,
89 0x0, 0x7f, 0x0,
90 0x0, 0xcc, 0x0,
91 0x0, 0x44, 0x44,
92 0x0, 0x0, 0x44,
93 0x0, 0x0, 0x88,
94 0xef, 0xb1, 0x7b,
95 0xdf, 0x98, 0x5f,
96 0xbf, 0x87, 0x56,
97 0x7f, 0x57, 0x26,
98 0x5f, 0x39, 0xc,
99 0x3f, 0x1c, 0x0,
100 0x21, 0x0, 0x0,
101 0x0, 0x43, 0x87,
102 0x2d, 0x70, 0xaf,
103 0x5a, 0x9e, 0xd7,
104 0x87, 0xcc, 0xff,
105 0xff, 0xe0, 0xba,
106 0x21, 0x43, 0xf,
107 0x3d, 0x5d, 0x25,
108 0x59, 0x78, 0x3a,
109 0x75, 0x93, 0x4f,
110 0x91, 0xae, 0x64,
111 0xad, 0xc8, 0x7a,
e0253070 112 0xf0, 0xa8, 0xef,
01111366
RR
113 0xd0, 0x88, 0xd0,
114 0xaf, 0x66, 0xaf,
115 0x8e, 0x44, 0x8e,
116 0x6d, 0x22, 0x6d,
e0253070 117 0x4b, 0x0, 0x4b,
01111366
RR
118 0xff, 0xc0, 0xbc,
119 0xff, 0x93, 0x91,
120 0xff, 0x66, 0x67,
121 0xd8, 0xf2, 0xbf,
122 0xff, 0xc9, 0x68,
123 0xff, 0x96, 0x67,
124 0xa5, 0x60, 0xff,
125 0x51, 0xff, 0x99,
126 0x3f, 0xa5, 0x63,
127 0x98, 0x90, 0x67
128};
129
c801d85f
KB
130//-----------------------------------------------------------------------------
131// local functions
132//-----------------------------------------------------------------------------
133
134extern void wxFlushResources(void);
135
136//-----------------------------------------------------------------------------
137// global functions
138//-----------------------------------------------------------------------------
139
60acb947 140void wxExit()
c801d85f 141{
ec758a20 142 gtk_main_quit();
ff7b1510 143}
c801d85f 144
60acb947 145bool wxYield()
c801d85f 146{
ec758a20
RR
147 while (gtk_events_pending() > 0) gtk_main_iteration();
148 return TRUE;
ff7b1510 149}
c801d85f
KB
150
151//-----------------------------------------------------------------------------
152// wxApp
153//-----------------------------------------------------------------------------
154
155IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
156
53010e52
RR
157BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
158 EVT_IDLE(wxApp::OnIdle)
159END_EVENT_TABLE()
160
c801d85f
KB
161gint wxapp_idle_callback( gpointer WXUNUSED(data) )
162{
ec758a20 163 if (wxTheApp) while (wxTheApp->ProcessIdle()) {}
06cfab17 164#if wxUSE_THREADS
f3855ef0 165 wxMutexGuiLeave();
ac57418f 166#endif
f3855ef0 167 usleep(10000);
06cfab17 168#if wxUSE_THREADS
f3855ef0 169 wxMutexGuiEnter();
ac57418f 170#endif
ec758a20 171 return TRUE;
ff7b1510 172}
c801d85f
KB
173
174wxApp::wxApp()
175{
0d2a2b60 176 wxTheApp = this;
60acb947 177
ec758a20
RR
178 m_topWindow = (wxWindow *) NULL;
179 m_exitOnFrameDelete = TRUE;
60acb947 180
0d2a2b60 181 m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
60acb947 182
f6fcbb63 183 m_colorCube = (unsigned char*) NULL;
ff7b1510 184}
c801d85f 185
60acb947 186wxApp::~wxApp()
c801d85f 187{
ec758a20 188 gtk_idle_remove( m_idleTag );
60acb947 189
f6fcbb63 190 if (m_colorCube) free(m_colorCube);
ff7b1510 191}
c801d85f 192
0d2a2b60 193bool wxApp::OnInitGui()
c801d85f 194{
f6fcbb63
RR
195 /* Nothing to do for 15, 16, 24, 32 bit displays */
196
197 GdkVisual *visual = gdk_visual_get_system();
198 if (visual->depth > 8) return TRUE;
60acb947 199
0d2a2b60
RR
200 /* this initiates the standard palette as defined by GdkImlib
201 in the GNOME libraries. it ensures that all GNOME applications
202 use the same 64 colormap entries on 8-bit displays so you
203 can use several rather graphics-heavy applications at the
204 same time.
205 NOTE: this doesn't really seem to work this way... */
bbe0af5b 206
0d2a2b60
RR
207 /*
208 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
bbe0af5b 209
0d2a2b60
RR
210 for (int i = 0; i < 64; i++)
211 {
212 GdkColor col;
213 col.red = g_palette[i*3 + 0] << 8;
214 col.green = g_palette[i*3 + 1] << 8;
215 col.blue = g_palette[i*3 + 2] << 8;
216 col.pixel = 0;
217
218 gdk_color_alloc( cmap, &col );
219 }
60acb947 220
0d2a2b60
RR
221 gtk_widget_set_default_colormap( cmap );
222 */
60acb947 223
f6fcbb63 224 /* initialize color cube for 8-bit color reduction dithering */
60acb947 225
f6fcbb63 226 GdkColormap *cmap = gtk_widget_get_default_colormap();
60acb947 227
f6fcbb63
RR
228 m_colorCube = (unsigned char*)malloc(32 * 32 * 32);
229
230 for (int r = 0; r < 32; r++)
231 {
232 for (int g = 0; g < 32; g++)
233 {
234 for (int b = 0; b < 32; b++)
235 {
236 int rr = (r << 3) | (r >> 2);
237 int gg = (g << 3) | (g >> 2);
238 int bb = (b << 3) | (b >> 2);
60acb947 239
f6fcbb63
RR
240 GdkColor *colors = cmap->colors;
241 int max = 3 * (65536);
242 int index = -1;
243
244 for (int i = 0; i < cmap->size; i++)
245 {
246 int rdiff = ((rr << 8) - colors[i].red);
247 int gdiff = ((gg << 8)- colors[i].green);
248 int bdiff = ((bb << 8)- colors[i].blue);
249 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
250 if (sum < max) { index = i; max = sum; }
251 }
60acb947 252
f6fcbb63
RR
253 m_colorCube[ (r*1024) + (g*32) + b ] = index;
254 }
255 }
256 }
c801d85f 257
60acb947 258
bbe0af5b
RR
259 return TRUE;
260}
261
60acb947 262bool wxApp::ProcessIdle()
53010e52 263{
ec758a20
RR
264 wxIdleEvent event;
265 event.SetEventObject( this );
266 ProcessEvent( event );
0cf2cb36 267
ec758a20 268 return event.MoreRequested();
ff7b1510 269}
53010e52
RR
270
271void wxApp::OnIdle( wxIdleEvent &event )
c801d85f 272{
ec758a20 273 static bool inOnIdle = FALSE;
53010e52 274
d524867f 275 /* Avoid recursion (via ProcessEvent default case) */
ec758a20
RR
276 if (inOnIdle)
277 return;
53010e52 278
ec758a20 279 inOnIdle = TRUE;
53010e52 280
d524867f 281 /* 'Garbage' collection of windows deleted with Close(). */
ec758a20 282 DeletePendingObjects();
53010e52 283
d524867f
RR
284 /* flush the logged messages if any */
285 wxLog *log = wxLog::GetActiveTarget();
286 if (log != NULL && log->HasPendingMessages())
287 log->Flush();
53010e52 288
d524867f 289 /* Send OnIdle events to all windows */
ec758a20 290 bool needMore = SendIdleEvents();
53010e52 291
ec758a20
RR
292 if (needMore)
293 event.RequestMore(TRUE);
53010e52 294
ec758a20 295 inOnIdle = FALSE;
ff7b1510 296}
53010e52 297
60acb947 298bool wxApp::SendIdleEvents()
53010e52
RR
299{
300 bool needMore = FALSE;
e0253070 301
ec758a20
RR
302 wxNode* node = wxTopLevelWindows.First();
303 while (node)
304 {
f3855ef0
RR
305 wxWindow* win = (wxWindow*) node->Data();
306 if (SendIdleEvents(win))
53010e52 307 needMore = TRUE;
ec758a20
RR
308 node = node->Next();
309 }
53010e52 310 return needMore;
ff7b1510 311}
53010e52
RR
312
313bool wxApp::SendIdleEvents( wxWindow* win )
314{
315 bool needMore = FALSE;
316
8bbe427f
VZ
317 wxIdleEvent event;
318 event.SetEventObject(win);
60acb947 319
9390a202 320 win->OnInternalIdle();
60acb947 321
8bbe427f 322 win->ProcessEvent(event);
53010e52
RR
323
324 if (event.MoreRequested())
325 needMore = TRUE;
326
8bbe427f
VZ
327 wxNode* node = win->GetChildren().First();
328 while (node)
329 {
330 wxWindow* win = (wxWindow*) node->Data();
331 if (SendIdleEvents(win))
53010e52
RR
332 needMore = TRUE;
333
8bbe427f
VZ
334 node = node->Next();
335 }
53010e52 336 return needMore ;
ff7b1510 337}
c801d85f 338
60acb947 339int wxApp::MainLoop()
c801d85f 340{
ec758a20
RR
341 gtk_main();
342 return 0;
ff7b1510 343}
c801d85f 344
60acb947 345void wxApp::ExitMainLoop()
c801d85f 346{
ec758a20 347 gtk_main_quit();
ff7b1510 348}
c801d85f 349
60acb947 350bool wxApp::Initialized()
c801d85f 351{
ec758a20 352 return m_initialized;
ff7b1510 353}
c801d85f 354
60acb947 355bool wxApp::Pending()
c801d85f 356{
ec758a20 357 return FALSE;
ff7b1510 358}
c801d85f 359
60acb947 360void wxApp::Dispatch()
c801d85f 361{
ff7b1510 362}
c801d85f 363
60acb947 364void wxApp::DeletePendingObjects()
c801d85f 365{
ec758a20
RR
366 wxNode *node = wxPendingDelete.First();
367 while (node)
368 {
369 wxObject *obj = (wxObject *)node->Data();
0cf2cb36 370
ec758a20 371 delete obj;
c801d85f 372
ec758a20
RR
373 if (wxPendingDelete.Member(obj))
374 delete node;
c801d85f 375
ec758a20
RR
376 node = wxPendingDelete.First();
377 }
ff7b1510 378}
c801d85f 379
60acb947 380wxWindow *wxApp::GetTopWindow()
c801d85f 381{
ec758a20
RR
382 if (m_topWindow) return m_topWindow;
383 wxNode *node = wxTopLevelWindows.First();
384 if (!node) return (wxWindow *) NULL;
385 return (wxWindow*)node->Data();
ff7b1510 386}
c801d85f
KB
387
388void wxApp::SetTopWindow( wxWindow *win )
389{
ec758a20 390 m_topWindow = win;
ff7b1510 391}
c801d85f 392
60acb947 393bool wxApp::Initialize()
c801d85f 394{
0d2a2b60
RR
395 wxBuffer = new char[BUFSIZ + 512];
396
397 wxClassInfo::InitializeClasses();
60acb947 398
0d2a2b60 399 wxSystemSettings::Init();
60acb947 400
36b3b54a 401/*
0d2a2b60
RR
402 wxTheFontNameDirectory = new wxFontNameDirectory;
403 wxTheFontNameDirectory->Initialize();
36b3b54a 404*/
c801d85f 405
0d2a2b60
RR
406 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
407 wxTheColourDatabase->Initialize();
a3622daa 408
0d2a2b60
RR
409 wxInitializeStockLists();
410 wxInitializeStockObjects();
c801d85f 411
06cfab17 412#if wxUSE_WX_RESOURCES
0d2a2b60 413 wxTheResourceCache = new wxResourceCache( wxKEY_STRING );
60acb947 414
0d2a2b60 415 wxInitializeResourceSystem();
f5abe911 416#endif
0cf2cb36 417
0d2a2b60 418 wxImage::InitStandardHandlers();
e0253070 419
0d2a2b60
RR
420 /* no global cursor under X
421 g_globalCursor = new wxCursor; */
60acb947 422
0d2a2b60
RR
423 wxModule::RegisterModules();
424 if (!wxModule::InitializeModules()) return FALSE;
60acb947 425
0d2a2b60 426 return TRUE;
ff7b1510 427}
c801d85f 428
60acb947 429void wxApp::CleanUp()
c801d85f 430{
0d2a2b60 431 wxModule::CleanUpModules();
0cf2cb36 432
06cfab17 433#if wxUSE_WX_RESOURCES
ec758a20 434 wxFlushResources();
a3622daa 435
60acb947
VZ
436 if (wxTheResourceCache)
437 delete wxTheResourceCache;
bbe0af5b 438 wxTheResourceCache = (wxResourceCache*) NULL;
60acb947 439
f5abe911
RR
440 wxCleanUpResourceSystem();
441#endif
a3622daa 442
60acb947
VZ
443 if (wxTheColourDatabase)
444 delete wxTheColourDatabase;
0d2a2b60 445 wxTheColourDatabase = (wxColourDatabase*) NULL;
60acb947 446
36b3b54a 447/*
0d2a2b60
RR
448 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
449 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
36b3b54a 450*/
60acb947 451
0d2a2b60
RR
452 wxDeleteStockObjects();
453
ec758a20 454 wxDeleteStockLists();
a3622daa 455
ec758a20 456 wxImage::CleanUpHandlers();
0cf2cb36 457
0d2a2b60
RR
458 delete wxTheApp;
459 wxTheApp = (wxApp*) NULL;
460
3e61c765 461 wxSystemSettings::Done();
60acb947 462
3e61c765
RR
463 delete[] wxBuffer;
464
465 wxClassInfo::CleanUpClasses();
60acb947
VZ
466
467 // check for memory leaks
0d2a2b60
RR
468#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
469 if (wxDebugContext::CountObjectsLeft() > 0)
470 {
471 wxLogDebug("There were memory leaks.\n");
472 wxDebugContext::Dump();
473 wxDebugContext::PrintStatistics();
474 }
475#endif
476
60acb947 477 // do this as the very last thing because everything else can log messages
0d2a2b60 478 wxLog::DontCreateOnDemand();
60acb947 479
0d2a2b60 480 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
60acb947
VZ
481 if (oldLog)
482 delete oldLog;
ff7b1510 483}
0cf2cb36 484
c801d85f
KB
485wxLog *wxApp::CreateLogTarget()
486{
0d2a2b60 487 return new wxLogGui;
c801d85f
KB
488}
489
490//-----------------------------------------------------------------------------
491// wxEntry
492//-----------------------------------------------------------------------------
493
494int wxEntry( int argc, char *argv[] )
495{
0d2a2b60 496 gtk_set_locale();
c801d85f 497
0d2a2b60 498 gtk_init( &argc, &argv );
0cf2cb36 499
60acb947
VZ
500 if (!wxApp::Initialize())
501 return -1;
0cf2cb36 502
ec758a20 503 if (!wxTheApp)
c801d85f 504 {
60acb947
VZ
505 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
506 "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
0cf2cb36 507
ec758a20 508 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
0cf2cb36 509
ec758a20 510 wxObject *test_app = app_ini();
0cf2cb36 511
ec758a20
RR
512 wxTheApp = (wxApp*) test_app;
513 }
0cf2cb36 514
60acb947 515 wxCHECK_MSG( wxTheApp, -1, "wxWindows error: no application object" );
c801d85f 516
ec758a20
RR
517 wxTheApp->argc = argc;
518 wxTheApp->argv = argv;
0cf2cb36 519
ec758a20
RR
520 char name[200];
521 strcpy( name, argv[0] );
522 strcpy( name, wxFileNameFromPath(name) );
523 wxStripExtension( name );
524 wxTheApp->SetAppName( name );
e0253070 525
60acb947
VZ
526 if (!wxTheApp->OnInitGui())
527 return 0;
c801d85f 528
0d2a2b60
RR
529 /* Here frames insert themselves automatically
530 * into wxTopLevelWindows by getting created
531 * in OnInit(). */
0cf2cb36 532
60acb947
VZ
533 if (!wxTheApp->OnInit())
534 return 0;
c801d85f 535
ec758a20 536 wxTheApp->m_initialized = (wxTopLevelWindows.Number() > 0);
0cf2cb36 537
ec758a20 538 int retValue = 0;
0cf2cb36 539
60acb947
VZ
540 if (wxTheApp->Initialized())
541 retValue = wxTheApp->OnRun();
0cf2cb36 542
0d2a2b60
RR
543 wxWindow *topWindow = wxTheApp->GetTopWindow();
544 if (topWindow)
ec758a20 545 {
60acb947 546 // Forcibly delete the window.
0d2a2b60
RR
547 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
548 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
549 {
550 topWindow->Close( TRUE );
551 wxTheApp->DeletePendingObjects();
552 }
553 else
554 {
555 delete topWindow;
556 wxTheApp->SetTopWindow( (wxWindow*) NULL );
557 }
ec758a20 558 }
e0253070 559
0d2a2b60 560 wxTheApp->OnExit();
0cf2cb36 561
60acb947 562 // flush the logged messages if any
0d2a2b60
RR
563 wxLog *log = wxLog::GetActiveTarget();
564 if (log != NULL && log->HasPendingMessages())
565 log->Flush();
566
60acb947
VZ
567 // continuing to use user defined log target is unsafe from now on because
568 // some resources may be already unavailable, so replace it by something
569 // more safe
570 wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr);
571 if ( oldlog )
572 delete oldlog;
573
0d2a2b60 574 wxApp::CleanUp();
184b5d99 575
ec758a20 576 return retValue;
ff7b1510 577}
1a56f55c 578