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"
22 #include "wx/settings.h"
23 #include "wx/module.h"
24 #include "wx/evtloop.h"
26 #include "wx/dialog.h"
31 #include "wx/mgl/private.h"
33 //-----------------------------------------------------------------------------
35 //-----------------------------------------------------------------------------
37 wxApp
*wxTheApp
= NULL
;
38 wxAppInitializerFunction
wxAppBase::m_appInitFn
= (wxAppInitializerFunction
) NULL
;
40 static wxEventLoop
*gs_mainEventLoop
= NULL
;
43 //-----------------------------------------------------------------------------
45 //-----------------------------------------------------------------------------
53 //-----------------------------------------------------------------------------
55 //-----------------------------------------------------------------------------
57 static bool gs_inYield
= FALSE
;
62 if ( !wxThread::IsMain() )
64 // can't process events from other threads, MGL is thread-unsafe
67 #endif // wxUSE_THREADS
73 while (gs_mainEventLoop
->Pending())
74 gs_mainEventLoop
->Dispatch();
76 /* it's necessary to call ProcessIdle() to update the frames sizes which
77 might have been changed (it also will update other things set from
78 OnUpdateUI() which is a nice (and desired) side effect) */
79 while (wxTheApp
->ProcessIdle()) { }
88 bool wxYieldIfNeeded()
97 //-----------------------------------------------------------------------------
99 //-----------------------------------------------------------------------------
104 if (!wxThread::IsMain())
108 while (wxTheApp
->ProcessIdle()) {}
111 if (!wxThread::IsMain())
116 //-----------------------------------------------------------------------------
118 //-----------------------------------------------------------------------------
120 IMPLEMENT_DYNAMIC_CLASS(wxApp
,wxEvtHandler
)
122 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
123 EVT_IDLE(wxApp::OnIdle
)
135 bool wxApp::OnInitGui()
137 if ( MGL_init(".", NULL
) == 0 )
139 if ( !wxCreateMGL_WM() )
142 // This has to be done *after* wxCreateMGL_WM() because it initializes
144 if ( !wxAppBase::OnInitGui() )
150 bool wxApp::ProcessIdle()
153 event
.SetEventObject(this);
156 return event
.MoreRequested();
159 void wxApp::OnIdle(wxIdleEvent
&event
)
161 static bool s_inOnIdle
= FALSE
;
163 /* Avoid recursion (via ProcessEvent default case) */
169 /* Resend in the main thread events which have been prepared in other
171 ProcessPendingEvents();
173 // 'Garbage' collection of windows deleted with Close().
174 DeletePendingObjects();
176 // Send OnIdle events to all windows
177 if ( SendIdleEvents() )
178 event
.RequestMore(TRUE
);
183 bool wxApp::SendIdleEvents()
185 bool needMore
= FALSE
;
187 wxWindowList::Node
* node
= wxTopLevelWindows
.GetFirst();
190 wxWindow
* win
= node
->GetData();
191 if ( SendIdleEvents(win
) )
193 node
= node
->GetNext();
199 bool wxApp::SendIdleEvents(wxWindow
* win
)
201 bool needMore
= FALSE
;
204 event
.SetEventObject(win
);
206 win
->GetEventHandler()->ProcessEvent(event
);
208 #if 0 // FIXME_MGL - what the hell it is?
209 win
->OnInternalIdle();
211 if ( event
.MoreRequested() )
215 wxNode
* node
= win
->GetChildren().First();
218 wxWindow
* win
= (wxWindow
*) node
->Data();
219 if ( SendIdleEvents(win
) )
227 int wxApp::MainLoop()
230 gs_mainEventLoop
= new wxEventLoop
;
231 rt
= gs_mainEventLoop
->Run();
232 delete gs_mainEventLoop
;
233 gs_mainEventLoop
= NULL
;
237 void wxApp::ExitMainLoop()
239 gs_mainEventLoop
->Exit(0);
242 bool wxApp::Initialized()
244 // FIXME_MGL -- only for now because we don't have wxFrame/wxDialog yet
246 //return (wxTopLevelWindows.GetCount() != 0);
249 bool wxApp::Pending()
251 return gs_mainEventLoop
->Pending();
254 void wxApp::Dispatch()
256 gs_mainEventLoop
->Dispatch();
259 void wxApp::DeletePendingObjects()
261 wxNode
*node
= wxPendingDelete
.First();
264 wxObject
*obj
= (wxObject
*)node
->Data();
268 if ( wxPendingDelete
.Find(obj
) )
271 node
= wxPendingDelete
.First();
275 bool wxApp::Initialize()
277 wxBuffer
= new wxChar
[BUFSIZ
+ 512];
279 wxClassInfo::InitializeClasses();
281 wxSystemSettings::Init();
284 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
287 // GL: I'm annoyed ... I don't know where to put this and I don't want to
288 // create a module for that as it's part of the core.
290 wxPendingEvents
= new wxList
;
291 wxPendingEventsLocker
= new wxCriticalSection
;
294 wxTheColourDatabase
= new wxColourDatabase(wxKEY_STRING
);
295 wxTheColourDatabase
->Initialize();
297 wxInitializeStockLists();
298 wxInitializeStockObjects();
300 #if wxUSE_WX_RESOURCES
301 wxInitializeResourceSystem();
304 wxModule::RegisterModules();
305 if (!wxModule::InitializeModules()) return FALSE
;
312 #include "question.xpm"
313 #include "warning.xpm"
315 wxIcon
wxApp::GetStdIcon(int which
) const
319 case wxICON_INFORMATION
:
320 return wxIcon(info_xpm
);
321 case wxICON_QUESTION
:
322 return wxIcon(question_xpm
);
323 case wxICON_EXCLAMATION
:
324 return wxIcon(warning_xpm
);
326 wxFAIL_MSG(wxT("requested non existent standard icon"));
327 // still fall through
329 return wxIcon(error_xpm
);
333 void wxApp::CleanUp()
336 // flush the logged messages if any
337 wxLog
*log
= wxLog::GetActiveTarget();
338 if (log
!= NULL
&& log
->HasPendingMessages())
341 // continuing to use user defined log target is unsafe from now on because
342 // some resources may be already unavailable, so replace it by something
344 wxLog
*oldlog
= wxLog::SetActiveTarget(new wxLogStderr
);
349 wxModule::CleanUpModules();
351 #if wxUSE_WX_RESOURCES
352 wxCleanUpResourceSystem();
355 if (wxTheColourDatabase
)
356 delete wxTheColourDatabase
;
358 wxTheColourDatabase
= (wxColourDatabase
*) NULL
;
360 wxDeleteStockObjects();
362 wxDeleteStockLists();
365 wxTheApp
= (wxApp
*) NULL
;
367 // GL: I'm annoyed ... I don't know where to put this and I don't want to
368 // create a module for that as it's part of the core.
370 delete wxPendingEvents
;
371 delete wxPendingEventsLocker
;
374 wxSystemSettings::Done();
378 wxClassInfo::CleanUpClasses();
380 // check for memory leaks
381 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
382 if (wxDebugContext::CountObjectsLeft(TRUE
) > 0)
384 wxLogDebug(wxT("There were memory leaks.\n"));
385 wxDebugContext::Dump();
386 wxDebugContext::PrintStatistics();
391 // do this as the very last thing because everything else can log messages
392 wxLog::DontCreateOnDemand();
394 wxLog
*oldLog
= wxLog::SetActiveTarget( (wxLog
*) NULL
);
404 int wxEntryStart(int argc
, char *argv
[])
406 return wxApp::Initialize() ? 0 : -1;
412 return wxTheApp
->OnInitGui() ? 0 : -1;
416 void wxEntryCleanup()
423 int wxEntry(int argc
, char *argv
[])
425 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
426 // This seems to be necessary since there are 'rogue'
427 // objects present at this point (perhaps global objects?)
428 // Setting a checkpoint will ignore them as far as the
429 // memory checking facility is concerned.
430 // Of course you may argue that memory allocated in globals should be
431 // checked, but this is a reasonable compromise.
432 wxDebugContext::SetCheckpoint();
434 int err
= wxEntryStart(argc
, argv
);
440 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
441 wxT("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
443 wxAppInitializerFunction app_ini
= wxApp::GetInitializerFunction();
445 wxObject
*test_app
= app_ini();
447 wxTheApp
= (wxApp
*) test_app
;
450 wxCHECK_MSG( wxTheApp
, -1, wxT("wxWindows error: no application object") );
452 wxTheApp
->argc
= argc
;
454 wxTheApp
->argv
= new wxChar
*[argc
+1];
456 while (mb_argc
< argc
)
458 wxTheApp
->argv
[mb_argc
] = wxStrdup(wxConvLibc
.cMB2WX(argv
[mb_argc
]));
461 wxTheApp
->argv
[mb_argc
] = (wxChar
*)NULL
;
463 wxTheApp
->argv
= argv
;
466 wxString
name(wxFileNameFromPath(argv
[0]));
467 wxStripExtension(name
);
468 wxTheApp
->SetAppName(name
);
471 retValue
= wxEntryInitGui();
473 // Here frames insert themselves automatically into wxTopLevelWindows by
474 // getting created in OnInit().
477 if ( !wxTheApp
->OnInit() )
483 /* delete pending toplevel windows (typically a single
484 dialog) so that, if there isn't any left, we don't
486 wxTheApp
->DeletePendingObjects();
488 if ( wxTheApp
->Initialized() )
492 wxWindow
*topWindow
= wxTheApp
->GetTopWindow();
495 /* Forcibly delete the window. */
496 if (topWindow
->IsKindOf(CLASSINFO(wxFrame
)) ||
497 topWindow
->IsKindOf(CLASSINFO(wxDialog
)) )
499 topWindow
->Close(TRUE
);
500 wxTheApp
->DeletePendingObjects();
505 wxTheApp
->SetTopWindow((wxWindow
*) NULL
);
509 retValue
= wxTheApp
->OnExit();