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/fontutil.h"
32 #include "wx/mgl/private.h"
34 //-----------------------------------------------------------------------------
36 //-----------------------------------------------------------------------------
38 wxApp
*wxTheApp
= NULL
;
39 wxAppInitializerFunction
wxAppBase::m_appInitFn
= (wxAppInitializerFunction
) NULL
;
42 //-----------------------------------------------------------------------------
44 //-----------------------------------------------------------------------------
52 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
56 static bool gs_inYield
= FALSE
;
61 if ( !wxThread::IsMain() )
63 // can't process events from other threads, MGL is thread-unsafe
66 #endif // wxUSE_THREADS
72 if ( wxEventLoop::GetActive() )
74 while (wxEventLoop::GetActive()->Pending())
75 wxEventLoop::GetActive()->Dispatch();
78 MGL_wmUpdateDC(g_winMng
); // FIXME_MGL -- temporary hack, please remove
80 /* it's necessary to call ProcessIdle() to update the frames sizes which
81 might have been changed (it also will update other things set from
82 OnUpdateUI() which is a nice (and desired) side effect) */
83 while (wxTheApp
->ProcessIdle()) { }
92 bool wxYieldIfNeeded()
101 //-----------------------------------------------------------------------------
103 //-----------------------------------------------------------------------------
108 if (!wxThread::IsMain())
112 while (wxTheApp
->ProcessIdle()) {}
115 if (!wxThread::IsMain())
120 //-----------------------------------------------------------------------------
122 //-----------------------------------------------------------------------------
124 IMPLEMENT_DYNAMIC_CLASS(wxApp
,wxEvtHandler
)
126 BEGIN_EVENT_TABLE(wxApp
, wxEvtHandler
)
127 EVT_IDLE(wxApp::OnIdle
)
131 wxApp::wxApp() : m_mainLoop(NULL
)
139 bool wxApp::OnInitGui()
141 if ( MGL_init(".", NULL
) == 0 )
143 if ( !wxCreateMGL_WM() )
146 // This has to be done *after* wxCreateMGL_WM() because it initializes
148 if ( !wxAppBase::OnInitGui() )
154 bool wxApp::ProcessIdle()
157 event
.SetEventObject(this);
160 return event
.MoreRequested();
163 void wxApp::OnIdle(wxIdleEvent
&event
)
165 static bool s_inOnIdle
= FALSE
;
167 /* Avoid recursion (via ProcessEvent default case) */
173 /* Resend in the main thread events which have been prepared in other
175 ProcessPendingEvents();
177 // 'Garbage' collection of windows deleted with Close().
178 DeletePendingObjects();
180 // Send OnIdle events to all windows
181 if ( SendIdleEvents() )
182 event
.RequestMore(TRUE
);
187 bool wxApp::SendIdleEvents()
189 bool needMore
= FALSE
;
191 wxWindowList::Node
* node
= wxTopLevelWindows
.GetFirst();
194 wxWindow
* win
= node
->GetData();
195 if ( SendIdleEvents(win
) )
197 node
= node
->GetNext();
203 bool wxApp::SendIdleEvents(wxWindow
* win
)
205 bool needMore
= FALSE
;
208 event
.SetEventObject(win
);
210 win
->GetEventHandler()->ProcessEvent(event
);
212 #if 0 // FIXME_MGL - what the hell it is?
213 win
->OnInternalIdle();
215 if ( event
.MoreRequested() )
219 wxNode
* node
= win
->GetChildren().First();
222 wxWindow
* win
= (wxWindow
*) node
->Data();
223 if ( SendIdleEvents(win
) )
231 int wxApp::MainLoop()
234 m_mainLoop
= new wxEventLoop
;
236 rt
= m_mainLoop
->Run();
243 void wxApp::ExitMainLoop()
249 bool wxApp::Initialized()
251 // FIXME_MGL -- only for now because we don't have wxFrame/wxDialog yet
253 //return (wxTopLevelWindows.GetCount() != 0);
256 bool wxApp::Pending()
258 return wxEventLoop::GetActive()->Pending();
261 void wxApp::Dispatch()
263 wxEventLoop::GetActive()->Dispatch();
266 void wxApp::DeletePendingObjects()
268 wxNode
*node
= wxPendingDelete
.First();
271 wxObject
*obj
= (wxObject
*)node
->Data();
275 if ( wxPendingDelete
.Find(obj
) )
278 node
= wxPendingDelete
.First();
282 bool wxApp::Initialize()
284 wxBuffer
= new wxChar
[BUFSIZ
+ 512];
286 wxClassInfo::InitializeClasses();
288 wxSystemSettings::Init();
291 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
294 // GL: I'm annoyed ... I don't know where to put this and I don't want to
295 // create a module for that as it's part of the core.
297 wxPendingEvents
= new wxList
;
298 wxPendingEventsLocker
= new wxCriticalSection
;
301 wxTheColourDatabase
= new wxColourDatabase(wxKEY_STRING
);
302 wxTheColourDatabase
->Initialize();
304 // Can't do this in wxModule, because fonts are needed by stock lists
305 wxTheFontsManager
= new wxFontsManager
;
307 wxInitializeStockLists();
308 wxInitializeStockObjects();
310 #if wxUSE_WX_RESOURCES
311 wxInitializeResourceSystem();
314 wxModule::RegisterModules();
315 if (!wxModule::InitializeModules()) return FALSE
;
322 #include "question.xpm"
323 #include "warning.xpm"
325 wxIcon
wxApp::GetStdIcon(int which
) const
329 case wxICON_INFORMATION
:
330 return wxIcon(info_xpm
);
331 case wxICON_QUESTION
:
332 return wxIcon(question_xpm
);
333 case wxICON_EXCLAMATION
:
334 return wxIcon(warning_xpm
);
336 wxFAIL_MSG(wxT("requested non existent standard icon"));
337 // still fall through
339 return wxIcon(error_xpm
);
343 void wxApp::CleanUp()
346 // flush the logged messages if any
347 wxLog
*log
= wxLog::GetActiveTarget();
348 if (log
!= NULL
&& log
->HasPendingMessages())
351 // continuing to use user defined log target is unsafe from now on because
352 // some resources may be already unavailable, so replace it by something
354 wxLog
*oldlog
= wxLog::SetActiveTarget(new wxLogStderr
);
359 wxModule::CleanUpModules();
361 #if wxUSE_WX_RESOURCES
362 wxCleanUpResourceSystem();
365 if (wxTheColourDatabase
)
366 delete wxTheColourDatabase
;
368 wxTheColourDatabase
= (wxColourDatabase
*) NULL
;
370 wxDeleteStockObjects();
371 wxDeleteStockLists();
373 // Can't do this in wxModule, because fonts are needed by stock lists
374 delete wxTheFontsManager
;
375 wxTheFontsManager
= (wxFontsManager
*) NULL
;
378 wxTheApp
= (wxApp
*) NULL
;
380 // GL: I'm annoyed ... I don't know where to put this and I don't want to
381 // create a module for that as it's part of the core.
383 delete wxPendingEvents
;
384 delete wxPendingEventsLocker
;
387 wxSystemSettings::Done();
391 wxClassInfo::CleanUpClasses();
393 // check for memory leaks
394 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
395 if (wxDebugContext::CountObjectsLeft(TRUE
) > 0)
397 wxLogDebug(wxT("There were memory leaks.\n"));
398 wxDebugContext::Dump();
399 wxDebugContext::PrintStatistics();
404 // do this as the very last thing because everything else can log messages
405 wxLog::DontCreateOnDemand();
407 wxLog
*oldLog
= wxLog::SetActiveTarget( (wxLog
*) NULL
);
417 int wxEntryStart(int argc
, char *argv
[])
419 return wxApp::Initialize() ? 0 : -1;
425 return wxTheApp
->OnInitGui() ? 0 : -1;
429 void wxEntryCleanup()
436 int wxEntry(int argc
, char *argv
[])
438 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
439 // This seems to be necessary since there are 'rogue'
440 // objects present at this point (perhaps global objects?)
441 // Setting a checkpoint will ignore them as far as the
442 // memory checking facility is concerned.
443 // Of course you may argue that memory allocated in globals should be
444 // checked, but this is a reasonable compromise.
445 wxDebugContext::SetCheckpoint();
447 int err
= wxEntryStart(argc
, argv
);
453 wxCHECK_MSG( wxApp::GetInitializerFunction(), -1,
454 wxT("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") );
456 wxAppInitializerFunction app_ini
= wxApp::GetInitializerFunction();
458 wxObject
*test_app
= app_ini();
460 wxTheApp
= (wxApp
*) test_app
;
463 wxCHECK_MSG( wxTheApp
, -1, wxT("wxWindows error: no application object") );
465 wxTheApp
->argc
= argc
;
467 wxTheApp
->argv
= new wxChar
*[argc
+1];
469 while (mb_argc
< argc
)
471 wxTheApp
->argv
[mb_argc
] = wxStrdup(wxConvLibc
.cMB2WX(argv
[mb_argc
]));
474 wxTheApp
->argv
[mb_argc
] = (wxChar
*)NULL
;
476 wxTheApp
->argv
= argv
;
479 wxString
name(wxFileNameFromPath(argv
[0]));
480 wxStripExtension(name
);
481 wxTheApp
->SetAppName(name
);
484 retValue
= wxEntryInitGui();
486 // Here frames insert themselves automatically into wxTopLevelWindows by
487 // getting created in OnInit().
490 if ( !wxTheApp
->OnInit() )
496 /* delete pending toplevel windows (typically a single
497 dialog) so that, if there isn't any left, we don't
499 wxTheApp
->DeletePendingObjects();
501 if ( wxTheApp
->Initialized() )
505 wxWindow
*topWindow
= wxTheApp
->GetTopWindow();
508 /* Forcibly delete the window. */
509 if (topWindow
->IsKindOf(CLASSINFO(wxFrame
)) ||
510 topWindow
->IsKindOf(CLASSINFO(wxDialog
)) )
512 topWindow
->Close(TRUE
);
513 wxTheApp
->DeletePendingObjects();
518 wxTheApp
->SetTopWindow((wxWindow
*) NULL
);
522 retValue
= wxTheApp
->OnExit();