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