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"
24 #if wxUSE_WX_RESOURCES
25 #include "wx/resource.h"
28 #include "wx/module.h"
31 #include "wx/thread.h"
39 #include "wx/gtk/win_gtk.h"
41 //-----------------------------------------------------------------------------
43 //-----------------------------------------------------------------------------
45 wxApp
*wxTheApp
= (wxApp
*) NULL
;
46 wxAppInitializerFunction
wxApp::m_appInitFn
= (wxAppInitializerFunction
) NULL
;
48 extern wxList wxPendingDelete
;
50 extern wxList wxPendingEvents
;
51 extern wxCriticalSection wxPendingEventsLocker
;
53 extern wxResourceCache
*wxTheResourceCache
;
55 unsigned char g_palette
[64*3] =
123 //-----------------------------------------------------------------------------
125 //-----------------------------------------------------------------------------
127 extern void wxFlushResources(void);
129 //-----------------------------------------------------------------------------
131 //-----------------------------------------------------------------------------
140 // it's necessary to call ProcessIdle() to update the frames sizes which
141 // might have been changed (it also will update other things set from
142 // OnUpdateUI() which is a nice (and desired) side effect)
143 for ( wxNode
*node
= wxTopLevelWindows
.GetFirst();
145 node
= node
->GetNext() )
147 wxWindow
*win
= ((wxWindow
*)node
->GetData());
148 win
->OnInternalIdle();
151 while (gtk_events_pending() > 0)
152 gtk_main_iteration();
157 //-----------------------------------------------------------------------------
159 //-----------------------------------------------------------------------------
161 IMPLEMENT_DYNAMIC_CLASS(wxApp
,wxEvtHandler
)
163 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
164 EVT_IDLE(wxApp::OnIdle
)
167 gint
wxapp_idle_callback( gpointer
WXUNUSED(data
) )
171 while (wxTheApp
->ProcessIdle())
187 m_topWindow
= (wxWindow
*) NULL
;
188 m_exitOnFrameDelete
= TRUE
;
190 m_idleTag
= gtk_idle_add( wxapp_idle_callback
, (gpointer
) NULL
);
192 m_colorCube
= (unsigned char*) NULL
;
197 gtk_idle_remove( m_idleTag
);
199 if (m_colorCube
) free(m_colorCube
);
202 bool wxApp::OnInitGui()
204 /* Nothing to do for 15, 16, 24, 32 bit displays */
206 GdkVisual
*visual
= gdk_visual_get_system();
207 if (visual
->depth
> 8) return TRUE
;
209 /* this initiates the standard palette as defined by GdkImlib
210 in the GNOME libraries. it ensures that all GNOME applications
211 use the same 64 colormap entries on 8-bit displays so you
212 can use several rather graphics-heavy applications at the
214 NOTE: this doesn't really seem to work this way... */
217 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
219 for (int i = 0; i < 64; i++)
222 col.red = g_palette[i*3 + 0] << 8;
223 col.green = g_palette[i*3 + 1] << 8;
224 col.blue = g_palette[i*3 + 2] << 8;
227 gdk_color_alloc( cmap, &col );
230 gtk_widget_set_default_colormap( cmap );
233 /* initialize color cube for 8-bit color reduction dithering */
235 GdkColormap
*cmap
= gtk_widget_get_default_colormap();
237 m_colorCube
= (unsigned char*)malloc(32 * 32 * 32);
239 for (int r
= 0; r
< 32; r
++)
241 for (int g
= 0; g
< 32; g
++)
243 for (int b
= 0; b
< 32; b
++)
245 int rr
= (r
<< 3) | (r
>> 2);
246 int gg
= (g
<< 3) | (g
>> 2);
247 int bb
= (b
<< 3) | (b
>> 2);
249 GdkColor
*colors
= cmap
->colors
;
250 int max
= 3 * (65536);
253 for (int i
= 0; i
< cmap
->size
; i
++)
255 int rdiff
= ((rr
<< 8) - colors
[i
].red
);
256 int gdiff
= ((gg
<< 8)- colors
[i
].green
);
257 int bdiff
= ((bb
<< 8)- colors
[i
].blue
);
258 int sum
= ABS (rdiff
) + ABS (gdiff
) + ABS (bdiff
);
259 if (sum
< max
) { index
= i
; max
= sum
; }
262 m_colorCube
[ (r
*1024) + (g
*32) + b
] = index
;
271 bool wxApp::ProcessIdle()
274 event
.SetEventObject( this );
275 ProcessEvent( event
);
277 return event
.MoreRequested();
280 void wxApp::OnIdle( wxIdleEvent
&event
)
282 static bool inOnIdle
= FALSE
;
284 /* Avoid recursion (via ProcessEvent default case) */
290 /* Resend in the main thread events which have been prepared in other
292 ProcessPendingEvents();
294 /* 'Garbage' collection of windows deleted with Close(). */
295 DeletePendingObjects();
297 /* flush the logged messages if any */
298 wxLog
*log
= wxLog::GetActiveTarget();
299 if (log
!= NULL
&& log
->HasPendingMessages())
302 /* Send OnIdle events to all windows */
303 bool needMore
= SendIdleEvents();
306 event
.RequestMore(TRUE
);
311 bool wxApp::SendIdleEvents()
313 bool needMore
= FALSE
;
315 wxNode
* node
= wxTopLevelWindows
.First();
318 wxWindow
* win
= (wxWindow
*) node
->Data();
319 if (SendIdleEvents(win
))
326 bool wxApp::SendIdleEvents( wxWindow
* win
)
328 bool needMore
= FALSE
;
331 event
.SetEventObject(win
);
333 win
->OnInternalIdle();
335 win
->ProcessEvent(event
);
337 if (event
.MoreRequested())
340 wxNode
* node
= win
->GetChildren().First();
343 wxWindow
* win
= (wxWindow
*) node
->Data();
344 if (SendIdleEvents(win
))
352 int wxApp::MainLoop()
358 void wxApp::ExitMainLoop()
363 bool wxApp::Initialized()
365 return m_initialized
;
368 bool wxApp::Pending()
373 void wxApp::Dispatch()
378 void wxApp::ProcessPendingEvents()
380 wxNode
*node
= wxPendingEvents
.First();
381 wxCriticalSectionLocker
locker(wxPendingEventsLocker
);
385 wxEvtHandler
*handler
= (wxEvtHandler
*)node
->Data();
387 handler
->ProcessPendingEvents();
391 node
= wxPendingEvents
.First();
396 void wxApp::DeletePendingObjects()
398 wxNode
*node
= wxPendingDelete
.First();
401 wxObject
*obj
= (wxObject
*)node
->Data();
405 if (wxPendingDelete
.Member(obj
))
408 node
= wxPendingDelete
.First();
412 wxWindow
*wxApp::GetTopWindow()
414 if (m_topWindow
) return m_topWindow
;
415 wxNode
*node
= wxTopLevelWindows
.First();
416 if (!node
) return (wxWindow
*) NULL
;
417 return (wxWindow
*)node
->Data();
420 void wxApp::SetTopWindow( wxWindow
*win
)
425 bool wxApp::Initialize()
427 wxBuffer
= new char[BUFSIZ
+ 512];
429 wxClassInfo::InitializeClasses();
431 wxSystemSettings::Init();
434 wxTheFontNameDirectory = new wxFontNameDirectory;
435 wxTheFontNameDirectory->Initialize();
438 wxTheColourDatabase
= new wxColourDatabase( wxKEY_STRING
);
439 wxTheColourDatabase
->Initialize();
441 wxInitializeStockLists();
442 wxInitializeStockObjects();
444 #if wxUSE_WX_RESOURCES
445 wxTheResourceCache
= new wxResourceCache( wxKEY_STRING
);
447 wxInitializeResourceSystem();
450 wxImage::InitStandardHandlers();
452 /* no global cursor under X
453 g_globalCursor = new wxCursor; */
455 wxModule::RegisterModules();
456 if (!wxModule::InitializeModules()) return FALSE
;
461 void wxApp::CleanUp()
463 wxModule::CleanUpModules();
465 #if wxUSE_WX_RESOURCES
468 if (wxTheResourceCache
)
469 delete wxTheResourceCache
;
470 wxTheResourceCache
= (wxResourceCache
*) NULL
;
472 wxCleanUpResourceSystem();
475 if (wxTheColourDatabase
)
476 delete wxTheColourDatabase
;
477 wxTheColourDatabase
= (wxColourDatabase
*) NULL
;
480 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
481 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
484 wxDeleteStockObjects();
486 wxDeleteStockLists();
488 wxImage::CleanUpHandlers();
491 wxTheApp
= (wxApp
*) NULL
;
493 wxSystemSettings::Done();
497 wxClassInfo::CleanUpClasses();
499 // check for memory leaks
500 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
501 if (wxDebugContext::CountObjectsLeft() > 0)
503 wxLogDebug("There were memory leaks.\n");
504 wxDebugContext::Dump();
505 wxDebugContext::PrintStatistics();
509 // do this as the very last thing because everything else can log messages
510 wxLog::DontCreateOnDemand();
512 wxLog
*oldLog
= wxLog::SetActiveTarget( (wxLog
*) NULL
);
517 wxLog
*wxApp::CreateLogTarget()
522 //-----------------------------------------------------------------------------
524 //-----------------------------------------------------------------------------
526 int wxEntry( int argc
, char *argv
[] )
530 gtk_init( &argc
, &argv
);
532 if (!wxApp::Initialize())
537 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
538 "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
540 wxAppInitializerFunction app_ini
= wxApp::GetInitializerFunction();
542 wxObject
*test_app
= app_ini();
544 wxTheApp
= (wxApp
*) test_app
;
547 wxCHECK_MSG( wxTheApp
, -1, "wxWindows error: no application object" );
549 wxTheApp
->argc
= argc
;
550 wxTheApp
->argv
= argv
;
553 strcpy( name
, argv
[0] );
554 strcpy( name
, wxFileNameFromPath(name
) );
555 wxStripExtension( name
);
556 wxTheApp
->SetAppName( name
);
558 if (!wxTheApp
->OnInitGui())
561 /* Here frames insert themselves automatically
562 * into wxTopLevelWindows by getting created
565 if (!wxTheApp
->OnInit())
568 wxTheApp
->m_initialized
= (wxTopLevelWindows
.Number() > 0);
572 if (wxTheApp
->Initialized())
573 retValue
= wxTheApp
->OnRun();
575 wxWindow
*topWindow
= wxTheApp
->GetTopWindow();
578 // Forcibly delete the window.
579 if (topWindow
->IsKindOf(CLASSINFO(wxFrame
)) ||
580 topWindow
->IsKindOf(CLASSINFO(wxDialog
)) )
582 topWindow
->Close( TRUE
);
583 wxTheApp
->DeletePendingObjects();
588 wxTheApp
->SetTopWindow( (wxWindow
*) NULL
);
594 // flush the logged messages if any
595 wxLog
*log
= wxLog::GetActiveTarget();
596 if (log
!= NULL
&& log
->HasPendingMessages())
599 // continuing to use user defined log target is unsafe from now on because
600 // some resources may be already unavailable, so replace it by something
602 wxLog
*oldlog
= wxLog::SetActiveTarget(new wxLogStderr
);