1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "app.h"
15 #include "wx/gdicmn.h"
19 #include "wx/memory.h"
21 #include "wx/settings.h"
22 #include "wx/dialog.h"
23 #if wxUSE_WX_RESOURCES
24 #include "wx/resource.h"
26 #include "wx/module.h"
29 #include "wx/thread.h"
33 // many versions of Unices have this function, but it is not defined in system
34 // headers - please add your system here if it is the case for your OS.
35 // SunOS < 5.6 (i.e. Solaris < 2.6) and DG-UX are like this.
36 #if (defined(__SUN__) && !defined(__SunOs_5_6) && \
37 !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \
41 void usleep(unsigned long usec
);
43 #endif // Unices without usleep()
48 #include "wx/gtk/win_gtk.h"
50 #include <unistd.h> // usleep() on solaris
52 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
56 wxApp
*wxTheApp
= (wxApp
*) NULL
;
57 wxAppInitializerFunction
wxApp::m_appInitFn
= (wxAppInitializerFunction
) NULL
;
59 extern wxList wxPendingDelete
;
60 extern wxResourceCache
*wxTheResourceCache
;
62 unsigned char g_palette
[64*3] =
130 //-----------------------------------------------------------------------------
132 //-----------------------------------------------------------------------------
134 extern void wxFlushResources(void);
136 //-----------------------------------------------------------------------------
138 //-----------------------------------------------------------------------------
147 while (gtk_events_pending() > 0) gtk_main_iteration();
151 //-----------------------------------------------------------------------------
153 //-----------------------------------------------------------------------------
155 IMPLEMENT_DYNAMIC_CLASS(wxApp
,wxEvtHandler
)
157 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
158 EVT_IDLE(wxApp::OnIdle
)
161 gint
wxapp_idle_callback( gpointer
WXUNUSED(data
) )
163 if (wxTheApp
) while (wxTheApp
->ProcessIdle()) {}
178 m_topWindow
= (wxWindow
*) NULL
;
179 m_exitOnFrameDelete
= TRUE
;
181 m_idleTag
= gtk_idle_add( wxapp_idle_callback
, (gpointer
) NULL
);
183 m_colorCube
= (unsigned char*) NULL
;
188 gtk_idle_remove( m_idleTag
);
190 if (m_colorCube
) free(m_colorCube
);
193 bool wxApp::OnInitGui()
195 /* Nothing to do for 15, 16, 24, 32 bit displays */
197 GdkVisual
*visual
= gdk_visual_get_system();
198 if (visual
->depth
> 8) return TRUE
;
200 /* this initiates the standard palette as defined by GdkImlib
201 in the GNOME libraries. it ensures that all GNOME applications
202 use the same 64 colormap entries on 8-bit displays so you
203 can use several rather graphics-heavy applications at the
205 NOTE: this doesn't really seem to work this way... */
208 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
210 for (int i = 0; i < 64; i++)
213 col.red = g_palette[i*3 + 0] << 8;
214 col.green = g_palette[i*3 + 1] << 8;
215 col.blue = g_palette[i*3 + 2] << 8;
218 gdk_color_alloc( cmap, &col );
221 gtk_widget_set_default_colormap( cmap );
224 /* initialize color cube for 8-bit color reduction dithering */
226 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
228 m_colorCube
= (unsigned char*)malloc(32 * 32 * 32);
230 for (int r
= 0; r
< 32; r
++)
232 for (int g
= 0; g
< 32; g
++)
234 for (int b
= 0; b
< 32; b
++)
236 int rr
= (r
<< 3) | (r
>> 2);
237 int gg
= (g
<< 3) | (g
>> 2);
238 int bb
= (b
<< 3) | (b
>> 2);
240 GdkColor
*colors
= cmap
->colors
;
241 int max
= 3 * (65536);
244 for (int i
= 0; i
< cmap
->size
; i
++)
246 int rdiff
= ((rr
<< 8) - colors
[i
].red
);
247 int gdiff
= ((gg
<< 8)- colors
[i
].green
);
248 int bdiff
= ((bb
<< 8)- colors
[i
].blue
);
249 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
250 if (sum
< max
) { index
= i
; max
= sum
; }
253 m_colorCube
[ (r
*1024) + (g
*32) + b
] = index
;
262 bool wxApp::ProcessIdle()
265 event
.SetEventObject( this );
266 ProcessEvent( event
);
268 return event
.MoreRequested();
271 void wxApp::OnIdle( wxIdleEvent
&event
)
273 static bool inOnIdle
= FALSE
;
275 /* Avoid recursion (via ProcessEvent default case) */
281 /* 'Garbage' collection of windows deleted with Close(). */
282 DeletePendingObjects();
284 /* flush the logged messages if any */
285 wxLog
*log
= wxLog::GetActiveTarget();
286 if (log
!= NULL
&& log
->HasPendingMessages())
289 /* Send OnIdle events to all windows */
290 bool needMore
= SendIdleEvents();
293 event
.RequestMore(TRUE
);
298 bool wxApp::SendIdleEvents()
300 bool needMore
= FALSE
;
302 wxNode
* node
= wxTopLevelWindows
.First();
305 wxWindow
* win
= (wxWindow
*) node
->Data();
306 if (SendIdleEvents(win
))
313 bool wxApp::SendIdleEvents( wxWindow
* win
)
315 bool needMore
= FALSE
;
318 event
.SetEventObject(win
);
320 win
->OnInternalIdle();
322 win
->ProcessEvent(event
);
324 if (event
.MoreRequested())
327 wxNode
* node
= win
->GetChildren().First();
330 wxWindow
* win
= (wxWindow
*) node
->Data();
331 if (SendIdleEvents(win
))
339 int wxApp::MainLoop()
345 void wxApp::ExitMainLoop()
350 bool wxApp::Initialized()
352 return m_initialized
;
355 bool wxApp::Pending()
360 void wxApp::Dispatch()
364 void wxApp::DeletePendingObjects()
366 wxNode
*node
= wxPendingDelete
.First();
369 wxObject
*obj
= (wxObject
*)node
->Data();
373 if (wxPendingDelete
.Member(obj
))
376 node
= wxPendingDelete
.First();
380 wxWindow
*wxApp::GetTopWindow()
382 if (m_topWindow
) return m_topWindow
;
383 wxNode
*node
= wxTopLevelWindows
.First();
384 if (!node
) return (wxWindow
*) NULL
;
385 return (wxWindow
*)node
->Data();
388 void wxApp::SetTopWindow( wxWindow
*win
)
393 bool wxApp::Initialize()
395 wxBuffer
= new char[BUFSIZ
+ 512];
397 wxClassInfo::InitializeClasses();
399 wxSystemSettings::Init();
402 wxTheFontNameDirectory = new wxFontNameDirectory;
403 wxTheFontNameDirectory->Initialize();
406 wxTheColourDatabase
= new wxColourDatabase( wxKEY_STRING
);
407 wxTheColourDatabase
->Initialize();
409 wxInitializeStockLists();
410 wxInitializeStockObjects();
412 #if wxUSE_WX_RESOURCES
413 wxTheResourceCache
= new wxResourceCache( wxKEY_STRING
);
415 wxInitializeResourceSystem();
418 wxImage::InitStandardHandlers();
420 /* no global cursor under X
421 g_globalCursor = new wxCursor; */
423 wxModule::RegisterModules();
424 if (!wxModule::InitializeModules()) return FALSE
;
429 void wxApp::CleanUp()
431 wxModule::CleanUpModules();
433 #if wxUSE_WX_RESOURCES
436 if (wxTheResourceCache
)
437 delete wxTheResourceCache
;
438 wxTheResourceCache
= (wxResourceCache
*) NULL
;
440 wxCleanUpResourceSystem();
443 if (wxTheColourDatabase
)
444 delete wxTheColourDatabase
;
445 wxTheColourDatabase
= (wxColourDatabase
*) NULL
;
448 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
449 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
452 wxDeleteStockObjects();
454 wxDeleteStockLists();
456 wxImage::CleanUpHandlers();
459 wxTheApp
= (wxApp
*) NULL
;
461 wxSystemSettings::Done();
465 wxClassInfo::CleanUpClasses();
467 // check for memory leaks
468 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
469 if (wxDebugContext::CountObjectsLeft() > 0)
471 wxLogDebug("There were memory leaks.\n");
472 wxDebugContext::Dump();
473 wxDebugContext::PrintStatistics();
477 // do this as the very last thing because everything else can log messages
478 wxLog::DontCreateOnDemand();
480 wxLog
*oldLog
= wxLog::SetActiveTarget( (wxLog
*) NULL
);
485 wxLog
*wxApp::CreateLogTarget()
490 //-----------------------------------------------------------------------------
492 //-----------------------------------------------------------------------------
494 int wxEntry( int argc
, char *argv
[] )
498 gtk_init( &argc
, &argv
);
500 if (!wxApp::Initialize())
505 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
506 "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
508 wxAppInitializerFunction app_ini
= wxApp::GetInitializerFunction();
510 wxObject
*test_app
= app_ini();
512 wxTheApp
= (wxApp
*) test_app
;
515 wxCHECK_MSG( wxTheApp
, -1, "wxWindows error: no application object" );
517 wxTheApp
->argc
= argc
;
518 wxTheApp
->argv
= argv
;
521 strcpy( name
, argv
[0] );
522 strcpy( name
, wxFileNameFromPath(name
) );
523 wxStripExtension( name
);
524 wxTheApp
->SetAppName( name
);
526 if (!wxTheApp
->OnInitGui())
529 /* Here frames insert themselves automatically
530 * into wxTopLevelWindows by getting created
533 if (!wxTheApp
->OnInit())
536 wxTheApp
->m_initialized
= (wxTopLevelWindows
.Number() > 0);
540 if (wxTheApp
->Initialized())
541 retValue
= wxTheApp
->OnRun();
543 wxWindow
*topWindow
= wxTheApp
->GetTopWindow();
546 // Forcibly delete the window.
547 if (topWindow
->IsKindOf(CLASSINFO(wxFrame
)) ||
548 topWindow
->IsKindOf(CLASSINFO(wxDialog
)) )
550 topWindow
->Close( TRUE
);
551 wxTheApp
->DeletePendingObjects();
556 wxTheApp
->SetTopWindow( (wxWindow
*) NULL
);
562 // flush the logged messages if any
563 wxLog
*log
= wxLog::GetActiveTarget();
564 if (log
!= NULL
&& log
->HasPendingMessages())
567 // continuing to use user defined log target is unsafe from now on because
568 // some resources may be already unavailable, so replace it by something
570 wxLog
*oldlog
= wxLog::SetActiveTarget(new wxLogStderr
);