1 /////////////////////////////////////////////////////////////////////////////
3 // Author: Vaclav Slavik
4 // based on GTK and MSW implementations
6 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "app.h"
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
23 #include "wx/settings.h"
24 #include "wx/module.h"
25 #include "wx/evtloop.h"
27 #include "wx/dialog.h"
33 #include "wx/fontutil.h"
34 #include "wx/mgl/private.h"
38 #if defined(MGL_DEBUG) && !defined(__WXDEBUG__)
42 //-----------------------------------------------------------------------------
44 //-----------------------------------------------------------------------------
46 wxApp
*wxTheApp
= NULL
;
47 wxAppInitializerFunction
wxAppBase::m_appInitFn
= (wxAppInitializerFunction
) NULL
;
50 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
60 //-----------------------------------------------------------------------------
62 //-----------------------------------------------------------------------------
64 static bool gs_inYield
= FALSE
;
69 if ( !wxThread::IsMain() )
71 // can't process events from other threads, MGL is thread-unsafe
74 #endif // wxUSE_THREADS
80 if ( wxEventLoop::GetActive() )
82 while (wxEventLoop::GetActive()->Pending())
83 wxEventLoop::GetActive()->Dispatch();
86 /* it's necessary to call ProcessIdle() to update the frames sizes which
87 might have been changed (it also will update other things set from
88 OnUpdateUI() which is a nice (and desired) side effect) */
89 while (wxTheApp
->ProcessIdle()) { }
98 bool wxYieldIfNeeded()
107 //-----------------------------------------------------------------------------
109 //-----------------------------------------------------------------------------
114 if (!wxThread::IsMain())
118 while (wxTheApp
->ProcessIdle()) {}
121 if (!wxThread::IsMain())
126 //-----------------------------------------------------------------------------
128 //-----------------------------------------------------------------------------
130 IMPLEMENT_DYNAMIC_CLASS(wxApp
,wxEvtHandler
)
132 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
133 EVT_IDLE(wxApp::OnIdle
)
137 wxApp::wxApp() : m_mainLoop(NULL
)
145 bool wxApp::OnInitGui()
147 if ( MGL_init(".", NULL
) == 0 )
149 if ( !wxCreateMGL_WM() )
152 // This has to be done *after* wxCreateMGL_WM() because it initializes
154 if ( !wxAppBase::OnInitGui() )
158 // That damn MGL redirects stdin and stdout to physical console
159 FILE *file
= fopen("stderr", "wt");
160 wxLog::SetActiveTarget(new wxLogStderr(file
));
166 bool wxApp::ProcessIdle()
169 event
.SetEventObject(this);
172 return event
.MoreRequested();
175 void wxApp::OnIdle(wxIdleEvent
&event
)
177 static bool s_inOnIdle
= FALSE
;
179 /* Avoid recursion (via ProcessEvent default case) */
185 /* Resend in the main thread events which have been prepared in other
187 ProcessPendingEvents();
189 // 'Garbage' collection of windows deleted with Close().
190 DeletePendingObjects();
192 // Send OnIdle events to all windows
193 if ( SendIdleEvents() )
194 event
.RequestMore(TRUE
);
199 bool wxApp::SendIdleEvents()
201 bool needMore
= FALSE
;
203 wxWindowList::Node
* node
= wxTopLevelWindows
.GetFirst();
206 wxWindow
* win
= node
->GetData();
207 if ( SendIdleEvents(win
) )
209 node
= node
->GetNext();
215 bool wxApp::SendIdleEvents(wxWindow
* win
)
217 bool needMore
= FALSE
;
220 event
.SetEventObject(win
);
222 win
->GetEventHandler()->ProcessEvent(event
);
224 if ( event
.MoreRequested() )
227 wxNode
* node
= win
->GetChildren().First();
230 wxWindow
* win
= (wxWindow
*) node
->Data();
231 if ( SendIdleEvents(win
) )
239 int wxApp::MainLoop()
242 m_mainLoop
= new wxEventLoop
;
244 rt
= m_mainLoop
->Run();
251 void wxApp::ExitMainLoop()
257 bool wxApp::Initialized()
259 // FIXME_MGL -- only for now because we don't have wxFrame/wxDialog yet
261 //return (wxTopLevelWindows.GetCount() != 0);
264 bool wxApp::Pending()
266 return wxEventLoop::GetActive()->Pending();
269 void wxApp::Dispatch()
271 wxEventLoop::GetActive()->Dispatch();
274 void wxApp::DeletePendingObjects()
276 wxNode
*node
= wxPendingDelete
.First();
279 wxObject
*obj
= (wxObject
*)node
->Data();
283 if ( wxPendingDelete
.Find(obj
) )
286 node
= wxPendingDelete
.First();
290 bool wxApp::Initialize()
292 wxBuffer
= new wxChar
[BUFSIZ
+ 512];
294 wxClassInfo::InitializeClasses();
296 wxSystemSettings::Init();
299 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
302 // GL: I'm annoyed ... I don't know where to put this and I don't want to
303 // create a module for that as it's part of the core.
305 wxPendingEvents
= new wxList
;
306 wxPendingEventsLocker
= new wxCriticalSection
;
309 wxTheColourDatabase
= new wxColourDatabase(wxKEY_STRING
);
310 wxTheColourDatabase
->Initialize();
312 // Can't do this in wxModule, because fonts are needed by stock lists
313 wxTheFontsManager
= new wxFontsManager
;
315 wxInitializeStockLists();
316 wxInitializeStockObjects();
318 #if wxUSE_WX_RESOURCES
319 wxInitializeResourceSystem();
322 wxModule::RegisterModules();
323 if (!wxModule::InitializeModules()) return FALSE
;
330 #include "question.xpm"
331 #include "warning.xpm"
333 wxIcon
wxApp::GetStdIcon(int which
) const
337 case wxICON_INFORMATION
:
338 return wxIcon(info_xpm
);
339 case wxICON_QUESTION
:
340 return wxIcon(question_xpm
);
341 case wxICON_EXCLAMATION
:
342 return wxIcon(warning_xpm
);
344 wxFAIL_MSG(wxT("requested non existent standard icon"));
345 // still fall through
347 return wxIcon(error_xpm
);
351 void wxApp::CleanUp()
354 // flush the logged messages if any
355 wxLog
*log
= wxLog::GetActiveTarget();
356 if (log
!= NULL
&& log
->HasPendingMessages())
359 // continuing to use user defined log target is unsafe from now on because
360 // some resources may be already unavailable, so replace it by something
362 wxLog
*oldlog
= wxLog::SetActiveTarget(new wxLogStderr
);
367 wxModule::CleanUpModules();
369 #if wxUSE_WX_RESOURCES
370 wxCleanUpResourceSystem();
373 if (wxTheColourDatabase
)
374 delete wxTheColourDatabase
;
376 wxTheColourDatabase
= (wxColourDatabase
*) NULL
;
378 wxDeleteStockObjects();
379 wxDeleteStockLists();
381 // Can't do this in wxModule, because fonts are needed by stock lists
382 delete wxTheFontsManager
;
383 wxTheFontsManager
= (wxFontsManager
*) NULL
;
386 wxTheApp
= (wxApp
*) NULL
;
388 // GL: I'm annoyed ... I don't know where to put this and I don't want to
389 // create a module for that as it's part of the core.
391 delete wxPendingEvents
;
392 delete wxPendingEventsLocker
;
395 wxSystemSettings::Done();
399 wxClassInfo::CleanUpClasses();
401 // check for memory leaks
402 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
403 if (wxDebugContext::CountObjectsLeft(TRUE
) > 0)
405 wxLogDebug(wxT("There were memory leaks.\n"));
406 wxDebugContext::Dump();
407 wxDebugContext::PrintStatistics();
412 // do this as the very last thing because everything else can log messages
413 wxLog::DontCreateOnDemand();
415 wxLog
*oldLog
= wxLog::SetActiveTarget( (wxLog
*) NULL
);
425 int wxEntryStart(int argc
, char *argv
[])
427 return wxApp::Initialize() ? 0 : -1;
433 return wxTheApp
->OnInitGui() ? 0 : -1;
437 void wxEntryCleanup()
444 int wxEntry(int argc
, char *argv
[])
446 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
447 // This seems to be necessary since there are 'rogue'
448 // objects present at this point (perhaps global objects?)
449 // Setting a checkpoint will ignore them as far as the
450 // memory checking facility is concerned.
451 // Of course you may argue that memory allocated in globals should be
452 // checked, but this is a reasonable compromise.
453 wxDebugContext::SetCheckpoint();
455 int err
= wxEntryStart(argc
, argv
);
461 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
462 wxT("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
464 wxAppInitializerFunction app_ini
= wxApp::GetInitializerFunction();
466 wxObject
*test_app
= app_ini();
468 wxTheApp
= (wxApp
*) test_app
;
471 wxCHECK_MSG( wxTheApp
, -1, wxT("wxWindows error: no application object") );
473 wxTheApp
->argc
= argc
;
475 wxTheApp
->argv
= new wxChar
*[argc
+1];
477 while (mb_argc
< argc
)
479 wxTheApp
->argv
[mb_argc
] = wxStrdup(wxConvLibc
.cMB2WX(argv
[mb_argc
]));
482 wxTheApp
->argv
[mb_argc
] = (wxChar
*)NULL
;
484 wxTheApp
->argv
= argv
;
487 wxString
name(wxFileNameFromPath(argv
[0]));
488 wxStripExtension(name
);
489 wxTheApp
->SetAppName(name
);
492 retValue
= wxEntryInitGui();
494 // Here frames insert themselves automatically into wxTopLevelWindows by
495 // getting created in OnInit().
498 if ( !wxTheApp
->OnInit() )
504 /* delete pending toplevel windows (typically a single
505 dialog) so that, if there isn't any left, we don't
507 wxTheApp
->DeletePendingObjects();
509 if ( wxTheApp
->Initialized() )
513 wxWindow
*topWindow
= wxTheApp
->GetTopWindow();
516 /* Forcibly delete the window. */
517 if (topWindow
->IsKindOf(CLASSINFO(wxFrame
)) ||
518 topWindow
->IsKindOf(CLASSINFO(wxDialog
)) )
520 topWindow
->Close(TRUE
);
521 wxTheApp
->DeletePendingObjects();
526 wxTheApp
->SetTopWindow((wxWindow
*) NULL
);
530 retValue
= wxTheApp
->OnExit();