From bafcf2de38d0ade9aab3f8e38ac8b22072f9e005 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 7 Jun 2017 17:52:28 +0100 Subject: [PATCH] GraphicsWinQt toggles fullscreen natively. This also improves handling when starting full-screen, and keeps the window and internal state in sync. --- src/Viewer/GraphicsWindowQt5.cpp | 75 ++++++++-- src/Viewer/GraphicsWindowQt5.hxx | 16 ++ src/Viewer/WindowBuilder.cxx | 244 ++++++++++++++++++++----------- src/Viewer/WindowBuilder.hxx | 11 +- src/Viewer/fg_os_osgviewer.cxx | 59 +++++--- 5 files changed, 284 insertions(+), 121 deletions(-) diff --git a/src/Viewer/GraphicsWindowQt5.cpp b/src/Viewer/GraphicsWindowQt5.cpp index ede5c8d4f..eaadf30b7 100644 --- a/src/Viewer/GraphicsWindowQt5.cpp +++ b/src/Viewer/GraphicsWindowQt5.cpp @@ -29,6 +29,8 @@ #include #include +#include
+ using namespace flightgear; class QtKeyboardMap @@ -155,8 +157,6 @@ void GLWindow::syncGeometryWithOSG() _gw->getEventQueue()->windowResize( x(), y(), scaled_width, scaled_height ); _gw->requestRedraw(); _gw->_updateContextNeeded = true; - - _gw->getEventQueue()->syncWindowRectangleWithGraphicsContext(); } } @@ -190,6 +190,15 @@ void GLWindow::processDeferredEvents() bool GLWindow::event( QEvent* event ) { + if (event->type() == QEvent::WindowStateChange) { + // keep full-screen state in sync + const bool isFullscreen = (windowState() == Qt::WindowFullScreen); + + if (_isPrimaryWindow) { + fgSetBool("/sim/startup/fullscreen", isFullscreen); + } + } + // Reparenting GLWidget may create a new underlying window and a new GL context. // Qt will then call doneCurrent on the GL context about to be deleted. The thread // where old GL context was current has no longer current context to render to and @@ -225,6 +234,11 @@ bool GLWindow::event( QEvent* event ) v->frame(); } } + else if (event->type() == QEvent::Close) { + // spin an 'are you sure'? dialog here + // need to decide immediately unfortunately. + _gw->getEventQueue()->closeWindow(); + } // perform regular event handling return QWindow::event( event ); @@ -368,15 +382,20 @@ bool GraphicsWindowQt5::init( Qt::WindowFlags f ) if ( !_window ) _window = windowData ? windowData->_window : nullptr; - // create widget if it does not exist + // create window if it does not exist _ownsWidget = (_window == NULL); if ( !_window ) { // WindowFlags Qt::WindowFlags flags = f | Qt::Window | Qt::CustomizeWindowHint; - if ( _traits->windowDecoration ) + if ( _traits->windowDecoration ) { flags |= Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint; - + flags |= Qt::WindowFullscreenButtonHint; + + // TODO - check if this is desirable or not on Windows+Linux + //flags |= Qt::MaximizeUsingFullscreenGeometryHint; + } + // create widget _window = new GLWindow(); _window->setFlags(flags); @@ -398,8 +417,13 @@ bool GraphicsWindowQt5::init( Qt::WindowFlags f ) } else { _window->resize( sz ); } + + if (windowData->createFullscreen) { + _window->setWindowState(Qt::WindowFullScreen); + } } + _window->_isPrimaryWindow = windowData->isPrimaryWindow; _window->setGraphicsWindow( this ); useCursor( _traits->useCursor ); @@ -619,15 +643,18 @@ bool GraphicsWindowQt5::valid() const bool GraphicsWindowQt5::realizeImplementation() { - _window->show(); - - // initialize GL context for the widget - // defer this to makeCurrent which happens on the rendering thread + WindowData* windowData = _traits.get() ? dynamic_cast(_traits->inheritedWindowData.get()) : nullptr; + if (windowData->createFullscreen) { + _window->showFullScreen(); + // work-around for resize events being discarded by EventQueue::setStartTick + _sendResizeOnEventCheck = true; + } else { + _window->show(); + } + + getEventQueue()->syncWindowRectangleWithGraphicsContext(); _realized = true; - - // make sure the event queue has the correct window rectangle size and input range - getEventQueue()->syncWindowRectangleWithGraphicsContext(); return true; } @@ -720,6 +747,12 @@ bool GraphicsWindowQt5::checkEvents() if (_window->getNumDeferredEvents() > 0) _window->processDeferredEvents(); + if (_sendResizeOnEventCheck) { + _sendResizeOnEventCheck = false; + _window->syncGeometryWithOSG(); + + } + // todo - only if not running inside QApplication::exec; can we check this? QCoreApplication::processEvents(QEventLoop::AllEvents); @@ -750,6 +783,17 @@ void GraphicsWindowQt5::requestContinuousUpdate(bool needed) GraphicsWindow::requestContinuousUpdate(needed); } +void GraphicsWindowQt5::setFullscreen(bool isFullscreen) +{ + if (isFullscreen) { + _window->showFullScreen(); + } else { + // FIXME should restore previous state? + _window->showNormal(); + } +} + + class Qt5WindowingSystem : public osg::GraphicsContext::WindowingSystemInterface { public: @@ -757,6 +801,7 @@ public: Qt5WindowingSystem() { OSG_INFO << "QtWindowingSystemInterface()" << std::endl; + } ~Qt5WindowingSystem() @@ -788,7 +833,7 @@ public: { QScreen* screen = qScreenFromSI(si); if (!screen) { - qWarning() << Q_FUNC_INFO << "no screen for identifier"; + qWarning() << Q_FUNC_INFO << "no screen for identifier" << QString::fromStdString(si.displayName()); return; } @@ -811,7 +856,7 @@ public: { QScreen* screen = qScreenFromSI(si); if (!screen) { - qWarning() << Q_FUNC_INFO << "no screen for identifier"; + qWarning() << Q_FUNC_INFO << "no screen for identifier" << QString::fromStdString(si.displayName()); return; } @@ -852,7 +897,7 @@ private: if (screens.size() < si.screenNum) return screens.at(si.screenNum); - return 0; // or should we return the primary screen? + return QGuiApplication::primaryScreen(); } // No implementation for these diff --git a/src/Viewer/GraphicsWindowQt5.hxx b/src/Viewer/GraphicsWindowQt5.hxx index ce47064b5..1b02d622b 100644 --- a/src/Viewer/GraphicsWindowQt5.hxx +++ b/src/Viewer/GraphicsWindowQt5.hxx @@ -113,6 +113,9 @@ protected: bool _forwardKeyEvents = false; qreal _devicePixelRatio; + + // is this the primary (GUI) window + bool _isPrimaryWindow = false; virtual void resizeEvent( QResizeEvent* event ); virtual void moveEvent( QMoveEvent* event ); @@ -132,6 +135,12 @@ public: { WindowData( GLWindow* win = NULL ): _window(win) {} GLWindow* _window; + + bool createFullscreen = false; + + // is this the main window, corresponding to the /sim/startup + // properties? If so we will drive them in some cases. + bool isPrimaryWindow = false; }; bool init( Qt::WindowFlags f ); @@ -178,6 +187,8 @@ public: void setViewer( osgViewer::ViewerBase *viewer ); virtual void contextInitalised() { ; } + + void setFullscreen(bool isFullscreen); protected: virtual void viewerChanged(osgViewer::ViewerBase*); @@ -190,6 +201,11 @@ protected: bool _realized; bool _updateContextNeeded; osg::observer_ptr< osgViewer::ViewerBase > _viewer; + + // if true, we will generate a resize event on the next + // call to check events. Ths works around OSG clearing the + // event queue on us. + bool _sendResizeOnEventCheck = false; }; } // of namespace flightgear diff --git a/src/Viewer/WindowBuilder.cxx b/src/Viewer/WindowBuilder.cxx index cc57bd911..42ac30ac3 100644 --- a/src/Viewer/WindowBuilder.cxx +++ b/src/Viewer/WindowBuilder.cxx @@ -29,6 +29,11 @@ #include #endif +#if defined(HAVE_QT) + #include "GraphicsWindowQt5.hxx" +#endif + + using namespace std; using namespace osg; @@ -56,16 +61,19 @@ void WindowBuilder::initWindowBuilder(bool stencil) WindowBuilder::WindowBuilder(bool stencil) : defaultCounter(0) { - defaultTraits = makeDefaultTraits(stencil); +#if defined (HAVE_QT) + usingQtGraphicsWindow = fgGetBool("/sim/rendering/graphics-window-qt", false); +#endif + makeDefaultTraits(stencil); } -GraphicsContext::Traits* -WindowBuilder::makeDefaultTraits(bool stencil) +void WindowBuilder::makeDefaultTraits(bool stencil) { GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); - GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits; - + defaultTraits = new osg::GraphicsContext::Traits; + auto traits = defaultTraits.get(); + traits->readDISPLAY(); if (traits->displayNum < 0) traits->displayNum = 0; @@ -81,10 +89,6 @@ WindowBuilder::makeDefaultTraits(bool stencil) if (stencil) traits->stencil = 8; - unsigned screenwidth = 0; - unsigned screenheight = 0; - wsi->getScreenResolution(*traits, screenwidth, screenheight); - traits->doubleBuffer = true; traits->mipMapGeneration = true; traits->windowName = "FlightGear"; @@ -92,31 +96,59 @@ WindowBuilder::makeDefaultTraits(bool stencil) traits->sampleBuffers = fgGetInt("/sim/rendering/multi-sample-buffers", traits->sampleBuffers); traits->samples = fgGetInt("/sim/rendering/multi-samples", traits->samples); traits->vsync = fgGetBool("/sim/rendering/vsync-enable", traits->vsync); - traits->windowDecoration = !fgGetBool("/sim/startup/fullscreen"); - - if (!traits->windowDecoration) { - // fullscreen - traits->supportsResize = false; - traits->width = screenwidth; - traits->height = screenheight; - SG_LOG(SG_VIEW,SG_DEBUG,"Using full screen size for window: " << screenwidth << " x " << screenheight); - } else { - // window - int w = fgGetInt("/sim/startup/xsize"); - int h = fgGetInt("/sim/startup/ysize"); + + const bool wantFullscreen = fgGetBool("/sim/startup/fullscreen"); + if (usingQtGraphicsWindow) { +#if defined(HAVE_QT) + // fullscreen is handled by Qt natively + // we will check and set fullscreen mode when building + // the window instance + auto data = new GraphicsWindowQt5::WindowData; + data->createFullscreen = wantFullscreen; + data->isPrimaryWindow = true; + + traits->inheritedWindowData = data; + traits->windowDecoration = true; traits->supportsResize = true; - traits->width = w; - traits->height = h; - if ((w>0)&&(h>0)) - { - traits->x = ((unsigned)w>screenwidth) ? 0 : (screenwidth-w)/3; - traits->y = ((unsigned)h>screenheight) ? 0 : (screenheight-h)/3; + traits->width = fgGetInt("/sim/startup/xsize"); + traits->height = fgGetInt("/sim/startup/ysize"); + traits->x = 50; + traits->y = 50; +#else + SG_LOG(SG_VIEW,SG_ALERT,"requested Qt GraphicsWindow in non-Qt build"); +#endif + } else { + unsigned screenwidth = 0; + unsigned screenheight = 0; + // this is a deprecated method, should be screen-aware. + wsi->getScreenResolution(*traits, screenwidth, screenheight); + + // handle fullscreen manually + traits->windowDecoration = !wantFullscreen; + if (!traits->windowDecoration) { + // fullscreen + traits->supportsResize = false; + traits->width = screenwidth; + traits->height = screenheight; + SG_LOG(SG_VIEW,SG_DEBUG,"Using full screen size for window: " << screenwidth << " x " << screenheight); + } else { + // window + int w = fgGetInt("/sim/startup/xsize"); + int h = fgGetInt("/sim/startup/ysize"); + traits->supportsResize = true; + traits->width = w; + traits->height = h; + if ((w>0)&&(h>0)) + { + traits->x = ((unsigned)w>screenwidth) ? 0 : (screenwidth-w)/3; + traits->y = ((unsigned)h>screenheight) ? 0 : (screenheight-h)/3; + } + SG_LOG(SG_VIEW,SG_DEBUG,"Using initial window size: " << w << " x " << h); } - SG_LOG(SG_VIEW,SG_DEBUG,"Using initial window size: " << w << " x " << h); } - return traits; -} } + +} // of namespace flightgear namespace { @@ -159,10 +191,93 @@ inline int setFromProperty(bool& place, const SGPropertyNode* node, namespace flightgear { + +void WindowBuilder::setFullscreenTraits(const SGPropertyNode* winNode, GraphicsContext::Traits* traits) +{ + const SGPropertyNode* orrNode = winNode->getNode("overrideRedirect"); + bool overrideRedirect = orrNode && orrNode->getBoolValue(); + traits->overrideRedirect = overrideRedirect; + +#if defined(HAVE_QT) + if (usingQtGraphicsWindow) { + auto data = new GraphicsWindowQt5::WindowData; + data->createFullscreen = true; + traits->inheritedWindowData = data; + traits->windowDecoration = winNode->getBoolValue("decoration"); + } else +#endif + // this codepath is mandatory on non-Qt builds + { + traits->windowDecoration = false; + + unsigned int width = 0; + unsigned int height = 0; + auto wsi = osg::GraphicsContext::getWindowingSystemInterface(); + wsi->getScreenResolution(*traits, width, height); + traits->width = width; + traits->height = height; + traits->supportsResize = false; + traits->x = 0; + traits->y = 0; + } +} + +bool WindowBuilder::setWindowedTraits(const SGPropertyNode* winNode, GraphicsContext::Traits* traits) +{ + bool customTraits = false; +#if defined(HAVE_QT) + if (usingQtGraphicsWindow) { + if (winNode->hasValue("fullscreen")) { + auto data = new GraphicsWindowQt5::WindowData; + data->createFullscreen = false; + traits->inheritedWindowData = data; + customTraits = true; + } + customTraits |= setFromProperty(traits->windowDecoration, winNode, "decoration"); + customTraits |= setFromProperty(traits->width, winNode, "width"); + customTraits |= setFromProperty(traits->height, winNode, "height"); + } else +#endif + { + int resizable = 0; + const SGPropertyNode* fullscreenNode = winNode->getNode("fullscreen"); + if (fullscreenNode && !fullscreenNode->getBoolValue()) + { + traits->windowDecoration = true; + resizable = 1; + } + resizable |= setFromProperty(traits->windowDecoration, winNode, "decoration"); + resizable |= setFromProperty(traits->width, winNode, "width"); + resizable |= setFromProperty(traits->height, winNode, "height"); + if (resizable) { + traits->supportsResize = true; + customTraits = true; + } + } + + return customTraits; +} + +void WindowBuilder::setMacPoseAsStandaloneApp(GraphicsContext::Traits* traits) +{ +#if defined(SG_MAC) + if (!usingQtGraphicsWindow) { + // this logic is unecessary if using a Qt window, since everything + // plays together nicely + int flags = osgViewer::GraphicsWindowCocoa::WindowData::CheckForEvents; + + // avoid both QApplication and OSG::CocoaViewer doing single-application + // init (Apple menu, making front process, etc) + if (poseAsStandaloneApp) { + flags |= osgViewer::GraphicsWindowCocoa::WindowData::PoseAsStandaloneApp; + } + traits->inheritedWindowData = new osgViewer::GraphicsWindowCocoa::WindowData(flags); + } +#endif +} + GraphicsWindow* WindowBuilder::buildWindow(const SGPropertyNode* winNode) { - GraphicsContext::WindowingSystemInterface* wsi - = osg::GraphicsContext::getWindowingSystemInterface(); WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA(); string windowName; if (winNode->hasChild("window-name")) @@ -171,49 +286,22 @@ GraphicsWindow* WindowBuilder::buildWindow(const SGPropertyNode* winNode) windowName = winNode->getStringValue("name"); GraphicsWindow* result = 0; if (!windowName.empty()) { + // look for an existing window and return that result = wsa->findWindow(windowName); if (result) return result; } - GraphicsContext::Traits* traits - = new GraphicsContext::Traits(*defaultTraits); + auto traits = new GraphicsContext::Traits(*defaultTraits); int traitsSet = setFromProperty(traits->hostName, winNode, "host-name"); traitsSet |= setFromProperty(traits->displayNum, winNode, "display"); traitsSet |= setFromProperty(traits->screenNum, winNode, "screen"); const SGPropertyNode* fullscreenNode = winNode->getNode("fullscreen"); - const SGPropertyNode* orrNode = winNode->getNode("overrideRedirect"); - if (fullscreenNode && fullscreenNode->getBoolValue()) { - // fullscreen mode - unsigned width = 0; - unsigned height = 0; - wsi->getScreenResolution(*traits, width, height); - traits->windowDecoration = false; - traits->width = width; - traits->height = height; - traits->supportsResize = false; - bool overrideRedirect = orrNode && orrNode->getBoolValue(); - traits->overrideRedirect = overrideRedirect; - traits->x = 0; - traits->y = 0; + setFullscreenTraits(winNode, traits); traitsSet = 1; } else { - int resizable = 0; - if (fullscreenNode && !fullscreenNode->getBoolValue()) - { - traits->windowDecoration = true; - resizable = 1; - } - resizable |= setFromProperty(traits->windowDecoration, winNode, - "decoration"); - resizable |= setFromProperty(traits->width, winNode, "width"); - resizable |= setFromProperty(traits->height, winNode, "height"); - if (resizable) { - traits->supportsResize = true; - traitsSet = 1; - } - // Otherwise use default values. + traitsSet |= setWindowedTraits(winNode, traits); } traitsSet |= setFromProperty(traits->x, winNode, "x"); traitsSet |= setFromProperty(traits->y, winNode, "y"); @@ -224,20 +312,19 @@ GraphicsWindow* WindowBuilder::buildWindow(const SGPropertyNode* winNode) traits->windowName = makeName("FlightGear", defaultCounter++); } -#if defined(SG_MAC) - int flags = osgViewer::GraphicsWindowCocoa::WindowData::CheckForEvents; + setMacPoseAsStandaloneApp(traits); - // avoid both QApplication and OSG::CocoaViewer doing single-application - // init (Apple menu, making front process, etc) - if (poseAsStandaloneApp) { - flags |= osgViewer::GraphicsWindowCocoa::WindowData::PoseAsStandaloneApp; - } - traits->inheritedWindowData = new osgViewer::GraphicsWindowCocoa::WindowData(flags); -#endif - bool drawGUI = false; traitsSet |= setFromProperty(drawGUI, winNode, "gui"); if (traitsSet) { +#if defined (HAVE_QT) + if (usingQtGraphicsWindow) { + // this assumes the user only sets the 'gui' flag on one window, not ideal + auto data = static_cast(traits->inheritedWindowData.get()); + data->isPrimaryWindow = drawGUI; + } +#endif + GraphicsContext* gc = GraphicsContext::createGraphicsContext(traits); if (gc) { GraphicsWindow* window = WindowSystemAdapter::getWSA() @@ -265,16 +352,7 @@ GraphicsWindow* WindowBuilder::getDefaultWindow() = new GraphicsContext::Traits(*defaultTraits); traits->windowName = "FlightGear"; -#if defined(SG_MAC) - int flags = osgViewer::GraphicsWindowCocoa::WindowData::CheckForEvents; - - // avoid both QApplication and OSG::CocoaViewer doing single-application - // init (Apple menu, making front process, etc) - if (poseAsStandaloneApp) { - flags |= osgViewer::GraphicsWindowCocoa::WindowData::PoseAsStandaloneApp; - } - traits->inheritedWindowData = new osgViewer::GraphicsWindowCocoa::WindowData(flags); -#endif + setMacPoseAsStandaloneApp(traits); GraphicsContext* gc = GraphicsContext::createGraphicsContext(traits); if (gc) { diff --git a/src/Viewer/WindowBuilder.hxx b/src/Viewer/WindowBuilder.hxx index 8836d6956..4790aa086 100644 --- a/src/Viewer/WindowBuilder.hxx +++ b/src/Viewer/WindowBuilder.hxx @@ -61,9 +61,18 @@ public: static void setPoseAsStandaloneApp(bool b); protected: WindowBuilder(bool stencil); - static osg::GraphicsContext::Traits* makeDefaultTraits(bool stencil); + + void setFullscreenTraits(const SGPropertyNode* winNode, osg::GraphicsContext::Traits* traits); + bool setWindowedTraits(const SGPropertyNode* winNode, osg::GraphicsContext::Traits* traits); + + void setMacPoseAsStandaloneApp(osg::GraphicsContext::Traits* traits); + + void makeDefaultTraits(bool stencil); + osg::ref_ptr defaultTraits; int defaultCounter; + bool usingQtGraphicsWindow = false; + static osg::ref_ptr windowBuilder; static const std::string defaultWindowName; static bool poseAsStandaloneApp; diff --git a/src/Viewer/fg_os_osgviewer.cxx b/src/Viewer/fg_os_osgviewer.cxx index 355a3fd08..4717e6075 100644 --- a/src/Viewer/fg_os_osgviewer.cxx +++ b/src/Viewer/fg_os_osgviewer.cxx @@ -2,7 +2,7 @@ // implemented as an osgViewer // // Copyright (C) 2007 Tim Moore timoore@redhat.com -// Copyright (C) 2007 Mathias Froehlich +// Copyright (C) 2007 Mathias Froehlich // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -61,6 +61,7 @@ #if defined(HAVE_QT) #include "GraphicsWindowQt5.hxx" +#include #include #endif @@ -100,12 +101,14 @@ USE_OSGPLUGIN(txf); // fg_os implementation // -using namespace std; +using namespace std; using namespace flightgear; using namespace osg; osg::ref_ptr viewer; +bool global_usingGraphicsWindowQt = false; + static void setStereoMode( const char * mode ) { DisplaySettings::StereoMode stereoMode = DisplaySettings::QUAD_BUFFER; @@ -147,7 +150,7 @@ static void setStereoMode( const char * mode ) { stereoMode = DisplaySettings::CHECKERBOARD; } else { - stereoOn = false; + stereoOn = false; } DisplaySettings::instance()->setStereo( stereoOn ); DisplaySettings::instance()->setStereoMode( stereoMode ); @@ -176,7 +179,7 @@ static const char * getStereoMode() return "VERTICAL_INTERLACE"; } else if( stereoMode == DisplaySettings::CHECKERBOARD ) { return "CHECKERBOARD"; - } + } return "OFF"; } @@ -229,7 +232,7 @@ public: { osg::NotifySeverity severity = osg::WARN; string val = boost::to_lower_copy(string(node->getStringValue())); - + if (val == "fatal") { severity = osg::FATAL; } else if (val == "warn") { @@ -241,7 +244,7 @@ public: } else if ((val == "debug") || (val == "debug-info")) { severity = osg::DEBUG_INFO; } - + osg::setNotifyLevel(severity); } }; @@ -253,7 +256,7 @@ void updateOSGNotifyLevel() void fgOSOpenWindow(bool stencil) { osg::setNotifyHandler(new NotifyLogger); - + viewer = new osgViewer::Viewer; viewer->setDatabasePager(FGScenery::getPagerSingleton()); @@ -271,7 +274,7 @@ void fgOSOpenWindow(bool stencil) viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded); WindowBuilder::initWindowBuilder(stencil); CameraGroup::buildDefaultGroup(viewer.get()); - + FGEventHandler* manipulator = globals->get_renderer()->getEventHandler(); WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA(); if (wsa->windows.size() != 1) { @@ -292,14 +295,14 @@ void fgOSResetProperties() NotifyLevelListener* l = new NotifyLevelListener; globals->addListenerToCleanup(l); osgLevel->addChangeListener(l, true); - + osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault()); if (guiCamera) { Viewport* guiViewport = guiCamera->getViewport(); fgSetInt("/sim/startup/xsize", guiViewport->width()); fgSetInt("/sim/startup/ysize", guiViewport->height()); } - + DisplaySettings * displaySettings = DisplaySettings::instance(); fgTie("/sim/rendering/osg-displaysettings/eye-separation", displaySettings, &DisplaySettings::getEyeSeparation, &DisplaySettings::setEyeSeparation ); fgTie("/sim/rendering/osg-displaysettings/screen-distance", displaySettings, &DisplaySettings::getScreenDistance, &DisplaySettings::setScreenDistance ); @@ -319,7 +322,7 @@ void fgOSExit(int code) viewer->setDone(true); viewer->getDatabasePager()->cancel(); status = code; - + // otherwise we crash if OSG does logging during static destruction, eg // GraphicsWindowX11, since OSG statics may have been created before the // sglog static, despite our best efforts in boostrap.cxx @@ -329,20 +332,19 @@ void fgOSExit(int code) int fgOSMainLoop() { viewer->setReleaseContextAtEndOfFrameHint(false); - if (!viewer->isRealized()) + if (!viewer->isRealized()) { viewer->realize(); + } + while (!viewer->done()) { fgIdleHandler idleFunc = globals->get_renderer()->getEventHandler()->getIdleHandler(); if (idleFunc) (*idleFunc)(); -#if defined(HAVE_QT) - QCoreApplication::processEvents(QEventLoop::AllEvents); -#endif globals->get_renderer()->update(); viewer->frame( globals->get_sim_time_sec() ); } - + return status; } @@ -352,7 +354,7 @@ int fgGetKeyModifiers() if (!r || !r->getEventHandler()) { // happens during shutdown return 0; } - + return r->getEventHandler()->getCurrentModifiers(); } @@ -364,7 +366,9 @@ void fgWarpMouse(int x, int y) void fgOSInit(int* argc, char** argv) { #if defined(HAVE_QT) - if (fgGetBool("/sim/rendering/graphics-window-qt", false)) { + global_usingGraphicsWindowQt = fgGetBool("/sim/rendering/graphics-window-qt", false); + if (global_usingGraphicsWindowQt) { + flightgear::initApp(*argc, argv); SG_LOG(SG_GL, SG_INFO, "Using Qt implementation of GraphicsWindow"); flightgear::initQtWindowingSystem(); } else { @@ -403,9 +407,20 @@ void fgOSFullScreen() * The other windows should use fixed setup from the camera.xml file anyway. */ osgViewer::GraphicsWindow* window = windows[0]; +#if defined(HAVE_QT) + if (global_usingGraphicsWindowQt) { + const bool wasFullscreen = fgGetBool("/sim/startup/fullscreen"); + auto qtWin = static_cast(window); + qtWin->setFullscreen(!wasFullscreen); + fgSetBool("/sim/startup/fullscreen", !wasFullscreen); + + // FIXME tell lies here for HiDPI sizing? + fgSetInt("/sim/startup/xsize", qtWin->getGLWindow()->width()); + fgSetInt("/sim/startup/ysize", qtWin->getGLWindow()->height()); + } else +#endif { osg::GraphicsContext::WindowingSystemInterface *wsi = osg::GraphicsContext::getWindowingSystemInterface(); - if (wsi == NULL) { SG_LOG(SG_VIEW, SG_ALERT, "ERROR: No WindowSystemInterface available. Cannot toggle window fullscreen."); @@ -476,7 +491,7 @@ void fgOSFullScreen() window->setWindowDecoration(isFullScreen); window->setWindowRectangle(x, y, width, height); window->grabFocusIfPointerInWindow(); - } + } // of stock GraphicsWindow verison (OSG has no native fullscreen mode) } static void setMouseCursor(osgViewer::GraphicsWindow* gw, int cursor) @@ -484,7 +499,7 @@ static void setMouseCursor(osgViewer::GraphicsWindow* gw, int cursor) if (!gw) { return; } - + osgViewer::GraphicsWindow::MouseCursor mouseCursor; mouseCursor = osgViewer::GraphicsWindow::InheritCursor; if (cursor == MOUSE_CURSOR_NONE) @@ -529,7 +544,7 @@ void fgSetMouseCursor(int cursor) _cursor = cursor; if (!viewer) return; - + std::vector windows; viewer->getWindows(windows); BOOST_FOREACH(osgViewer::GraphicsWindow* gw, windows) {