]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/app.cpp
thread fixes (compiles, but doesn't work yet)
[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
c801d85f
KB
38//-----------------------------------------------------------------------------
39// global data
40//-----------------------------------------------------------------------------
41
c67daf87 42wxApp *wxTheApp = (wxApp *) NULL;
c801d85f
KB
43wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL;
44
45extern wxList wxPendingDelete;
a3622daa 46extern wxResourceCache *wxTheResourceCache;
c801d85f 47
01111366
RR
48unsigned 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,
e0253070 98 0xf0, 0xa8, 0xef,
01111366
RR
99 0xd0, 0x88, 0xd0,
100 0xaf, 0x66, 0xaf,
101 0x8e, 0x44, 0x8e,
102 0x6d, 0x22, 0x6d,
e0253070 103 0x4b, 0x0, 0x4b,
01111366
RR
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
c801d85f
KB
116//-----------------------------------------------------------------------------
117// local functions
118//-----------------------------------------------------------------------------
119
120extern void wxFlushResources(void);
121
122//-----------------------------------------------------------------------------
123// global functions
124//-----------------------------------------------------------------------------
125
126void wxExit(void)
127{
ec758a20 128 gtk_main_quit();
ff7b1510 129}
c801d85f
KB
130
131bool wxYield(void)
132{
ec758a20
RR
133 while (gtk_events_pending() > 0) gtk_main_iteration();
134 return TRUE;
ff7b1510 135}
c801d85f
KB
136
137//-----------------------------------------------------------------------------
138// wxApp
139//-----------------------------------------------------------------------------
140
141IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
142
53010e52
RR
143BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
144 EVT_IDLE(wxApp::OnIdle)
145END_EVENT_TABLE()
146
c801d85f
KB
147gint wxapp_idle_callback( gpointer WXUNUSED(data) )
148{
ec758a20 149 if (wxTheApp) while (wxTheApp->ProcessIdle()) {}
06cfab17 150#if wxUSE_THREADS
f3855ef0 151 wxMutexGuiLeave();
ac57418f 152#endif
f3855ef0 153 usleep(10000);
06cfab17 154#if wxUSE_THREADS
f3855ef0 155 wxMutexGuiEnter();
ac57418f 156#endif
ec758a20 157 return TRUE;
ff7b1510 158}
c801d85f
KB
159
160wxApp::wxApp()
161{
0d2a2b60
RR
162 wxTheApp = this;
163
ec758a20
RR
164 m_topWindow = (wxWindow *) NULL;
165 m_exitOnFrameDelete = TRUE;
0d2a2b60
RR
166
167 m_idleTag = gtk_idle_add( wxapp_idle_callback, (gpointer) NULL );
168
f6fcbb63 169 m_colorCube = (unsigned char*) NULL;
ff7b1510 170}
c801d85f
KB
171
172wxApp::~wxApp(void)
173{
ec758a20 174 gtk_idle_remove( m_idleTag );
f6fcbb63
RR
175
176 if (m_colorCube) free(m_colorCube);
ff7b1510 177}
c801d85f 178
0d2a2b60 179bool wxApp::OnInitGui()
c801d85f 180{
f6fcbb63
RR
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;
bbe0af5b 185
0d2a2b60
RR
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... */
bbe0af5b 192
0d2a2b60
RR
193 /*
194 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
bbe0af5b 195
0d2a2b60
RR
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 }
aae24d21 206
0d2a2b60
RR
207 gtk_widget_set_default_colormap( cmap );
208 */
f6fcbb63
RR
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 }
c801d85f 243
bbe0af5b
RR
244
245 return TRUE;
246}
247
53010e52
RR
248bool wxApp::ProcessIdle(void)
249{
ec758a20
RR
250 wxIdleEvent event;
251 event.SetEventObject( this );
252 ProcessEvent( event );
0cf2cb36 253
ec758a20 254 return event.MoreRequested();
ff7b1510 255}
53010e52
RR
256
257void wxApp::OnIdle( wxIdleEvent &event )
c801d85f 258{
ec758a20 259 static bool inOnIdle = FALSE;
53010e52 260
d524867f 261 /* Avoid recursion (via ProcessEvent default case) */
ec758a20
RR
262 if (inOnIdle)
263 return;
53010e52 264
ec758a20 265 inOnIdle = TRUE;
53010e52 266
d524867f 267 /* 'Garbage' collection of windows deleted with Close(). */
ec758a20 268 DeletePendingObjects();
53010e52 269
d524867f
RR
270 /* flush the logged messages if any */
271 wxLog *log = wxLog::GetActiveTarget();
272 if (log != NULL && log->HasPendingMessages())
273 log->Flush();
53010e52 274
d524867f 275 /* Send OnIdle events to all windows */
ec758a20 276 bool needMore = SendIdleEvents();
53010e52 277
ec758a20
RR
278 if (needMore)
279 event.RequestMore(TRUE);
53010e52 280
ec758a20 281 inOnIdle = FALSE;
ff7b1510 282}
53010e52
RR
283
284bool wxApp::SendIdleEvents(void)
285{
286 bool needMore = FALSE;
e0253070 287
ec758a20
RR
288 wxNode* node = wxTopLevelWindows.First();
289 while (node)
290 {
f3855ef0
RR
291 wxWindow* win = (wxWindow*) node->Data();
292 if (SendIdleEvents(win))
53010e52 293 needMore = TRUE;
ec758a20
RR
294 node = node->Next();
295 }
53010e52 296 return needMore;
ff7b1510 297}
53010e52
RR
298
299bool wxApp::SendIdleEvents( wxWindow* win )
300{
301 bool needMore = FALSE;
302
8bbe427f
VZ
303 wxIdleEvent event;
304 event.SetEventObject(win);
305 win->ProcessEvent(event);
53010e52
RR
306
307 if (event.MoreRequested())
308 needMore = TRUE;
309
8bbe427f
VZ
310 wxNode* node = win->GetChildren().First();
311 while (node)
312 {
313 wxWindow* win = (wxWindow*) node->Data();
314 if (SendIdleEvents(win))
53010e52
RR
315 needMore = TRUE;
316
8bbe427f
VZ
317 node = node->Next();
318 }
53010e52 319 return needMore ;
ff7b1510 320}
c801d85f 321
c801d85f
KB
322int wxApp::MainLoop(void)
323{
ec758a20
RR
324 gtk_main();
325 return 0;
ff7b1510 326}
c801d85f
KB
327
328void wxApp::ExitMainLoop(void)
329{
ec758a20 330 gtk_main_quit();
ff7b1510 331}
c801d85f
KB
332
333bool wxApp::Initialized(void)
334{
ec758a20 335 return m_initialized;
ff7b1510 336}
c801d85f 337
0cf2cb36 338bool wxApp::Pending(void)
c801d85f 339{
ec758a20 340 return FALSE;
ff7b1510 341}
c801d85f 342
0cf2cb36 343void wxApp::Dispatch(void)
c801d85f 344{
ff7b1510 345}
c801d85f
KB
346
347void wxApp::DeletePendingObjects(void)
348{
ec758a20
RR
349 wxNode *node = wxPendingDelete.First();
350 while (node)
351 {
352 wxObject *obj = (wxObject *)node->Data();
0cf2cb36 353
ec758a20 354 delete obj;
c801d85f 355
ec758a20
RR
356 if (wxPendingDelete.Member(obj))
357 delete node;
c801d85f 358
ec758a20
RR
359 node = wxPendingDelete.First();
360 }
ff7b1510 361}
c801d85f
KB
362
363wxWindow *wxApp::GetTopWindow(void)
364{
ec758a20
RR
365 if (m_topWindow) return m_topWindow;
366 wxNode *node = wxTopLevelWindows.First();
367 if (!node) return (wxWindow *) NULL;
368 return (wxWindow*)node->Data();
ff7b1510 369}
c801d85f
KB
370
371void wxApp::SetTopWindow( wxWindow *win )
372{
ec758a20 373 m_topWindow = win;
ff7b1510 374}
c801d85f 375
0d2a2b60 376bool wxApp::Initialize(void)
c801d85f 377{
0d2a2b60
RR
378 wxBuffer = new char[BUFSIZ + 512];
379
380 wxClassInfo::InitializeClasses();
381
382 wxSystemSettings::Init();
f5abe911 383
0d2a2b60
RR
384 wxTheFontNameDirectory = new wxFontNameDirectory;
385 wxTheFontNameDirectory->Initialize();
c801d85f 386
0d2a2b60
RR
387 wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING );
388 wxTheColourDatabase->Initialize();
a3622daa 389
0d2a2b60
RR
390 wxInitializeStockLists();
391 wxInitializeStockObjects();
c801d85f 392
06cfab17 393#if wxUSE_WX_RESOURCES
0d2a2b60 394 wxTheResourceCache = new wxResourceCache( wxKEY_STRING );
f5abe911 395
0d2a2b60 396 wxInitializeResourceSystem();
f5abe911 397#endif
0cf2cb36 398
0d2a2b60 399 wxImage::InitStandardHandlers();
e0253070 400
0d2a2b60
RR
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;
ff7b1510 408}
c801d85f 409
0d2a2b60 410void wxApp::CleanUp(void)
c801d85f 411{
0d2a2b60 412 wxModule::CleanUpModules();
0cf2cb36 413
06cfab17 414#if wxUSE_WX_RESOURCES
ec758a20 415 wxFlushResources();
a3622daa 416
bbe0af5b
RR
417 if (wxTheResourceCache) delete wxTheResourceCache;
418 wxTheResourceCache = (wxResourceCache*) NULL;
f5abe911
RR
419
420 wxCleanUpResourceSystem();
421#endif
a3622daa 422
0d2a2b60
RR
423 if (wxTheColourDatabase) delete wxTheColourDatabase;
424 wxTheColourDatabase = (wxColourDatabase*) NULL;
425
426 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
427 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
428
429 wxDeleteStockObjects();
430
ec758a20 431 wxDeleteStockLists();
a3622daa 432
ec758a20 433 wxImage::CleanUpHandlers();
0cf2cb36 434
0d2a2b60
RR
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
ec758a20 454 wxSystemSettings::Done();
0d2a2b60
RR
455
456 wxClassInfo::CleanUpClasses();
457
458 delete[] wxBuffer;
ff7b1510 459}
0cf2cb36 460
c801d85f
KB
461wxLog *wxApp::CreateLogTarget()
462{
0d2a2b60 463 return new wxLogGui;
c801d85f
KB
464}
465
466//-----------------------------------------------------------------------------
467// wxEntry
468//-----------------------------------------------------------------------------
469
470int wxEntry( int argc, char *argv[] )
471{
0d2a2b60 472 gtk_set_locale();
c801d85f 473
0d2a2b60 474 gtk_init( &argc, &argv );
0cf2cb36 475
0d2a2b60 476 if (!wxApp::Initialize()) return 0;
0cf2cb36 477
ec758a20 478 if (!wxTheApp)
c801d85f 479 {
ec758a20
RR
480 if (!wxApp::GetInitializerFunction())
481 {
482 printf( "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
483 return 0;
484 }
0cf2cb36 485
ec758a20 486 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
0cf2cb36 487
ec758a20 488 wxObject *test_app = app_ini();
0cf2cb36 489
ec758a20
RR
490 wxTheApp = (wxApp*) test_app;
491 }
0cf2cb36 492
ec758a20
RR
493 if (!wxTheApp)
494 {
495 printf( "wxWindows error: wxTheApp == NULL\n" );
496 return 0;
497 }
c801d85f 498
ec758a20
RR
499 wxTheApp->argc = argc;
500 wxTheApp->argv = argv;
0cf2cb36 501
ec758a20
RR
502 char name[200];
503 strcpy( name, argv[0] );
504 strcpy( name, wxFileNameFromPath(name) );
505 wxStripExtension( name );
506 wxTheApp->SetAppName( name );
e0253070 507
bbe0af5b 508 if (!wxTheApp->OnInitGui()) return 0;
c801d85f 509
0d2a2b60
RR
510 /* Here frames insert themselves automatically
511 * into wxTopLevelWindows by getting created
512 * in OnInit(). */
0cf2cb36 513
ec758a20 514 if (!wxTheApp->OnInit()) return 0;
c801d85f 515
ec758a20 516 wxTheApp->m_initialized = (wxTopLevelWindows.Number() > 0);
0cf2cb36 517
ec758a20 518 int retValue = 0;
0cf2cb36 519
ec758a20 520 if (wxTheApp->Initialized()) retValue = wxTheApp->OnRun();
0cf2cb36 521
0d2a2b60
RR
522 wxWindow *topWindow = wxTheApp->GetTopWindow();
523 if (topWindow)
ec758a20 524 {
0d2a2b60
RR
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 }
ec758a20 537 }
e0253070 538
0d2a2b60 539 wxTheApp->OnExit();
0cf2cb36 540
0d2a2b60
RR
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();
184b5d99 547
ec758a20 548 return retValue;
ff7b1510 549}
1a56f55c 550