]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/app.cpp
dec83867a09766dfb70044a0bd1c1faffbc6e1cb
[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 #if wxUSE_WX_RESOURCES
23 #include "wx/resource.h"
24 #endif
25 #include "wx/module.h"
26 #include "wx/image.h"
27 #if wxUSE_THREADS
28 #include "wx/thread.h"
29 #endif
30 #include "unistd.h"
31
32 #include "glib.h"
33 #include "gdk/gdk.h"
34 #include "gtk/gtk.h"
35 #include "wx/gtk/win_gtk.h"
36
37 //-----------------------------------------------------------------------------
38 // global data
39 //-----------------------------------------------------------------------------
40
41 wxApp *wxTheApp = (wxApp *) NULL;
42 wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL;
43
44 extern wxList wxPendingDelete;
45 extern wxResourceCache *wxTheResourceCache;
46
47 GdkVisual *wxVisualSetByExternal = (GdkVisual*) NULL;
48 GdkColormap *wxColormapSetByExternal = (GdkColormap*) NULL;
49
50 unsigned 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,
100 0xf0, 0xa8, 0xef,
101 0xd0, 0x88, 0xd0,
102 0xaf, 0x66, 0xaf,
103 0x8e, 0x44, 0x8e,
104 0x6d, 0x22, 0x6d,
105 0x4b, 0x0, 0x4b,
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
118 //-----------------------------------------------------------------------------
119 // local functions
120 //-----------------------------------------------------------------------------
121
122 extern void wxFlushResources(void);
123
124 //-----------------------------------------------------------------------------
125 // global functions
126 //-----------------------------------------------------------------------------
127
128 void wxExit(void)
129 {
130 gtk_main_quit();
131 }
132
133 bool wxYield(void)
134 {
135 while (gtk_events_pending() > 0) gtk_main_iteration();
136 return TRUE;
137 }
138
139 //-----------------------------------------------------------------------------
140 // wxApp
141 //-----------------------------------------------------------------------------
142
143 IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
144
145 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
146 EVT_IDLE(wxApp::OnIdle)
147 END_EVENT_TABLE()
148
149 gint wxapp_idle_callback( gpointer WXUNUSED(data) )
150 {
151 if (wxTheApp) while (wxTheApp->ProcessIdle()) {}
152 #if wxUSE_THREADS
153 wxMutexGuiLeave();
154 #endif
155 usleep(10000);
156 #if wxUSE_THREADS
157 wxMutexGuiEnter();
158 #endif
159 return TRUE;
160 }
161
162 wxApp::wxApp()
163 {
164 m_idleTag = 0;
165 m_topWindow = (wxWindow *) NULL;
166 m_exitOnFrameDelete = TRUE;
167 wxTheApp = this;
168 }
169
170 wxApp::~wxApp(void)
171 {
172 gtk_idle_remove( m_idleTag );
173 }
174
175 bool wxApp::InitVisual()
176 {
177 if (wxVisualSetByExternal)
178 {
179 /* this happens in the wxModule code of the OpenGl canvas.
180 it chooses the best display for OpenGl and stores it
181 in wxDisplaySetByExternal. we then have to make it the
182 default for the system */
183
184 gtk_widget_set_default_visual( wxVisualSetByExternal );
185 }
186
187 if (wxColormapSetByExternal)
188 {
189 /* OpenGl also gives us a colormap */
190
191 gtk_widget_set_default_colormap( wxColormapSetByExternal );
192 }
193 else
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
201 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
202
203 for (int i = 0; i < 64; i++)
204 {
205 GdkColor col;
206 col.red = g_palette[i*3 + 0] << 8;
207 col.green = g_palette[i*3 + 1] << 8;
208 col.blue = g_palette[i*3 + 2] << 8;
209 col.pixel = 0;
210
211 gdk_color_alloc( cmap, &col );
212 }
213
214 gtk_widget_set_default_colormap( cmap );
215 }
216
217 return TRUE;
218 }
219
220 bool wxApp::OnInitGui(void)
221 {
222 m_idleTag = gtk_idle_add( wxapp_idle_callback, NULL );
223
224 return TRUE;
225 }
226
227 bool wxApp::OnInit(void)
228 {
229 return TRUE;
230 }
231
232 int wxApp::OnRun(void)
233 {
234 return MainLoop();
235 }
236
237 bool wxApp::ProcessIdle(void)
238 {
239 wxIdleEvent event;
240 event.SetEventObject( this );
241 ProcessEvent( event );
242
243 return event.MoreRequested();
244 }
245
246 void wxApp::OnIdle( wxIdleEvent &event )
247 {
248 static bool inOnIdle = FALSE;
249
250 /* Avoid recursion (via ProcessEvent default case) */
251 if (inOnIdle)
252 return;
253
254 inOnIdle = TRUE;
255
256 /* 'Garbage' collection of windows deleted with Close(). */
257 DeletePendingObjects();
258
259 /* flush the logged messages if any */
260 wxLog *log = wxLog::GetActiveTarget();
261 if (log != NULL && log->HasPendingMessages())
262 log->Flush();
263
264 /* Send OnIdle events to all windows */
265 bool needMore = SendIdleEvents();
266
267 if (needMore)
268 event.RequestMore(TRUE);
269
270 inOnIdle = FALSE;
271 }
272
273 bool wxApp::SendIdleEvents(void)
274 {
275 bool needMore = FALSE;
276
277 wxNode* node = wxTopLevelWindows.First();
278 while (node)
279 {
280 wxWindow* win = (wxWindow*) node->Data();
281 if (SendIdleEvents(win))
282 needMore = TRUE;
283 node = node->Next();
284 }
285 return needMore;
286 }
287
288 bool wxApp::SendIdleEvents( wxWindow* win )
289 {
290 bool needMore = FALSE;
291
292 wxIdleEvent event;
293 event.SetEventObject(win);
294 win->ProcessEvent(event);
295
296 if (event.MoreRequested())
297 needMore = TRUE;
298
299 wxNode* node = win->GetChildren().First();
300 while (node)
301 {
302 wxWindow* win = (wxWindow*) node->Data();
303 if (SendIdleEvents(win))
304 needMore = TRUE;
305
306 node = node->Next();
307 }
308 return needMore ;
309 }
310
311 int wxApp::OnExit(void)
312 {
313 return 0;
314 }
315
316 int wxApp::MainLoop(void)
317 {
318 gtk_main();
319 return 0;
320 }
321
322 void wxApp::ExitMainLoop(void)
323 {
324 gtk_main_quit();
325 }
326
327 bool wxApp::Initialized(void)
328 {
329 return m_initialized;
330 }
331
332 bool wxApp::Pending(void)
333 {
334 return FALSE;
335 }
336
337 void wxApp::Dispatch(void)
338 {
339 }
340
341 void wxApp::DeletePendingObjects(void)
342 {
343 wxNode *node = wxPendingDelete.First();
344 while (node)
345 {
346 wxObject *obj = (wxObject *)node->Data();
347
348 delete obj;
349
350 if (wxPendingDelete.Member(obj))
351 delete node;
352
353 node = wxPendingDelete.First();
354 }
355 }
356
357 wxWindow *wxApp::GetTopWindow(void)
358 {
359 if (m_topWindow) return m_topWindow;
360 wxNode *node = wxTopLevelWindows.First();
361 if (!node) return (wxWindow *) NULL;
362 return (wxWindow*)node->Data();
363 }
364
365 void wxApp::SetTopWindow( wxWindow *win )
366 {
367 m_topWindow = win;
368 }
369
370 void wxApp::CommonInit(void)
371 {
372 wxSystemSettings::Init();
373
374 wxTheFontNameDirectory = new wxFontNameDirectory;
375 wxTheFontNameDirectory->Initialize();
376
377 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
378 wxTheColourDatabase->Initialize();
379
380 wxInitializeStockLists();
381 wxInitializeStockObjects();
382
383 #if wxUSE_WX_RESOURCES
384 wxTheResourceCache = new wxResourceCache(wxKEY_STRING);
385
386 wxInitializeResourceSystem();
387 #endif
388
389 wxImage::InitStandardHandlers();
390
391 // g_globalCursor = new wxCursor;
392 }
393
394 void wxApp::CommonCleanUp(void)
395 {
396 if (wxTheColourDatabase) delete wxTheColourDatabase;
397 wxTheColourDatabase = (wxColourDatabase*) NULL;
398
399 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
400 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
401
402 wxDeleteStockObjects();
403
404 #if wxUSE_WX_RESOURCES
405 wxFlushResources();
406
407 if (wxTheResourceCache) delete wxTheResourceCache;
408 wxTheResourceCache = (wxResourceCache*) NULL;
409
410 wxCleanUpResourceSystem();
411 #endif
412
413 wxDeleteStockLists();
414
415 wxImage::CleanUpHandlers();
416
417 wxSystemSettings::Done();
418 }
419
420 wxLog *wxApp::CreateLogTarget()
421 {
422 return new wxLogGui;
423 }
424
425 //-----------------------------------------------------------------------------
426 // wxEntry
427 //-----------------------------------------------------------------------------
428
429 int wxEntry( int argc, char *argv[] )
430 {
431 wxBuffer = new char[BUFSIZ + 512];
432
433 wxClassInfo::InitializeClasses();
434
435
436 if (!wxTheApp)
437 {
438 if (!wxApp::GetInitializerFunction())
439 {
440 printf( "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
441 return 0;
442 }
443
444 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
445
446 wxObject *test_app = app_ini();
447
448 wxTheApp = (wxApp*) test_app;
449 }
450
451 if (!wxTheApp)
452 {
453 printf( "wxWindows error: wxTheApp == NULL\n" );
454 return 0;
455 }
456
457 wxTheApp->argc = argc;
458 wxTheApp->argv = argv;
459
460 char name[200];
461 strcpy( name, argv[0] );
462 strcpy( name, wxFileNameFromPath(name) );
463 wxStripExtension( name );
464 wxTheApp->SetAppName( name );
465
466 gtk_set_locale();
467
468 gtk_init( &argc, &argv );
469
470 wxModule::RegisterModules();
471 if (!wxModule::InitializeModules()) return FALSE;
472
473 if (!wxTheApp->InitVisual()) return 0;
474
475 wxApp::CommonInit();
476
477 if (!wxTheApp->OnInitGui()) return 0;
478
479 // Here frames insert themselves automatically
480 // into wxTopLevelWindows by getting created
481 // in OnInit().
482
483 if (!wxTheApp->OnInit()) return 0;
484
485 wxTheApp->m_initialized = (wxTopLevelWindows.Number() > 0);
486
487 int retValue = 0;
488
489 if (wxTheApp->Initialized()) retValue = wxTheApp->OnRun();
490
491 wxTheApp->DeletePendingObjects();
492
493 wxTheApp->OnExit();
494
495 wxModule::CleanUpModules();
496
497 wxApp::CommonCleanUp();
498
499 delete wxTheApp;
500 wxTheApp = (wxApp*) NULL;
501
502 wxClassInfo::CleanUpClasses();
503
504 delete[] wxBuffer;
505
506 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
507
508 if (wxDebugContext::CountObjectsLeft() > 0)
509 {
510 wxLogDebug("There were memory leaks.\n");
511 wxDebugContext::Dump();
512 wxDebugContext::PrintStatistics();
513 }
514
515 #endif
516
517 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
518 if (oldLog) delete oldLog;
519
520 return retValue;
521 }
522