]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/app.cpp
thread fixes (compiles, but doesn't work yet)
[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 win->ProcessEvent(event);
306
307 if (event.MoreRequested())
308 needMore = TRUE;
309
310 wxNode* node = win->GetChildren().First();
311 while (node)
312 {
313 wxWindow* win = (wxWindow*) node->Data();
314 if (SendIdleEvents(win))
315 needMore = TRUE;
316
317 node = node->Next();
318 }
319 return needMore ;
320 }
321
322 int wxApp::MainLoop(void)
323 {
324 gtk_main();
325 return 0;
326 }
327
328 void wxApp::ExitMainLoop(void)
329 {
330 gtk_main_quit();
331 }
332
333 bool wxApp::Initialized(void)
334 {
335 return m_initialized;
336 }
337
338 bool wxApp::Pending(void)
339 {
340 return FALSE;
341 }
342
343 void wxApp::Dispatch(void)
344 {
345 }
346
347 void wxApp::DeletePendingObjects(void)
348 {
349 wxNode *node = wxPendingDelete.First();
350 while (node)
351 {
352 wxObject *obj = (wxObject *)node->Data();
353
354 delete obj;
355
356 if (wxPendingDelete.Member(obj))
357 delete node;
358
359 node = wxPendingDelete.First();
360 }
361 }
362
363 wxWindow *wxApp::GetTopWindow(void)
364 {
365 if (m_topWindow) return m_topWindow;
366 wxNode *node = wxTopLevelWindows.First();
367 if (!node) return (wxWindow *) NULL;
368 return (wxWindow*)node->Data();
369 }
370
371 void wxApp::SetTopWindow( wxWindow *win )
372 {
373 m_topWindow = win;
374 }
375
376 bool wxApp::Initialize(void)
377 {
378 wxBuffer = new char[BUFSIZ + 512];
379
380 wxClassInfo::InitializeClasses();
381
382 wxSystemSettings::Init();
383
384 wxTheFontNameDirectory = new wxFontNameDirectory;
385 wxTheFontNameDirectory->Initialize();
386
387 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
388 wxTheColourDatabase->Initialize();
389
390 wxInitializeStockLists();
391 wxInitializeStockObjects();
392
393 #if wxUSE_WX_RESOURCES
394 wxTheResourceCache = new wxResourceCache( wxKEY_STRING );
395
396 wxInitializeResourceSystem();
397 #endif
398
399 wxImage::InitStandardHandlers();
400
401 /* no global cursor under X
402 g_globalCursor = new wxCursor; */
403
404 wxModule::RegisterModules();
405 if (!wxModule::InitializeModules()) return FALSE;
406
407 return TRUE;
408 }
409
410 void wxApp::CleanUp(void)
411 {
412 wxModule::CleanUpModules();
413
414 #if wxUSE_WX_RESOURCES
415 wxFlushResources();
416
417 if (wxTheResourceCache) delete wxTheResourceCache;
418 wxTheResourceCache = (wxResourceCache*) NULL;
419
420 wxCleanUpResourceSystem();
421 #endif
422
423 if (wxTheColourDatabase) delete wxTheColourDatabase;
424 wxTheColourDatabase = (wxColourDatabase*) NULL;
425
426 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
427 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
428
429 wxDeleteStockObjects();
430
431 wxDeleteStockLists();
432
433 wxImage::CleanUpHandlers();
434
435 delete wxTheApp;
436 wxTheApp = (wxApp*) NULL;
437
438 /* check for memory leaks */
439 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
440 if (wxDebugContext::CountObjectsLeft() > 0)
441 {
442 wxLogDebug("There were memory leaks.\n");
443 wxDebugContext::Dump();
444 wxDebugContext::PrintStatistics();
445 }
446 #endif
447
448 /* do this as the very last thing because everything else can log messages */
449 wxLog::DontCreateOnDemand();
450
451 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
452 if (oldLog) delete oldLog;
453
454 wxSystemSettings::Done();
455
456 wxClassInfo::CleanUpClasses();
457
458 delete[] wxBuffer;
459 }
460
461 wxLog *wxApp::CreateLogTarget()
462 {
463 return new wxLogGui;
464 }
465
466 //-----------------------------------------------------------------------------
467 // wxEntry
468 //-----------------------------------------------------------------------------
469
470 int wxEntry( int argc, char *argv[] )
471 {
472 gtk_set_locale();
473
474 gtk_init( &argc, &argv );
475
476 if (!wxApp::Initialize()) return 0;
477
478 if (!wxTheApp)
479 {
480 if (!wxApp::GetInitializerFunction())
481 {
482 printf( "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
483 return 0;
484 }
485
486 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
487
488 wxObject *test_app = app_ini();
489
490 wxTheApp = (wxApp*) test_app;
491 }
492
493 if (!wxTheApp)
494 {
495 printf( "wxWindows error: wxTheApp == NULL\n" );
496 return 0;
497 }
498
499 wxTheApp->argc = argc;
500 wxTheApp->argv = argv;
501
502 char name[200];
503 strcpy( name, argv[0] );
504 strcpy( name, wxFileNameFromPath(name) );
505 wxStripExtension( name );
506 wxTheApp->SetAppName( name );
507
508 if (!wxTheApp->OnInitGui()) return 0;
509
510 /* Here frames insert themselves automatically
511 * into wxTopLevelWindows by getting created
512 * in OnInit(). */
513
514 if (!wxTheApp->OnInit()) return 0;
515
516 wxTheApp->m_initialized = (wxTopLevelWindows.Number() > 0);
517
518 int retValue = 0;
519
520 if (wxTheApp->Initialized()) retValue = wxTheApp->OnRun();
521
522 wxWindow *topWindow = wxTheApp->GetTopWindow();
523 if (topWindow)
524 {
525 /* Forcibly delete the window. */
526 if (topWindow->IsKindOf(CLASSINFO(wxFrame)) ||
527 topWindow->IsKindOf(CLASSINFO(wxDialog)) )
528 {
529 topWindow->Close( TRUE );
530 wxTheApp->DeletePendingObjects();
531 }
532 else
533 {
534 delete topWindow;
535 wxTheApp->SetTopWindow( (wxWindow*) NULL );
536 }
537 }
538
539 wxTheApp->OnExit();
540
541 /* flush the logged messages if any */
542 wxLog *log = wxLog::GetActiveTarget();
543 if (log != NULL && log->HasPendingMessages())
544 log->Flush();
545
546 wxApp::CleanUp();
547
548 return retValue;
549 }
550