From 7bdc18790e34d17edfc02f3e25edcb3425b38a8a Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Thu, 9 Aug 2001 22:40:39 +0000 Subject: [PATCH] wxMGL wxWindow and wxApp mostly complete, now hunting bugs git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11341 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/mgl/app.h | 57 ++--- include/wx/mgl/dc.h | 3 + include/wx/mgl/dcclient.h | 10 +- include/wx/mgl/settings.h | 15 +- include/wx/mgl/window.h | 5 +- src/mgl/app.cpp | 456 ++++++++++++++++++++++++++++++++++++-- src/mgl/cursor.cpp | 3 + src/mgl/dc.cpp | 32 ++- src/mgl/dcclient.cpp | 33 ++- src/mgl/evtloop.cpp | 176 +++++++++++++++ src/mgl/settings.cpp | 26 ++- src/mgl/utils.cpp | 33 ++- src/mgl/window.cpp | 109 ++++----- 13 files changed, 802 insertions(+), 156 deletions(-) create mode 100644 src/mgl/evtloop.cpp diff --git a/include/wx/mgl/app.h b/include/wx/mgl/app.h index 1b2506c2b0..8cb604c6a1 100644 --- a/include/wx/mgl/app.h +++ b/include/wx/mgl/app.h @@ -21,8 +21,8 @@ // classes //----------------------------------------------------------------------------- -class wxApp; -class wxLog; +class WXDLLEXPORT wxApp; +class WXDLLEXPORT wxLog; //----------------------------------------------------------------------------- // wxApp @@ -31,59 +31,40 @@ class wxLog; class WXDLLEXPORT wxApp: public wxAppBase { public: - wxApp() {} - ~wxApp() {} + wxApp(); + ~wxApp(); /* override for altering the way wxGTK intializes the GUI * (palette/visual/colorcube). under wxMSW, OnInitGui() does nothing by * default. when overriding this method, the code in it is likely to be * platform dependent, otherwise use OnInit(). */ - virtual bool OnInitGui() {return 0;} + virtual bool OnInitGui(); // override base class (pure) virtuals - virtual int MainLoop() {return 0;} - virtual void ExitMainLoop() {} - virtual bool Initialized() {return 0;} - virtual bool Pending() {return 0;} - virtual void Dispatch() {} + virtual int MainLoop(); + virtual void ExitMainLoop(); + virtual bool Initialized(); + virtual bool Pending(); + virtual void Dispatch(); - virtual wxIcon GetStdIcon(int which) const {return wxNullIcon;} + virtual wxIcon GetStdIcon(int which) const; // implementation only from now on - void OnIdle( wxIdleEvent &event ) {} - bool SendIdleEvents() {return 0;} - bool SendIdleEvents( wxWindow* win ) {return 0;} + void OnIdle(wxIdleEvent &event); + bool SendIdleEvents(); + bool SendIdleEvents(wxWindow* win); - static bool Initialize() {return 0;} - static bool InitialzeVisual() {return 0;} - static void CleanUp() {} + static bool Initialize(); + static void CleanUp(); - bool ProcessIdle() {return 0;} - void DeletePendingObjects() {} - - // This can be used to suppress the generation of Idle events. - void SuppressIdleEvents(bool arg = TRUE) { m_suppressIdleEvents = arg; } - bool GetSuppressIdleEvents() const { return m_suppressIdleEvents; } - -#if 0 //FIXME MGL - bool m_initialized; - - gint m_idleTag; -#if wxUSE_THREADS - gint m_wakeUpTimerTag; -#endif - unsigned char *m_colorCube; -#endif - -private: - /// Set to TRUE while we are in wxYield(). - bool m_suppressIdleEvents; + bool ProcessIdle(); + void DeletePendingObjects(); private: DECLARE_DYNAMIC_CLASS(wxApp) DECLARE_EVENT_TABLE() }; -int WXDLLEXPORT wxEntry( int argc, char *argv[] ); +int WXDLLEXPORT wxEntry(int argc, char *argv[]); #endif // __WX_APP_H__ diff --git a/include/wx/mgl/dc.h b/include/wx/mgl/dc.h index 5d4b1c1be1..d59cec8a7b 100644 --- a/include/wx/mgl/dc.h +++ b/include/wx/mgl/dc.h @@ -45,6 +45,7 @@ class WXDLLEXPORT wxDC; // MGL fwd declarations: class MGLDevCtx; +class MGLRegion; struct font_t; class WXDLLEXPORT wxDC : public wxDCBase @@ -268,6 +269,8 @@ protected: wxPalette m_oldPalette; wxRegion m_currentClippingRegion; + // clipping region m_MGLDC had when it was attached: + MGLRegion *m_globalClippingRegion; // wxDC::Blit handles memoryDCs as special cases :( bool m_isMemDC; diff --git a/include/wx/mgl/dcclient.h b/include/wx/mgl/dcclient.h index f062e9d5e7..37f8ea423e 100644 --- a/include/wx/mgl/dcclient.h +++ b/include/wx/mgl/dcclient.h @@ -16,8 +16,6 @@ #include "wx/dc.h" -class WXDLLEXPORT wxWindowMGL; - //----------------------------------------------------------------------------- // classes //----------------------------------------------------------------------------- @@ -25,6 +23,7 @@ class WXDLLEXPORT wxWindowMGL; class WXDLLEXPORT wxWindowDC; class WXDLLEXPORT wxPaintDC; class WXDLLEXPORT wxClientDC; +class WXDLLEXPORT wxWindowMGL; //----------------------------------------------------------------------------- // wxWindowDC @@ -39,6 +38,7 @@ public: protected: wxWindow *m_wnd; + bool m_inPaintHandler; private: DECLARE_DYNAMIC_CLASS(wxWindowDC) @@ -55,7 +55,6 @@ public: wxClientDC(wxWindow *win); private: - wxWindowMGL *m_wnd; DECLARE_DYNAMIC_CLASS(wxClientDC) }; @@ -63,12 +62,11 @@ private: // wxPaintDC //----------------------------------------------------------------------------- -// FIXME_MGL class WXDLLEXPORT wxPaintDC : public wxClientDC { public: - wxPaintDC() { } - wxPaintDC( wxWindow *win ) {} + wxPaintDC() : wxClientDC() {} + wxPaintDC(wxWindow *win) : wxClientDC(win) {} private: DECLARE_DYNAMIC_CLASS(wxPaintDC) diff --git a/include/wx/mgl/settings.h b/include/wx/mgl/settings.h index 78204b3f07..5ecfa01f8e 100644 --- a/include/wx/mgl/settings.h +++ b/include/wx/mgl/settings.h @@ -1,9 +1,8 @@ ///////////////////////////////////////////////////////////////////////////// // Name: settings.h -// Purpose: -// Author: Robert Roebling +// Author: Vaclav Slavik // Id: $Id$ -// Copyright: (c) 1998 Robert Roebling +// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com) // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -24,19 +23,19 @@ class wxSystemSettings: public wxObject { public: - inline wxSystemSettings() {} + wxSystemSettings() {} - inline static void Init() {} + static void Init() {} static void Done() {} // Get a system colour - static wxColour GetSystemColour(int index) {} + static wxColour GetSystemColour(int index); // Get a system font - static wxFont GetSystemFont(int index) {} + static wxFont GetSystemFont(int index); // Get a system metric, e.g. scrollbar size - static int GetSystemMetric(int index) {} + static int GetSystemMetric(int index); }; #endif diff --git a/include/wx/mgl/window.h b/include/wx/mgl/window.h index 4cd53c3d27..9735d47aba 100644 --- a/include/wx/mgl/window.h +++ b/include/wx/mgl/window.h @@ -113,7 +113,6 @@ protected: // (see wxWindow::Refresh) bool m_frozen; bool m_refreshAfterThaw; - wxFont m_font; // implement the base class pure virtuals virtual void DoClientToScreen( int *x, int *y ) const; @@ -141,9 +140,6 @@ private: MGLDevCtx *m_paintMGLDC; friend class wxPaintDC; - void OnEraseBackground(wxEraseEvent& event); - void OnSetFocus(wxFocusEvent& event); - DECLARE_DYNAMIC_CLASS(wxWindowMGL); DECLARE_NO_COPY_CLASS(wxWindowMGL); DECLARE_EVENT_TABLE() @@ -151,6 +147,7 @@ private: public: void HandlePaint(MGLDevCtx *dc); // needed by wxWindowPainter + MGLDevCtx *GetPaintMGLDC() const { return m_paintMGLDC; } }; diff --git a/src/mgl/app.cpp b/src/mgl/app.cpp index f1c96de528..d8b012870e 100644 --- a/src/mgl/app.cpp +++ b/src/mgl/app.cpp @@ -1,7 +1,7 @@ ///////////////////////////////////////////////////////////////////////////// // Name: app.cpp -// Purpose: // Author: Vaclav Slavik +// based on GTK and MSW implementations // Id: $Id$ // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com) // Licence: wxWindows licence @@ -11,28 +11,42 @@ #pragma implementation "app.h" #endif -#include "wx/app.h" -#include "wx/settings.h" -#include "wx/module.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/settings.h" + #include "wx/module.h" + #include "wx/evtloop.h" + #include "wx/frame.h" + #include "wx/dialog.h" + #include "wx/intl.h" +#endif -#include +#include "wx/app.h" +#include "wx/mgl/private.h" //----------------------------------------------------------------------------- // Global data //----------------------------------------------------------------------------- -wxApp *wxTheApp = (wxApp *) NULL; +wxApp *wxTheApp = NULL; wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL; -// FIXME_MGL - whole file - +static wxEventLoop *gs_mainEventLoop = NULL; -extern bool g_isIdle; -bool g_mainThreadLocked = FALSE; +//----------------------------------------------------------------------------- +// wxExit +//----------------------------------------------------------------------------- void wxExit() { + MGL_exit(); exit(0); } @@ -40,17 +54,63 @@ void wxExit() // wxYield //----------------------------------------------------------------------------- +static bool gs_inYield = FALSE; + bool wxYield() { +#if wxUSE_THREADS + if ( !wxThread::IsMain() ) + { + // can't process events from other threads, MGL is thread-unsafe + return TRUE; + } +#endif // wxUSE_THREADS + + gs_inYield = TRUE; + + wxLog::Suspend(); + + while (gs_mainEventLoop->Pending()) + gs_mainEventLoop->Dispatch(); + + /* it's necessary to call ProcessIdle() to update the frames sizes which + might have been changed (it also will update other things set from + OnUpdateUI() which is a nice (and desired) side effect) */ + while (wxTheApp->ProcessIdle()) { } + + wxLog::Resume(); + + gs_inYield = FALSE; + return TRUE; } +bool wxYieldIfNeeded() +{ + if (gs_inYield) + return FALSE; + + return wxYield(); +} + + //----------------------------------------------------------------------------- // wxWakeUpIdle //----------------------------------------------------------------------------- void wxWakeUpIdle() { +#if wxUSE_THREADS + if (!wxThread::IsMain()) + wxMutexGuiEnter(); +#endif + + while (wxTheApp->ProcessIdle()) {} + +#if wxUSE_THREADS + if (!wxThread::IsMain()) + wxMutexGuiLeave(); +#endif } //----------------------------------------------------------------------------- @@ -64,26 +124,390 @@ BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) END_EVENT_TABLE() -int wxEntry( int argc, char *argv[] ) +wxApp::wxApp() +{ +} + +wxApp::~wxApp() +{ +} + +bool wxApp::OnInitGui() +{ + if ( MGL_init(".", NULL) == 0 ) + return FALSE; + if ( !wxCreateMGL_WM() ) + return FALSE; + + // This has to be done *after* wxCreateMGL_WM() because it initializes + // wxUniv's themes + if ( !wxAppBase::OnInitGui() ) + return FALSE; + + return TRUE; +} + +bool wxApp::ProcessIdle() +{ + wxIdleEvent event; + event.SetEventObject(this); + ProcessEvent(event); + + return event.MoreRequested(); +} + +void wxApp::OnIdle(wxIdleEvent &event) +{ + static bool s_inOnIdle = FALSE; + + /* Avoid recursion (via ProcessEvent default case) */ + if (s_inOnIdle) + return; + + s_inOnIdle = TRUE; + + /* Resend in the main thread events which have been prepared in other + threads */ + ProcessPendingEvents(); + + // 'Garbage' collection of windows deleted with Close(). + DeletePendingObjects(); + + // Send OnIdle events to all windows + if ( SendIdleEvents() ) + event.RequestMore(TRUE); + + s_inOnIdle = FALSE; +} + +bool wxApp::SendIdleEvents() +{ + bool needMore = FALSE; + + wxWindowList::Node* node = wxTopLevelWindows.GetFirst(); + while (node) + { + wxWindow* win = node->GetData(); + if ( SendIdleEvents(win) ) + needMore = TRUE; + node = node->GetNext(); + } + + return needMore; +} + +bool wxApp::SendIdleEvents(wxWindow* win) +{ + bool needMore = FALSE; + + wxIdleEvent event; + event.SetEventObject(win); + + win->GetEventHandler()->ProcessEvent(event); + +#if 0 // FIXME_MGL - what the hell it is? + win->OnInternalIdle(); + + if ( event.MoreRequested() ) + needMore = TRUE; +#endif + + wxNode* node = win->GetChildren().First(); + while (node) + { + wxWindow* win = (wxWindow*) node->Data(); + if ( SendIdleEvents(win) ) + needMore = TRUE; + + node = node->Next(); + } + return needMore; +} + +int wxApp::MainLoop() +{ + gs_mainEventLoop = new wxEventLoop; + return gs_mainEventLoop->Run(); + delete gs_mainEventLoop; + gs_mainEventLoop = NULL; +} + +void wxApp::ExitMainLoop() +{ + gs_mainEventLoop->Exit(0); +} + +bool wxApp::Initialized() +{ + return (GetTopWindow() != NULL); +} + +bool wxApp::Pending() +{ + return gs_mainEventLoop->Pending(); +} + +void wxApp::Dispatch() { - return 0; + gs_mainEventLoop->Dispatch(); } +void wxApp::DeletePendingObjects() +{ + wxNode *node = wxPendingDelete.First(); + while (node) + { + wxObject *obj = (wxObject *)node->Data(); + + delete obj; + + if ( wxPendingDelete.Find(obj) ) + delete node; -// FIXME_MGL - this is temporary solution, will be removed -// once I have wxApp up and running -bool wxMGL_Initialize() + node = wxPendingDelete.First(); + } +} + +bool wxApp::Initialize() { wxBuffer = new wxChar[BUFSIZ + 512]; wxClassInfo::InitializeClasses(); + wxSystemSettings::Init(); - wxTheColourDatabase = new wxColourDatabase( wxKEY_STRING ); + +#if wxUSE_INTL + wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding()); +#endif + + // GL: I'm annoyed ... I don't know where to put this and I don't want to + // create a module for that as it's part of the core. +#if wxUSE_THREADS + wxPendingEvents = new wxList; + wxPendingEventsLocker = new wxCriticalSection; +#endif + + wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING); wxTheColourDatabase->Initialize(); + wxInitializeStockLists(); wxInitializeStockObjects(); + +#if wxUSE_WX_RESOURCES + wxInitializeResourceSystem(); +#endif + wxModule::RegisterModules(); if (!wxModule::InitializeModules()) return FALSE; + return TRUE; } +#include "info.xpm" +#include "error.xpm" +#include "question.xpm" +#include "warning.xpm" + +wxIcon wxApp::GetStdIcon(int which) const +{ + switch(which) + { + case wxICON_INFORMATION: + return wxIcon(info_xpm); + case wxICON_QUESTION: + return wxIcon(question_xpm); + case wxICON_EXCLAMATION: + return wxIcon(warning_xpm); + default: + wxFAIL_MSG(wxT("requested non existent standard icon")); + // still fall through + case wxICON_HAND: + return wxIcon(error_xpm); + } +} + +void wxApp::CleanUp() +{ +#if wxUSE_LOG + // flush the logged messages if any + wxLog *log = wxLog::GetActiveTarget(); + if (log != NULL && log->HasPendingMessages()) + log->Flush(); + + // continuing to use user defined log target is unsafe from now on because + // some resources may be already unavailable, so replace it by something + // more safe + wxLog *oldlog = wxLog::SetActiveTarget(new wxLogStderr); + if ( oldlog ) + delete oldlog; +#endif // wxUSE_LOG + + wxModule::CleanUpModules(); + +#if wxUSE_WX_RESOURCES + wxCleanUpResourceSystem(); +#endif + + if (wxTheColourDatabase) + delete wxTheColourDatabase; + + wxTheColourDatabase = (wxColourDatabase*) NULL; + + wxDeleteStockObjects(); + + wxDeleteStockLists(); + + delete wxTheApp; + wxTheApp = (wxApp*) NULL; + + // GL: I'm annoyed ... I don't know where to put this and I don't want to + // create a module for that as it's part of the core. +#if wxUSE_THREADS + delete wxPendingEvents; + delete wxPendingEventsLocker; +#endif + + wxSystemSettings::Done(); + + delete[] wxBuffer; + + wxClassInfo::CleanUpClasses(); + + // check for memory leaks +#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT + if (wxDebugContext::CountObjectsLeft(TRUE) > 0) + { + wxLogDebug(wxT("There were memory leaks.\n")); + wxDebugContext::Dump(); + wxDebugContext::PrintStatistics(); + } +#endif // Debug + +#if wxUSE_LOG + // do this as the very last thing because everything else can log messages + wxLog::DontCreateOnDemand(); + + wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL ); + if (oldLog) + delete oldLog; +#endif // wxUSE_LOG + + wxDestroyMGL_WM(); + MGL_exit(); +} + + +int wxEntryStart(int argc, char *argv[]) +{ + return wxApp::Initialize() ? 0 : -1; +} + + +int wxEntryInitGui() +{ + return wxTheApp->OnInitGui() ? 0 : -1; +} + + +void wxEntryCleanup() +{ + wxApp::CleanUp(); +} + + + +int wxEntry(int argc, char *argv[]) +{ +#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT + // This seems to be necessary since there are 'rogue' + // objects present at this point (perhaps global objects?) + // Setting a checkpoint will ignore them as far as the + // memory checking facility is concerned. + // Of course you may argue that memory allocated in globals should be + // checked, but this is a reasonable compromise. + wxDebugContext::SetCheckpoint(); +#endif + int err = wxEntryStart(argc, argv); + if ( err ) + return err; + + if ( !wxTheApp ) + { + wxCHECK_MSG( wxApp::GetInitializerFunction(), -1, + wxT("wxWindows error: No initializer - use IMPLEMENT_APP macro.\n") ); + + wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction(); + + wxObject *test_app = app_ini(); + + wxTheApp = (wxApp*) test_app; + } + + wxCHECK_MSG( wxTheApp, -1, wxT("wxWindows error: no application object") ); + + wxTheApp->argc = argc; +#if wxUSE_UNICODE + wxTheApp->argv = new wxChar*[argc+1]; + int mb_argc = 0; + while (mb_argc < argc) + { + wxTheApp->argv[mb_argc] = wxStrdup(wxConvLibc.cMB2WX(argv[mb_argc])); + mb_argc++; + } + wxTheApp->argv[mb_argc] = (wxChar *)NULL; +#else + wxTheApp->argv = argv; +#endif + + wxString name(wxFileNameFromPath(argv[0])); + wxStripExtension(name); + wxTheApp->SetAppName(name); + + int retValue; + retValue = wxEntryInitGui(); + + // Here frames insert themselves automatically into wxTopLevelWindows by + // getting created in OnInit(). + if ( retValue == 0 ) + { + if ( !wxTheApp->OnInit() ) + retValue = -1; + } + + if ( retValue == 0 ) + { + /* delete pending toplevel windows (typically a single + dialog) so that, if there isn't any left, we don't + call OnRun() */ + wxTheApp->DeletePendingObjects(); + + if ( wxTheApp->Initialized() && + wxTopLevelWindows.GetCount() != 0 ) + { + wxTheApp->OnRun(); + + wxWindow *topWindow = wxTheApp->GetTopWindow(); + if ( topWindow ) + { + /* Forcibly delete the window. */ + if (topWindow->IsKindOf(CLASSINFO(wxFrame)) || + topWindow->IsKindOf(CLASSINFO(wxDialog)) ) + { + topWindow->Close(TRUE); + wxTheApp->DeletePendingObjects(); + } + else + { + delete topWindow; + wxTheApp->SetTopWindow((wxWindow*) NULL); + } + } + + retValue = wxTheApp->OnExit(); + } + } + + wxEntryCleanup(); + + return retValue; +} diff --git a/src/mgl/cursor.cpp b/src/mgl/cursor.cpp index 0764b93519..1e4867ae70 100644 --- a/src/mgl/cursor.cpp +++ b/src/mgl/cursor.cpp @@ -68,6 +68,9 @@ wxCursor::wxCursor(int cursorId) switch (cursorId) { + // FIXME_MGL -- what about storing these default cursors in executable + // as XPMs so that wxMGL binary wouldn't depend on + // tons of files in $MGL_ROOT/cursors? I don't know yet... case wxCURSOR_ARROW: cursorname = "arrow.cur"; break; case wxCURSOR_BULLSEYE: cursorname = "bullseye.cur"; break; case wxCURSOR_CHAR: cursorname = "char.cur"; break; diff --git a/src/mgl/dc.cpp b/src/mgl/dc.cpp index bc91b0e75e..a2d932bd5a 100644 --- a/src/mgl/dc.cpp +++ b/src/mgl/dc.cpp @@ -172,6 +172,7 @@ wxDC::wxDC() m_downloadedPatterns[0] = m_downloadedPatterns[1] = FALSE; m_mglFont = NULL; + m_globalClippingRegion = NULL; } @@ -179,6 +180,7 @@ wxDC::~wxDC() { if (m_OwnsMGLDC) delete m_MGLDC; + delete m_globalClippingRegion; } void wxDC::SetMGLDC(MGLDevCtx *mgldc, bool OwnsMGLDC) @@ -188,6 +190,15 @@ void wxDC::SetMGLDC(MGLDevCtx *mgldc, bool OwnsMGLDC) m_MGLDC = mgldc; m_OwnsMGLDC = OwnsMGLDC; m_ok = TRUE; + + if ( mgldc->getDC()->a.clipRegion ) + { + m_globalClippingRegion = new MGLRegion; + mgldc->getClipRegion(*m_globalClippingRegion); + } + else + m_globalClippingRegion = NULL; + InitializeMGLDC(); } @@ -226,7 +237,13 @@ void wxDC::DoSetClippingRegion(wxCoord cx, wxCoord cy, wxCoord cw, wxCoord ch) else m_currentClippingRegion.Union(rect); - m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion()); + if ( m_globalClippingRegion ) + { + m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion() + & *m_globalClippingRegion); + } + else + m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion()); m_clipping = TRUE; DO_SET_CLIPPING_BOX(m_currentClippingRegion) @@ -265,7 +282,13 @@ void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region) else m_currentClippingRegion.Union(rg); - m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion()); + if ( m_globalClippingRegion ) + { + m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion() + & *m_globalClippingRegion); + } + else + m_MGLDC->setClipRegion(m_currentClippingRegion.GetMGLRegion()); m_clipping = TRUE; DO_SET_CLIPPING_BOX(m_currentClippingRegion) @@ -275,7 +298,10 @@ void wxDC::DestroyClippingRegion() { wxCHECK_RET( Ok(), wxT("invalid dc") ); - m_MGLDC->setClipRect(MGLRect(0, 0, m_MGLDC->sizex(), m_MGLDC->sizey())); + if ( m_globalClippingRegion ) + m_MGLDC->setClipRegion(*m_globalClippingRegion); + else + m_MGLDC->setClipRect(MGLRect(0, 0, m_MGLDC->sizex(), m_MGLDC->sizey())); m_clipping = FALSE; m_currentClippingRegion.Clear(); } diff --git a/src/mgl/dcclient.cpp b/src/mgl/dcclient.cpp index f3bef5fbd7..8edae04c3b 100644 --- a/src/mgl/dcclient.cpp +++ b/src/mgl/dcclient.cpp @@ -26,20 +26,41 @@ #include IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC) -IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC) IMPLEMENT_DYNAMIC_CLASS(wxClientDC,wxWindowDC) +IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC) wxWindowDC::wxWindowDC(wxWindow *win) : m_wnd(win) { - MGLDC *dc = MGL_wmBeginPaint(m_wnd->GetHandle()); - SetMGLDC(new MGLDevCtx(dc), FALSE); - // FIXME_MGL -- correctly handle setting device origin and - // clipping regions + MGLDevCtx *dc = win->GetPaintMGLDC(); + if ( dc ) + { + m_inPaintHandler = TRUE; + SetMGLDC(dc, FALSE); + } + else + { + m_inPaintHandler = FALSE; + SetMGLDC(new MGLDevCtx(MGL_wmBeginPaint(m_wnd->GetHandle())), TRUE); + // TRUE means that dtor will delete MGLDevCtx object + // but it won't destroy MGLDC returned by MGL_wmBeginPaint because + // ~MGLDevCtx() doesn't call destroy() + } } wxWindowDC::~wxWindowDC() { - MGL_wmEndPaint(m_wnd->GetHandle()); + if ( m_inPaintHandler ) + { + // This is neccessary so that subsequently created wxPaintDCs won't get + // confused about clipping. Another reason is that the same MGL dc is reused + // for wxEraseEvent, wxNcPaintEvent and wxPaintEvent + DestroyClippingRegion(); + } + else + { + GetMGLDC()->setDC(NULL); + MGL_wmEndPaint(m_wnd->GetHandle()); + } } wxClientDC::wxClientDC(wxWindow *win) : wxWindowDC(win) diff --git a/src/mgl/evtloop.cpp b/src/mgl/evtloop.cpp new file mode 100644 index 0000000000..9f8161da68 --- /dev/null +++ b/src/mgl/evtloop.cpp @@ -0,0 +1,176 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: mgl/evtloop.cpp +// Purpose: implements wxEventLoop for MGL +// Author: Vaclav Slavik +// RCS-ID: $Id$ +// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com) +// License: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#ifdef __GNUG__ + #pragma implementation "evtloop.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/window.h" + #include "wx/app.h" + #include "wx/thread.h" +#endif //WX_PRECOMP + +#include "wx/evtloop.h" + +#include "wx/mgl/private.h" + +// ---------------------------------------------------------------------------- +// wxEventLoopImpl +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxEventLoopImpl +{ +public: + // ctor + wxEventLoopImpl() + { + SetExitCode(0); + SetKeepLooping(TRUE); + } + + // process a message + void ProcessEvent(event_t *evt); + + // generate an idle message, return TRUE if more idle time requested + bool SendIdleMessage(); + + // set/get the exit code + void SetExitCode(int exitcode) { m_exitcode = exitcode; } + int GetExitCode() const { return m_exitcode; } + + void SetKeepLooping(bool k) { m_keepLooping = k; } + bool GetKeepLooping() const { return m_keepLooping; } + +private: + + // the exit code of the event loop + int m_exitcode; + // FALSE if the loop should end + bool m_keepLooping; +}; + +// ============================================================================ +// wxEventLoopImpl implementation +// ============================================================================ + +void wxEventLoopImpl::ProcessEvent(event_t *evt) +{ + MGL_wmProcessEvent(g_winMng, evt); +} + +bool wxEventLoopImpl::SendIdleMessage() +{ + wxIdleEvent event; + + return wxTheApp->ProcessEvent(event) && event.MoreRequested(); +} + +// ============================================================================ +// wxEventLoop implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxEventLoop running and exiting +// ---------------------------------------------------------------------------- + +wxEventLoop::~wxEventLoop() +{ + wxASSERT_MSG( !m_impl, _T("should have been deleted in Run()") ); +} + +bool wxEventLoop::IsRunning() const +{ + return m_impl != NULL; +} + +int wxEventLoop::Run() +{ + // event loops are not recursive, you need to create another loop! + wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") ); + + m_impl = new wxEventLoopImpl; + + for ( ;; ) + { +#if wxUSE_THREADS + //wxMutexGuiLeaveOrEnter(); // FIXME_MGL - huh? +#endif // wxUSE_THREADS + + // generate and process idle events for as long as we don't have + // anything else to do + while ( !Pending() && m_impl->SendIdleMessage() ) {} + + // a message came or no more idle processing to do, sit in Dispatch() + // waiting for the next message + if ( !Dispatch() ) + { + // app terminated + break; + } + } + + int exitcode = m_impl->GetExitCode(); + delete m_impl; + m_impl = NULL; + + return exitcode; +} + +void wxEventLoop::Exit(int rc) +{ + wxCHECK_RET( IsRunning(), _T("can't call Exit() if not running") ); + + m_impl->SetExitCode(rc); + m_impl->SetKeepLooping(FALSE); +} + +// ---------------------------------------------------------------------------- +// wxEventLoop message processing dispatching +// ---------------------------------------------------------------------------- + +bool wxEventLoop::Pending() const +{ + event_t evt; + return EVT_peekNext(&evt, EVT_EVERYEVT); +} + +bool wxEventLoop::Dispatch() +{ + wxCHECK_MSG( IsRunning(), FALSE, _T("can't call Dispatch() if not running") ); + + event_t evt; + ibool rc = EVT_getNext(&evt, EVT_EVERYEVT); + + if ( !rc ) + { + wxLogError(_T("events queue empty even though Pending() returned true")); + return FALSE; + } + + // FIXME_MGL -- there must be some way to programatically exit + // the loop, like WM_QUIT under Windows -- perhaps we need custom + // event to indicate this?? + + m_impl->ProcessEvent(&evt); + + return m_impl->GetKeepLooping(); +} + diff --git a/src/mgl/settings.cpp b/src/mgl/settings.cpp index 19427c69a5..fab6801169 100644 --- a/src/mgl/settings.cpp +++ b/src/mgl/settings.cpp @@ -1,9 +1,8 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: settings.cpp -// Purpose: -// Author: Robert Roebling +// Name: settings.h +// Author: Vaclav Slavik // Id: $Id$ -// Copyright: (c) 1998 Robert Roebling +// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com) // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -13,4 +12,23 @@ #endif #include "wx/settings.h" +#include "wx/colour.h" +#include "wx/font.h" +wxColour wxSystemSettings::GetSystemColour(int WXUNUSED(index)) +{ + // FIXME_MGL + return wxColour(255,255,0); +} + +wxFont wxSystemSettings::GetSystemFont(int WXUNUSED(index)) +{ + // FIXME_MGL + return wxFont(12, wxMODERN, wxNORMAL, wxNORMAL); +} + +int wxSystemSettings::GetSystemMetric(int WXUNUSED(index)) +{ + // FIXME_MGL + return 1; +} diff --git a/src/mgl/utils.cpp b/src/mgl/utils.cpp index 7ad8f8af4f..5e5409772d 100644 --- a/src/mgl/utils.cpp +++ b/src/mgl/utils.cpp @@ -47,16 +47,23 @@ void wxDisplaySize(int *width, int *height) if (height) *height = g_displayDC->sizey(); } -void wxGetMousePosition(int* x, int* y) +void wxDisplaySizeMM(int *width, int *height) { - MS_getPos(x, y); + wxASSERT_MSG( g_displayDC, wxT("MGL display DC not created yet.") ); + if (width) *width = g_displayDC->sizex() * 25/72; + if (height) *height = g_displayDC->sizey() * 25/72; + // FIXME_MGL -- what about returning *real* monitor dimensions? } -wxPoint wxGetMousePosition() +void wxClientDisplayRect(int *x, int *y, int *width, int *height) { - wxPoint pt; - wxGetMousePosition(&pt.x, &pt.y); - return pt; + // This is supposed to return desktop dimensions minus any window + // manager panels, menus, taskbars, etc. If there is a way to do that + // for this platform please fix this function, otherwise it defaults + // to the entire desktop. + if (x) *x = 0; + if (y) *y = 0; + wxDisplaySize(width, height); } bool wxColourDisplay() @@ -85,6 +92,20 @@ int wxGetOsVersion(int *majorVsn, int *minorVsn) } +void wxGetMousePosition(int* x, int* y) +{ + MS_getPos(x, y); +} + +wxPoint wxGetMousePosition() +{ + wxPoint pt; + wxGetMousePosition(&pt.x, &pt.y); + return pt; +} + + + #ifdef __UNIX__ int wxAddProcessCallback(wxEndProcessData *proc_data, int fd) diff --git a/src/mgl/window.cpp b/src/mgl/window.cpp index 2b65c36f0d..1ac85be6fa 100644 --- a/src/mgl/window.cpp +++ b/src/mgl/window.cpp @@ -65,8 +65,11 @@ MGLDevCtx *g_displayDC = NULL; extern wxList WXDLLEXPORT wxPendingDelete; // FIXME_MGL -- ??? - -static wxWindowMGL *g_focusedWindow; + +// the window that has keyboard+joystick focus: +static wxWindowMGL *g_focusedWindow = NULL; +// the window that is currently under mouse cursor: +static wxWindowMGL *g_windowUnderMouse = NULL; // --------------------------------------------------------------------------- // constants @@ -85,8 +88,6 @@ enum // private functions // --------------------------------------------------------------------------- -static void wxWindowPainter(window_t *wnd, MGLDC *dc); - // wxCreateMGL_WM creates MGL display DC and associates it with winmng_t // structure. Dimensions and depth of the DC are fetched from wxSystemOptions // object. @@ -137,15 +138,31 @@ bool wxCreateMGL_WM() void wxDestroyMGL_WM() { - if (g_winMng) + if ( g_winMng ) { MGL_wmDestroy(g_winMng); g_winMng = NULL; } - delete g_displayDC; - g_displayDC = NULL; + if ( g_displayDC ) + { + delete g_displayDC; + g_displayDC = NULL; + } } +// --------------------------------------------------------------------------- +// MGL_WM hooks: +// --------------------------------------------------------------------------- + +static void wxWindowPainter(window_t *wnd, MGLDC *dc) +{ + wxWindowMGL *w = (wxWindow*) wnd->userData; + if (w) + { + MGLDevCtx ctx(dc); + w->HandlePaint(&ctx); + } +} // --------------------------------------------------------------------------- // event tables @@ -156,8 +173,6 @@ void wxDestroyMGL_WM() IMPLEMENT_ABSTRACT_CLASS(wxWindowMGL, wxWindowBase) BEGIN_EVENT_TABLE(wxWindowMGL, wxWindowBase) - EVT_ERASE_BACKGROUND(wxWindowMGL::OnEraseBackground) - EVT_SET_FOCUS(wxWindowMGL::OnSetFocus) END_EVENT_TABLE() // =========================================================================== @@ -191,7 +206,8 @@ wxWindowMGL::~wxWindowMGL() m_isBeingDeleted = TRUE; if ( g_focusedWindow == this ) - g_focusedWindow = NULL; + KillFocus(); + #if 0 // -- fixme - do we need this? // VS: make sure there's no wxFrame with last focus set to us: for (wxWindow *win = GetParent(); win; win = win->GetParent()) @@ -226,12 +242,16 @@ bool wxWindowMGL::Create(wxWindow *parent, long style, const wxString& name) { - wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") ); + // FIXME_MGL -- temporary! + //wxCHECK_MSG( parent, FALSE, wxT("can't create wxWindow without parent") ); if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) ) return FALSE; - parent->AddChild(this); + if ( parent ) // FIXME_MGL temporary + parent->AddChild(this); + else + m_isShown=FALSE;// FIXME_MGL -- temporary, simulates wxTLW/wxFrame if ( style & wxPOPUP_WINDOW ) { @@ -260,10 +280,6 @@ void wxWindowMGL::SetFocus() MGL_wmCaptureEvents(GetHandle(), EVT_KEYEVT | EVT_JOYEVT, wxMGL_CAPTURE_KEYB); - wxPanel *panel = wxDynamicCast(GetParent(), wxPanel); - if (panel) - panel->SetLastFocus((wxWindow*)this); - #if wxUSE_CARET // caret needs to be informed about focus change wxCaret *caret = GetCaret(); @@ -288,16 +304,18 @@ void wxWindowMGL::KillFocus() if ( g_focusedWindow != this ) return; g_focusedWindow = NULL; + if ( m_isBeingDeleted ) return; + MGL_wmUncaptureEvents(GetHandle(), wxMGL_CAPTURE_KEYB); #if wxUSE_CARET // caret needs to be informed about focus change wxCaret *caret = GetCaret(); - if (caret) + if ( caret ) caret->OnKillFocus(); #endif // wxUSE_CARET - if (IsTopLevel()) + if ( IsTopLevel() ) { wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId()); event.SetEventObject(this); @@ -657,35 +675,6 @@ void wxWindowMGL::GetCaretPos(int *x, int *y) const #endif // wxUSE_CARET -// --------------------------------------------------------------------------- -// activation/focus -// --------------------------------------------------------------------------- - -void wxWindowMGL::OnSetFocus(wxFocusEvent& event) -{ - // panel wants to track the window which was the last to have focus in it, - // so we want to set ourselves as the window which last had focus - // - // notice that it's also important to do it upwards the tree becaus - // otherwise when the top level panel gets focus, it won't set it back to - // us, but to some other sibling - wxWindow *win = (wxWindow *)this; - while ( win ) - { - wxWindow *parent = win->GetParent(); - wxPanel *panel = wxDynamicCast(parent, wxPanel); - if ( panel ) - { - panel->SetLastFocus(win); - } - - win = parent; - } - - event.Skip(); -} - - // --------------------------------------------------------------------------- // painting // --------------------------------------------------------------------------- @@ -731,16 +720,6 @@ void wxWindowMGL::Thaw() Refresh(); } -static void wxWindowPainter(window_t *wnd, MGLDC *dc) -{ - wxWindow *w = (wxWindow*) wnd->userData; - if (w) - { - MGLDevCtx ctx(dc); - w->HandlePaint(&ctx); - } -} - void wxWindowMGL::HandlePaint(MGLDevCtx *dc) { if ( m_frozen ) @@ -749,14 +728,17 @@ void wxWindowMGL::HandlePaint(MGLDevCtx *dc) return; } - region_t *clip = NULL; - MGL_getClipRegionDC(*dc, clip); - m_updateRegion = wxRegion(MGLRegion(clip)); + region_t clip; + MGL_getClipRegionDC(*dc, &clip); + m_updateRegion = wxRegion(MGLRegion(&clip)); m_paintMGLDC = dc; - wxEraseEvent eventEr(m_windowId, NULL); + { + wxWindowDC dc((wxWindow*)this); + wxEraseEvent eventEr(m_windowId, &dc); eventEr.SetEventObject(this); GetEventHandler()->ProcessEvent(eventEr); + } wxNcPaintEvent eventNc(GetId()); eventNc.SetEventObject(this); @@ -765,11 +747,8 @@ void wxWindowMGL::HandlePaint(MGLDevCtx *dc) wxPaintEvent eventPt(GetId()); eventPt.SetEventObject(this); GetEventHandler()->ProcessEvent(eventPt); -} -void wxWindowMGL::OnEraseBackground(wxEraseEvent& event) -{ - Clear(); + m_paintMGLDC = NULL; } -- 2.47.2