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