diff --git a/include/osgViewer/GraphicsWindow b/include/osgViewer/GraphicsWindow index 0aaa9c310..a2a60e672 100644 --- a/include/osgViewer/GraphicsWindow +++ b/include/osgViewer/GraphicsWindow @@ -30,6 +30,9 @@ extern "C" namespace osgViewer { +class View; + + /** Base class for providing Windowing API agnostic access to creating and managing graphics window and events. * Note, the GraphicsWindow is subclassed from osg::GraphicsContext, and to provide an implemention you'll need to implement its * range of pure virtual functions, you'll find these all have naming convention methodNameImplemention(..). @@ -180,8 +183,13 @@ class OSGVIEWER_EXPORT GraphicsWindow : public osg::GraphicsContext, public osgG public: + typedef std::list Views; + /** Returns the list of views (osgViewer::View) attached to this GraphicsWindow. + * Internally, the method walks through all the cameras and collects all the views attached to the cameras.*/ + void getViews(Views& views); + // Override from GUIActionAdapter - virtual void requestRedraw() {} + virtual void requestRedraw(); // Override from GUIActionAdapter virtual void requestContinuousUpdate(bool /*needed*/=true) {} diff --git a/include/osgViewer/ViewerBase b/include/osgViewer/ViewerBase index 8c3e15aff..488c64bf5 100644 --- a/include/osgViewer/ViewerBase +++ b/include/osgViewer/ViewerBase @@ -195,9 +195,6 @@ class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object osgUtil::IncrementalCompileOperation* getIncrementalCompileOperation() { return _incrementalCompileOperation.get(); } - /** Check to see if windows are still open, if not set viewer done to true. */ - void checkWindowStatus(); - enum FrameScheme { ON_DEMAND, @@ -253,6 +250,15 @@ class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object typedef std::vector Views; virtual void getViews(Views& views, bool onlyValid=true) = 0; + /** Check to see if any windows are still open. If not, set viewer done to true. */ + void checkWindowStatus(); + + /** Check to see if windows are still open using the list of contexts given as a parameter. + * If no windows are open, stop rendering threads and set viewer done to true. + * This function is more effective than checkWindowStatus() as it does not query + * the context list and should be used whenever context list is already available in your code.*/ + void checkWindowStatus(const Contexts& contexts); + virtual double elapsedTime() = 0; virtual osg::FrameStamp* getViewerFrameStamp() = 0; diff --git a/src/osgViewer/CMakeLists.txt b/src/osgViewer/CMakeLists.txt index 3218debf2..c455295e7 100644 --- a/src/osgViewer/CMakeLists.txt +++ b/src/osgViewer/CMakeLists.txt @@ -23,6 +23,7 @@ SET(TARGET_H SET(LIB_COMMON_FILES CompositeViewer.cpp + GraphicsWindow.cpp HelpHandler.cpp Renderer.cpp Scene.cpp diff --git a/src/osgViewer/CompositeViewer.cpp b/src/osgViewer/CompositeViewer.cpp index 7e08fdd37..1cfb4eeb4 100644 --- a/src/osgViewer/CompositeViewer.cpp +++ b/src/osgViewer/CompositeViewer.cpp @@ -688,6 +688,10 @@ void CompositeViewer::eventTraversal() Contexts contexts; getContexts(contexts); + // set done if there are no windows + checkWindowStatus(contexts); + if (_done) return; + Scenes scenes; getScenes(scenes); diff --git a/src/osgViewer/GraphicsWindow.cpp b/src/osgViewer/GraphicsWindow.cpp new file mode 100644 index 000000000..8aa4fea68 --- /dev/null +++ b/src/osgViewer/GraphicsWindow.cpp @@ -0,0 +1,60 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2011 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#include +#include +#include + +using namespace osgViewer; + + +void GraphicsWindow::getViews(Views& views) +{ + views.clear(); + osgViewer::View *prev = NULL; + + for(Cameras::iterator it = _cameras.begin(); + it != _cameras.end(); + it++) + { + osgViewer::View *v = dynamic_cast((*it)->getView()); + if (v) + // perform a simple test to reduce the number of duplicates + if (v != prev) + // append view + views.push_back(v); + } + + // remove duplicates + views.sort(); + views.unique(); +} + +void GraphicsWindow::requestRedraw() +{ + Views views; + getViews(views); + + if (views.empty()) + { + OSG_INFO << "GraphicsWindow::requestRedraw(): No views assigned yet." << std::endl; + return; + } + + for(Views::iterator it = views.begin(); + it != views.end(); + it++) + { + (*it)->requestRedraw(); + } +} diff --git a/src/osgViewer/GraphicsWindowWin32.cpp b/src/osgViewer/GraphicsWindowWin32.cpp index a3415e014..b31d38a18 100644 --- a/src/osgViewer/GraphicsWindowWin32.cpp +++ b/src/osgViewer/GraphicsWindowWin32.cpp @@ -1833,7 +1833,7 @@ bool GraphicsWindowWin32::realizeImplementation() } } protected: - HDC _hdc; + HDC _hdc; HGLRC _hglrc; } restoreContext; @@ -2355,6 +2355,7 @@ LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, W PAINTSTRUCT paint; ::BeginPaint(hwnd, &paint); ::EndPaint(hwnd, &paint); + requestRedraw(); } break; @@ -2467,10 +2468,15 @@ LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, W int windowWidth = (clientRect.right == 0) ? 1 : clientRect.right ; int windowHeight = (clientRect.bottom == 0) ? 1 : clientRect.bottom;; + // send resize event if window position or size was changed if (windowX!=_traits->x || windowY!=_traits->y || windowWidth!=_traits->width || windowHeight!=_traits->height) { resized(windowX, windowY, windowWidth, windowHeight); getEventQueue()->windowResize(windowX, windowY, windowWidth, windowHeight, resizeTime); + + // request redraw if window size was changed + if (windowWidth!=_traits->width || windowHeight!=_traits->height) + requestRedraw(); } } break; diff --git a/src/osgViewer/GraphicsWindowX11.cpp b/src/osgViewer/GraphicsWindowX11.cpp index 141f00324..b68508f8c 100644 --- a/src/osgViewer/GraphicsWindowX11.cpp +++ b/src/osgViewer/GraphicsWindowX11.cpp @@ -1090,25 +1090,6 @@ void GraphicsWindowX11::swapBuffersImplementation() #endif glXSwapBuffers( _display, _window ); #endif - - - while( XPending(_display) ) - { - XEvent ev; - XNextEvent( _display, &ev ); - - switch( ev.type ) - { - case ClientMessage: - { - if (static_cast(ev.xclient.data.l[0]) == _deleteWindow) - { - OSG_INFO<<"DeleteWindow event received"<closeWindow(); - } - } - } - } } void GraphicsWindowX11::checkEvents() @@ -1154,6 +1135,7 @@ void GraphicsWindowX11::checkEvents() } case Expose : OSG_INFO<<"Expose x="<closeWindow(); + } + } + } } #if 0 diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index 10b71e248..ed02a5476 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -617,6 +617,10 @@ void Viewer::eventTraversal() Contexts contexts; getContexts(contexts); + // set done if there are no windows + checkWindowStatus(contexts); + if (_done) return; + osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState(); osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix(); if (getCamera()->getViewport()) diff --git a/src/osgViewer/ViewerBase.cpp b/src/osgViewer/ViewerBase.cpp index b08585ab0..6371f9829 100644 --- a/src/osgViewer/ViewerBase.cpp +++ b/src/osgViewer/ViewerBase.cpp @@ -522,9 +522,11 @@ void ViewerBase::checkWindowStatus() { Contexts contexts; getContexts(contexts); + checkWindowStatus(contexts); +} - // OSG_NOTICE<<"Viewer::checkWindowStatus() - "<