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