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