1///////////////////////////////////////////////////////////////////////////// 2// Name: src/mgl/app.cpp 3// Author: Vaclav Slavik 4// based on GTK and MSW implementations 5// Id: $Id: app.cpp 53607 2008-05-16 15:21:40Z SN $ 6// Copyright: (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com) 7// Licence: wxWindows licence 8///////////////////////////////////////////////////////////////////////////// 9 10// For compilers that support precompilation, includes "wx.h". 11#include "wx/wxprec.h" 12 13#ifdef __BORLANDC__ 14 #pragma hdrstop 15#endif 16 17#include "wx/app.h" 18 19#ifndef WX_PRECOMP 20 #include "wx/settings.h" 21 #include "wx/frame.h" 22 #include "wx/dialog.h" 23 #include "wx/log.h" 24 #include "wx/intl.h" 25 #include "wx/module.h" 26#endif 27 28#include "wx/evtloop.h" 29#include "wx/fontutil.h" 30#include "wx/univ/theme.h" 31#include "wx/univ/renderer.h" 32#include "wx/univ/colschem.h" 33#include "wx/sysopt.h" 34#include "wx/mgl/private.h" 35#include "wx/private/fontmgr.h" 36 37//----------------------------------------------------------------------------- 38// wxApp::Exit() 39//----------------------------------------------------------------------------- 40 41void wxApp::Exit() 42{ 43 MGL_exit(); 44 exit(0); 45} 46 47//----------------------------------------------------------------------------- 48// wxYield 49//----------------------------------------------------------------------------- 50 51static bool gs_inYield = false; 52 53bool wxApp::Yield(bool onlyIfNeeded) 54{ 55 if ( gs_inYield ) 56 { 57 if ( !onlyIfNeeded ) 58 { 59 wxFAIL_MSG( wxT("wxYield called recursively" ) ); 60 } 61 62 return false; 63 } 64 65#if wxUSE_THREADS 66 if ( !wxThread::IsMain() ) 67 { 68 // can't process events from other threads, MGL is thread-unsafe 69 return true; 70 } 71#endif // wxUSE_THREADS 72 73 gs_inYield = true; 74 75 wxLog::Suspend(); 76 77 // A guarentee that there will be an active event loop: 78 wxEventLoopGuarantor dummyLoopIfNeeded; 79 while (wxEventLoop::GetActive()->Pending()) 80 wxEventLoop::GetActive()->Dispatch(); 81 82 /* it's necessary to call ProcessIdle() to update the frames sizes which 83 might have been changed (it also will update other things set from 84 OnUpdateUI() which is a nice (and desired) side effect) */ 85 while (wxTheApp->ProcessIdle()) { } 86 87 wxLog::Resume(); 88 89 gs_inYield = false; 90 91 return true; 92} 93 94 95//----------------------------------------------------------------------------- 96// wxWakeUpIdle 97//----------------------------------------------------------------------------- 98 99void wxApp::WakeUpIdle() 100{ 101#if wxUSE_THREADS 102 if (!wxThread::IsMain()) 103 wxMutexGuiEnter(); 104#endif 105 106 while (wxTheApp->ProcessIdle()) 107 ; 108 109#if wxUSE_THREADS 110 if (!wxThread::IsMain()) 111 wxMutexGuiLeave(); 112#endif 113} 114 115//----------------------------------------------------------------------------- 116// Root window 117//----------------------------------------------------------------------------- 118 119class wxRootWindow : public wxWindow 120{ 121 public: 122 wxRootWindow() : wxWindow(NULL, wxID_ANY) 123 { 124 SetMGLwindow_t(MGL_wmGetRootWindow(g_winMng)); 125 SetBackgroundColour(wxTHEME_COLOUR(DESKTOP)); 126 } 127 virtual ~wxRootWindow() 128 { 129 // we don't want to delete MGL_WM's rootWnd 130 m_wnd = NULL; 131 } 132 133 virtual bool AcceptsFocus() const { return false; } 134 135 DECLARE_DYNAMIC_CLASS(wxRootWindow) 136}; 137 138IMPLEMENT_DYNAMIC_CLASS(wxRootWindow, wxWindow) 139 140static wxRootWindow *gs_rootWindow = NULL; 141 142//----------------------------------------------------------------------------- 143// MGL initialization 144//----------------------------------------------------------------------------- 145 146static bool wxCreateMGL_WM(const wxVideoMode& displayMode) 147{ 148 int mode; 149 int refresh = MGL_DEFAULT_REFRESH; 150 151#if wxUSE_SYSTEM_OPTIONS 152 if ( wxSystemOptions::HasOption(wxT("mgl.screen-refresh")) ) 153 refresh = wxSystemOptions::GetOptionInt(wxT("mgl.screen-refresh")); 154#endif 155 156 mode = MGL_findMode(displayMode.GetWidth(), 157 displayMode.GetHeight(), 158 displayMode.GetDepth()); 159 if ( mode == -1 ) 160 { 161 wxLogError(_("Mode %ix%i-%i not available."), 162 displayMode.GetWidth(), 163 displayMode.GetHeight(), 164 displayMode.GetDepth()); 165 return false; 166 } 167 g_displayDC = new MGLDisplayDC(mode, 1, refresh); 168 if ( !g_displayDC->isValid() ) 169 { 170 delete g_displayDC; 171 g_displayDC = NULL; 172 return false; 173 } 174 175 g_winMng = MGL_wmCreate(g_displayDC->getDC()); 176 if (!g_winMng) 177 return false; 178 179 return true; 180} 181 182static void wxDestroyMGL_WM() 183{ 184 if ( g_winMng ) 185 { 186 MGL_wmDestroy(g_winMng); 187 g_winMng = NULL; 188 } 189 if ( g_displayDC ) 190 { 191 delete g_displayDC; 192 g_displayDC = NULL; 193 } 194} 195 196//----------------------------------------------------------------------------- 197// wxApp 198//----------------------------------------------------------------------------- 199 200IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler) 201 202BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) 203 EVT_IDLE(wxAppBase::OnIdle) 204END_EVENT_TABLE() 205 206 207wxApp::wxApp() 208{ 209} 210 211wxApp::~wxApp() 212{ 213} 214 215wxVideoMode wxGetDefaultDisplayMode() 216{ 217 wxString mode; 218 unsigned w, h, bpp; 219 220 if ( !wxGetEnv(wxT("WXMODE"), &mode) || 221 (wxSscanf(mode.c_str(), _T("%ux%u-%u"), &w, &h, &bpp) != 3) ) 222 { 223 w = 640, h = 480, bpp = 16; 224 } 225 226 return wxVideoMode(w, h, bpp); 227} 228 229bool wxApp::SetDisplayMode(const wxVideoMode& mode) 230{ 231 if ( !mode.IsOk() ) 232 { 233 return false; 234 } 235 if ( g_displayDC != NULL ) 236 { 237 // FIXME_MGL -- we currently don't allow to switch video mode 238 // more than once. This can hopefully be changed... 239 wxFAIL_MSG(wxT("Can't change display mode after intialization!")); 240 return false; 241 } 242 243 if ( !wxCreateMGL_WM(mode) ) 244 return false; 245 gs_rootWindow = new wxRootWindow; 246 247 m_displayMode = mode; 248 249 return true; 250} 251 252bool wxApp::OnInitGui() 253{ 254 if ( !wxAppBase::OnInitGui() ) 255 return false; 256 257#ifdef __WXDEBUG__ 258 // MGL redirects stdout and stderr to physical console, so lets redirect 259 // it to file in debug build. Do it only when WXSTDERR environment variable is set 260 wxString redirect; 261 if ( wxGetEnv(wxT("WXSTDERR"), &redirect) ) 262 freopen(redirect.mb_str(), "wt", stderr); 263#endif // __WXDEBUG__ 264 265 wxLog *oldLog = wxLog::SetActiveTarget(new wxLogGui); 266 if ( oldLog ) delete oldLog; 267 268 return true; 269} 270 271bool wxApp::Initialize(int& argc, wxChar **argv) 272{ 273#ifdef __DJGPP__ 274 // VS: disable long filenames under DJGPP as the very first thing, 275 // since SciTech MGL doesn't like them much... 276 wxSetEnv(wxT("LFN"), wxT("N")); 277#endif 278 279 // intialize MGL before creating wxFontsManager since it uses MGL funcs 280 if ( MGL_init(".", NULL) == 0 ) 281 { 282 wxLogError(_("Cannot initialize SciTech MGL!")); 283 return false; 284 } 285 286 if ( !wxAppBase::Initialize(argc, argv) ) 287 { 288 MGL_exit(); 289 return false; 290 } 291 292#if wxUSE_INTL 293 wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding()); 294#endif 295 296 return true; 297} 298 299// Modules are cleaned up after wxApp::CleanUp(), and some modules may 300// require MGL to still be alive, e.g. the stock fonts need the fonts 301// manager. So append this module last minute in wxApp::CleanUp() to close 302// down MGL after all the other modules have been cleaned up. 303// 304struct wxMGLFinalCleanup: public wxModule 305{ 306 bool OnInit() { return true; } 307 308 void OnExit() 309 { 310 wxFontsManager::CleanUp(); 311 312 wxDestroyMGL_WM(); 313 MGL_exit(); 314 } 315}; 316 317void wxApp::CleanUp() 318{ 319 delete gs_rootWindow; 320 321 wxAppBase::CleanUp(); 322 323 wxModule::RegisterModule(new wxMGLFinalCleanup); 324} 325