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