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