Remove the custom graphics window impl
Probably not worth the compat hassle :)
This commit is contained in:
parent
c92c41a50f
commit
37272b14ac
2 changed files with 0 additions and 1091 deletions
|
@ -1,898 +0,0 @@
|
||||||
// Copyright (C) 2017 James Turner
|
|
||||||
// derived from OSG GraphicsWindowQt by Wang Rui
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU General Public License as
|
|
||||||
// published by the Free Software Foundation; either version 2 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program 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 GNU
|
|
||||||
// General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
|
|
||||||
#include <osg/DeleteHandler>
|
|
||||||
#include <osg/Version>
|
|
||||||
#include "GraphicsWindowQt5.hxx"
|
|
||||||
#include <osgViewer/ViewerBase>
|
|
||||||
#include <QInputEvent>
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
#include <QScreen>
|
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QAbstractEventDispatcher>
|
|
||||||
#include <QOpenGLContext>
|
|
||||||
#include <QSurfaceFormat>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include <Main/fg_props.hxx>
|
|
||||||
|
|
||||||
using namespace flightgear;
|
|
||||||
|
|
||||||
class QtKeyboardMap
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
QtKeyboardMap()
|
|
||||||
{
|
|
||||||
mKeyMap[Qt::Key_Escape ] = osgGA::GUIEventAdapter::KEY_Escape;
|
|
||||||
mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_Delete;
|
|
||||||
mKeyMap[Qt::Key_Home ] = osgGA::GUIEventAdapter::KEY_Home;
|
|
||||||
mKeyMap[Qt::Key_Enter ] = osgGA::GUIEventAdapter::KEY_KP_Enter;
|
|
||||||
mKeyMap[Qt::Key_End ] = osgGA::GUIEventAdapter::KEY_End;
|
|
||||||
mKeyMap[Qt::Key_Return ] = osgGA::GUIEventAdapter::KEY_Return;
|
|
||||||
mKeyMap[Qt::Key_PageUp ] = osgGA::GUIEventAdapter::KEY_Page_Up;
|
|
||||||
mKeyMap[Qt::Key_PageDown ] = osgGA::GUIEventAdapter::KEY_Page_Down;
|
|
||||||
mKeyMap[Qt::Key_Left ] = osgGA::GUIEventAdapter::KEY_Left;
|
|
||||||
mKeyMap[Qt::Key_Right ] = osgGA::GUIEventAdapter::KEY_Right;
|
|
||||||
mKeyMap[Qt::Key_Up ] = osgGA::GUIEventAdapter::KEY_Up;
|
|
||||||
mKeyMap[Qt::Key_Down ] = osgGA::GUIEventAdapter::KEY_Down;
|
|
||||||
mKeyMap[Qt::Key_Backspace ] = osgGA::GUIEventAdapter::KEY_BackSpace;
|
|
||||||
mKeyMap[Qt::Key_Tab ] = osgGA::GUIEventAdapter::KEY_Tab;
|
|
||||||
mKeyMap[Qt::Key_Space ] = osgGA::GUIEventAdapter::KEY_Space;
|
|
||||||
mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_Delete;
|
|
||||||
mKeyMap[Qt::Key_Alt ] = osgGA::GUIEventAdapter::KEY_Alt_L;
|
|
||||||
mKeyMap[Qt::Key_Shift ] = osgGA::GUIEventAdapter::KEY_Shift_L;
|
|
||||||
|
|
||||||
#if defined(Q_OS_MACOS)
|
|
||||||
// undo the Qt-mac remapping
|
|
||||||
mKeyMap[Qt::Key_Meta ] = osgGA::GUIEventAdapter::KEY_Control_L;
|
|
||||||
mKeyMap[Qt::Key_Control ] = osgGA::GUIEventAdapter::KEY_Meta_L;
|
|
||||||
#else
|
|
||||||
mKeyMap[Qt::Key_Control ] = osgGA::GUIEventAdapter::KEY_Control_L;
|
|
||||||
mKeyMap[Qt::Key_Meta ] = osgGA::GUIEventAdapter::KEY_Meta_L;
|
|
||||||
#endif
|
|
||||||
mKeyMap[Qt::Key_Super_L ] = osgGA::GUIEventAdapter::KEY_Super_L;
|
|
||||||
mKeyMap[Qt::Key_Super_R ] = osgGA::GUIEventAdapter::KEY_Super_R;
|
|
||||||
mKeyMap[Qt::Key_Hyper_L ] = osgGA::GUIEventAdapter::KEY_Hyper_L;
|
|
||||||
mKeyMap[Qt::Key_Hyper_R ] = osgGA::GUIEventAdapter::KEY_Hyper_R;
|
|
||||||
|
|
||||||
|
|
||||||
mKeyMap[Qt::Key_F1 ] = osgGA::GUIEventAdapter::KEY_F1;
|
|
||||||
mKeyMap[Qt::Key_F2 ] = osgGA::GUIEventAdapter::KEY_F2;
|
|
||||||
mKeyMap[Qt::Key_F3 ] = osgGA::GUIEventAdapter::KEY_F3;
|
|
||||||
mKeyMap[Qt::Key_F4 ] = osgGA::GUIEventAdapter::KEY_F4;
|
|
||||||
mKeyMap[Qt::Key_F5 ] = osgGA::GUIEventAdapter::KEY_F5;
|
|
||||||
mKeyMap[Qt::Key_F6 ] = osgGA::GUIEventAdapter::KEY_F6;
|
|
||||||
mKeyMap[Qt::Key_F7 ] = osgGA::GUIEventAdapter::KEY_F7;
|
|
||||||
mKeyMap[Qt::Key_F8 ] = osgGA::GUIEventAdapter::KEY_F8;
|
|
||||||
mKeyMap[Qt::Key_F9 ] = osgGA::GUIEventAdapter::KEY_F9;
|
|
||||||
mKeyMap[Qt::Key_F10 ] = osgGA::GUIEventAdapter::KEY_F10;
|
|
||||||
mKeyMap[Qt::Key_F11 ] = osgGA::GUIEventAdapter::KEY_F11;
|
|
||||||
mKeyMap[Qt::Key_F12 ] = osgGA::GUIEventAdapter::KEY_F12;
|
|
||||||
mKeyMap[Qt::Key_F13 ] = osgGA::GUIEventAdapter::KEY_F13;
|
|
||||||
mKeyMap[Qt::Key_F14 ] = osgGA::GUIEventAdapter::KEY_F14;
|
|
||||||
mKeyMap[Qt::Key_F15 ] = osgGA::GUIEventAdapter::KEY_F15;
|
|
||||||
mKeyMap[Qt::Key_F16 ] = osgGA::GUIEventAdapter::KEY_F16;
|
|
||||||
mKeyMap[Qt::Key_F17 ] = osgGA::GUIEventAdapter::KEY_F17;
|
|
||||||
mKeyMap[Qt::Key_F18 ] = osgGA::GUIEventAdapter::KEY_F18;
|
|
||||||
mKeyMap[Qt::Key_F19 ] = osgGA::GUIEventAdapter::KEY_F19;
|
|
||||||
mKeyMap[Qt::Key_F20 ] = osgGA::GUIEventAdapter::KEY_F20;
|
|
||||||
|
|
||||||
|
|
||||||
mKeyMap[Qt::Key_Insert ] = osgGA::GUIEventAdapter::KEY_KP_Insert;
|
|
||||||
//mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_KP_Delete;
|
|
||||||
}
|
|
||||||
|
|
||||||
~QtKeyboardMap()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int remapKey(QKeyEvent* event)
|
|
||||||
{
|
|
||||||
const QChar unicodePoint = event->text().isEmpty() ? QChar() : event->text().at(0);
|
|
||||||
KeyMap::iterator itr = mKeyMap.find(event->key());
|
|
||||||
if (itr == mKeyMap.end()) {
|
|
||||||
if (unicodePoint.isNull()) {
|
|
||||||
// this happens for Ctrl modifiers on A-Z (at least). Keyboard.xml relies on the
|
|
||||||
// old ASCII mappings of these values, so we need to synthesise those here
|
|
||||||
// since Qt won't do it.
|
|
||||||
|
|
||||||
const auto k = event->key();
|
|
||||||
if ((k >= Qt::Key_A) && (k <= Qt::Key_Z)) {
|
|
||||||
return 1 + (k - Qt::Key_A); // offset into the ASCII control code range
|
|
||||||
} else {
|
|
||||||
qWarning() << Q_FUNC_INFO << "misssing mapping for key";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
qDebug() << "key" << event->key() << ", mods" << event->modifiers() << "Unicode:" << unicodePoint << ", ASCII:"
|
|
||||||
<< unicodePoint.toLatin1() << "(" << (int)unicodePoint.toLatin1() << "), raw text:" << event->text();
|
|
||||||
#endif
|
|
||||||
return int(unicodePoint.toLatin1());
|
|
||||||
}
|
|
||||||
|
|
||||||
return itr->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef std::map<unsigned int, int> KeyMap;
|
|
||||||
KeyMap mKeyMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
static QtKeyboardMap s_QtKeyboardMap;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GLWindow::GLWindow()
|
|
||||||
: QWindow()
|
|
||||||
{
|
|
||||||
_devicePixelRatio = 1.0;
|
|
||||||
connect(this, &QWindow::screenChanged, this, &GLWindow::onScreenChanged);
|
|
||||||
onScreenChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::onScreenChanged()
|
|
||||||
{
|
|
||||||
qWarning() << Q_FUNC_INFO << "screen changed";
|
|
||||||
_devicePixelRatio = screen()->devicePixelRatio();
|
|
||||||
|
|
||||||
if (_isPrimaryWindow) {
|
|
||||||
// allow PUI and Canvas to be scaled
|
|
||||||
fgSetDouble("/sim/rendering/gui-pixel-ratio", _devicePixelRatio);
|
|
||||||
}
|
|
||||||
|
|
||||||
syncGeometryWithOSG();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::syncGeometryWithOSG()
|
|
||||||
{
|
|
||||||
const int w = width();
|
|
||||||
const int h = height();
|
|
||||||
|
|
||||||
int scaled_width = static_cast<int>(w *_devicePixelRatio);
|
|
||||||
int scaled_height = static_cast<int>(h*_devicePixelRatio);
|
|
||||||
|
|
||||||
if (_gw) {
|
|
||||||
_gw->resized( x(), y(), scaled_width, scaled_height);
|
|
||||||
_gw->getEventQueue()->windowResize( x(), y(), scaled_width, scaled_height );
|
|
||||||
_gw->requestRedraw();
|
|
||||||
_gw->_updateContextNeeded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLWindow::~GLWindow()
|
|
||||||
{
|
|
||||||
if (_gw) {
|
|
||||||
_gw->_window = nullptr;
|
|
||||||
_gw = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (event->type() == QEvent::UpdateRequest)
|
|
||||||
{
|
|
||||||
processUpdateEvent();
|
|
||||||
}
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::processUpdateEvent()
|
|
||||||
{
|
|
||||||
osg::ref_ptr<osgViewer::ViewerBase> v;
|
|
||||||
if (_gw->_viewer.lock(v)) {
|
|
||||||
v->frame();
|
|
||||||
}
|
|
||||||
|
|
||||||
// see discussion of QWindow::requestUpdate to see
|
|
||||||
// why this is good behaviour
|
|
||||||
if (_gw->_continousUpdate) {
|
|
||||||
requestUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setOSGModifier(int& modifiers, unsigned int bits, bool set)
|
|
||||||
{
|
|
||||||
if (set) {
|
|
||||||
modifiers |= bits;
|
|
||||||
} else {
|
|
||||||
modifiers &= ~bits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::setKeyboardModifiers(const Qt::KeyboardModifiers qtMods)
|
|
||||||
{
|
|
||||||
auto es = _gw->getEventQueue()->getCurrentEventState();
|
|
||||||
auto modifiers = es->getModKeyMask();
|
|
||||||
|
|
||||||
#if defined(Q_OS_MACOS)
|
|
||||||
setOSGModifier(modifiers, osgGA::GUIEventAdapter::MODKEY_CTRL, qtMods & Qt::MetaModifier);
|
|
||||||
#else
|
|
||||||
setOSGModifier(modifiers, osgGA::GUIEventAdapter::MODKEY_CTRL, qtMods & Qt::ControlModifier);
|
|
||||||
#endif
|
|
||||||
setOSGModifier(modifiers, osgGA::GUIEventAdapter::MODKEY_ALT, qtMods & Qt::AltModifier);
|
|
||||||
setOSGModifier(modifiers, osgGA::GUIEventAdapter::MODKEY_SHIFT, qtMods & Qt::ShiftModifier);
|
|
||||||
|
|
||||||
_gw->getEventQueue()->getCurrentEventState()->setModKeyMask(modifiers);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::resizeEvent( QResizeEvent* event )
|
|
||||||
{
|
|
||||||
QWindow::resizeEvent(event);
|
|
||||||
syncGeometryWithOSG();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::moveEvent( QMoveEvent* event )
|
|
||||||
{
|
|
||||||
QWindow::moveEvent(event);
|
|
||||||
syncGeometryWithOSG();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::keyPressEvent( QKeyEvent* event )
|
|
||||||
{
|
|
||||||
setKeyboardModifiers( event->modifiers() );
|
|
||||||
int value = s_QtKeyboardMap.remapKey( event );
|
|
||||||
_gw->getEventQueue()->keyPress( value );
|
|
||||||
|
|
||||||
// this passes the event to the regular Qt key event processing,
|
|
||||||
// among others, it closes popup windows on ESC and forwards the event to the parent widgets
|
|
||||||
if( _forwardKeyEvents )
|
|
||||||
inherited::keyPressEvent( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::keyReleaseEvent( QKeyEvent* event )
|
|
||||||
{
|
|
||||||
if (event->isAutoRepeat()) {
|
|
||||||
event->ignore();
|
|
||||||
} else {
|
|
||||||
setKeyboardModifiers(event->modifiers() );
|
|
||||||
int value = s_QtKeyboardMap.remapKey( event );
|
|
||||||
_gw->getEventQueue()->keyRelease( value );
|
|
||||||
}
|
|
||||||
|
|
||||||
// this passes the event to the regular Qt key event processing,
|
|
||||||
// among others, it closes popup windows on ESC and forwards the event to the parent widgets
|
|
||||||
if( _forwardKeyEvents )
|
|
||||||
inherited::keyReleaseEvent( event );
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::mousePressEvent( QMouseEvent* event )
|
|
||||||
{
|
|
||||||
int button = 0;
|
|
||||||
switch ( event->button() )
|
|
||||||
{
|
|
||||||
case Qt::LeftButton: button = 1; break;
|
|
||||||
case Qt::MidButton: button = 2; break;
|
|
||||||
case Qt::RightButton: button = 3; break;
|
|
||||||
case Qt::NoButton: button = 0; break;
|
|
||||||
default: button = 0; break;
|
|
||||||
}
|
|
||||||
setKeyboardModifiers(event->modifiers());
|
|
||||||
_gw->getEventQueue()->mouseButtonPress( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button );
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::mouseReleaseEvent( QMouseEvent* event )
|
|
||||||
{
|
|
||||||
int button = 0;
|
|
||||||
switch ( event->button() )
|
|
||||||
{
|
|
||||||
case Qt::LeftButton: button = 1; break;
|
|
||||||
case Qt::MidButton: button = 2; break;
|
|
||||||
case Qt::RightButton: button = 3; break;
|
|
||||||
case Qt::NoButton: button = 0; break;
|
|
||||||
default: button = 0; break;
|
|
||||||
}
|
|
||||||
setKeyboardModifiers(event->modifiers());
|
|
||||||
_gw->getEventQueue()->mouseButtonRelease( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button );
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::mouseDoubleClickEvent( QMouseEvent* event )
|
|
||||||
{
|
|
||||||
int button = 0;
|
|
||||||
switch ( event->button() )
|
|
||||||
{
|
|
||||||
case Qt::LeftButton: button = 1; break;
|
|
||||||
case Qt::MidButton: button = 2; break;
|
|
||||||
case Qt::RightButton: button = 3; break;
|
|
||||||
case Qt::NoButton: button = 0; break;
|
|
||||||
default: button = 0; break;
|
|
||||||
}
|
|
||||||
setKeyboardModifiers(event->modifiers());
|
|
||||||
_gw->getEventQueue()->mouseDoubleButtonPress( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button );
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::mouseMoveEvent( QMouseEvent* event )
|
|
||||||
{
|
|
||||||
setKeyboardModifiers(event->modifiers());
|
|
||||||
_gw->getEventQueue()->mouseMotion( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio );
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::wheelEvent( QWheelEvent* event )
|
|
||||||
{
|
|
||||||
setKeyboardModifiers(event->modifiers());
|
|
||||||
_gw->getEventQueue()->mouseScroll(
|
|
||||||
event->orientation() == Qt::Vertical ?
|
|
||||||
(event->delta()>0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN) :
|
|
||||||
(event->delta()>0 ? osgGA::GUIEventAdapter::SCROLL_LEFT : osgGA::GUIEventAdapter::SCROLL_RIGHT) );
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsWindowQt5::GraphicsWindowQt5(osg::GraphicsContext::Traits* traits)
|
|
||||||
{
|
|
||||||
_traits = traits;
|
|
||||||
init(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
GraphicsWindowQt5::~GraphicsWindowQt5()
|
|
||||||
{
|
|
||||||
OSG_INFO << "destroying GraphicsWindowQt5" << std::endl;
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt5::init( Qt::WindowFlags f )
|
|
||||||
{
|
|
||||||
// update _widget and parent by WindowData
|
|
||||||
WindowData* windowData = _traits.get() ? dynamic_cast<WindowData*>(_traits->inheritedWindowData.get()) : 0;
|
|
||||||
assert(!_window);
|
|
||||||
_ownsWidget = true;
|
|
||||||
|
|
||||||
// WindowFlags
|
|
||||||
Qt::WindowFlags flags = f | Qt::Window | Qt::CustomizeWindowHint;
|
|
||||||
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 window
|
|
||||||
_window.reset(new GLWindow);
|
|
||||||
_window->setFlags(flags);
|
|
||||||
_window->setSurfaceType(QSurface::OpenGLSurface);
|
|
||||||
_window->setFormat(traits2qSurfaceFormat(_traits.get()));
|
|
||||||
_window->create();
|
|
||||||
_window->setTitle( _traits->windowName.c_str() );
|
|
||||||
|
|
||||||
// to get OS-dependant default positioning of the window (which is desirable),
|
|
||||||
// we must take care to only set the position if explicitly requested.
|
|
||||||
// hence we set X & Y to these marker values by default.
|
|
||||||
// And hence only set position if both are valid.
|
|
||||||
if ((_traits->x != std::numeric_limits<int>::max()) && (_traits->y != std::numeric_limits<int>::max())) {
|
|
||||||
_window->setPosition( _traits->x, _traits->y );
|
|
||||||
}
|
|
||||||
|
|
||||||
QSize sz(_traits->width, _traits->height);
|
|
||||||
if ( !_traits->supportsResize ) {
|
|
||||||
_window->setMinimumSize( sz );
|
|
||||||
_window->setMaximumSize( sz );
|
|
||||||
} else {
|
|
||||||
_window->resize( sz );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (windowData->createFullscreen) {
|
|
||||||
// this doesn't seem to actually work, so we
|
|
||||||
// check the flag again in realizeImplementation()
|
|
||||||
_window->setWindowState(Qt::WindowFullScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
_window->_isPrimaryWindow = windowData->isPrimaryWindow;
|
|
||||||
if (_window->_isPrimaryWindow) {
|
|
||||||
fgSetDouble("/sim/rendering/gui-pixel-ratio", _window->_devicePixelRatio);
|
|
||||||
}
|
|
||||||
|
|
||||||
_window->setGraphicsWindow( this );
|
|
||||||
useCursor( _traits->useCursor );
|
|
||||||
|
|
||||||
// initialize State
|
|
||||||
setState( new osg::State );
|
|
||||||
getState()->setGraphicsContext(this);
|
|
||||||
getState()->setContextID( osg::GraphicsContext::createNewContextID() );
|
|
||||||
|
|
||||||
// make sure the event queue has the correct window rectangle size and input range
|
|
||||||
getEventQueue()->syncWindowRectangleWithGraphicsContext();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSurfaceFormat GraphicsWindowQt5::traits2qSurfaceFormat( const osg::GraphicsContext::Traits* traits )
|
|
||||||
{
|
|
||||||
QSurfaceFormat format;
|
|
||||||
format.setRenderableType(QSurfaceFormat::OpenGL);
|
|
||||||
|
|
||||||
format.setAlphaBufferSize( traits->alpha );
|
|
||||||
format.setRedBufferSize( traits->red );
|
|
||||||
format.setGreenBufferSize( traits->green );
|
|
||||||
format.setBlueBufferSize( traits->blue );
|
|
||||||
format.setDepthBufferSize( traits->depth );
|
|
||||||
format.setStencilBufferSize( traits->stencil );
|
|
||||||
// format.setSampleBuffers( traits->sampleBuffers );
|
|
||||||
format.setSamples( traits->samples );
|
|
||||||
|
|
||||||
format.setAlphaBufferSize( traits->alpha>0 );
|
|
||||||
format.setDepthBufferSize( traits->depth );
|
|
||||||
|
|
||||||
format.setSwapBehavior( traits->doubleBuffer ?
|
|
||||||
QSurfaceFormat::DoubleBuffer :
|
|
||||||
QSurfaceFormat::DefaultSwapBehavior);
|
|
||||||
format.setSwapInterval( traits->vsync ? 1 : 0 );
|
|
||||||
format.setStereo( traits->quadBufferStereo ? 1 : 0 );
|
|
||||||
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::qSurfaceFormat2traits( const QSurfaceFormat& format, osg::GraphicsContext::Traits* traits )
|
|
||||||
{
|
|
||||||
traits->red = format.redBufferSize();
|
|
||||||
traits->green = format.greenBufferSize();
|
|
||||||
traits->blue = format.blueBufferSize();
|
|
||||||
traits->alpha = format.alphaBufferSize();
|
|
||||||
traits->depth = format.depthBufferSize();
|
|
||||||
traits->stencil = format.stencilBufferSize();
|
|
||||||
traits->samples = format.samples();
|
|
||||||
|
|
||||||
traits->quadBufferStereo = format.stereo();
|
|
||||||
traits->doubleBuffer = (format.swapBehavior() == QSurfaceFormat::DoubleBuffer);
|
|
||||||
traits->vsync = format.swapInterval() >= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::GraphicsContext::Traits* GraphicsWindowQt5::createTraits( const QWindow* window )
|
|
||||||
{
|
|
||||||
osg::GraphicsContext::Traits *traits = new osg::GraphicsContext::Traits;
|
|
||||||
|
|
||||||
qSurfaceFormat2traits( window->format(), traits );
|
|
||||||
|
|
||||||
QRect r = window->geometry();
|
|
||||||
traits->x = r.x();
|
|
||||||
traits->y = r.y();
|
|
||||||
traits->width = r.width();
|
|
||||||
traits->height = r.height();
|
|
||||||
|
|
||||||
traits->windowName = window->title().toLocal8Bit().data();
|
|
||||||
Qt::WindowFlags f = window->flags();
|
|
||||||
traits->windowDecoration = ( f & Qt::WindowTitleHint ) &&
|
|
||||||
( f & Qt::WindowMinMaxButtonsHint ) &&
|
|
||||||
( f & Qt::WindowSystemMenuHint );
|
|
||||||
|
|
||||||
traits->supportsResize = true;
|
|
||||||
|
|
||||||
/*
|
|
||||||
QSizePolicy sp = window->sizePolicy();
|
|
||||||
traits->supportsResize = sp.horizontalPolicy() != QSizePolicy::Fixed ||
|
|
||||||
sp.verticalPolicy() != QSizePolicy::Fixed;
|
|
||||||
*/
|
|
||||||
return traits;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt5::setWindowRectangleImplementation( int x, int y, int width, int height )
|
|
||||||
{
|
|
||||||
if (!_window)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
qDebug() << "setWRI window geometry to " << x << "," << y <<
|
|
||||||
" w=" << width << " h=" << height;
|
|
||||||
_window->setGeometry( x, y, width, height );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::getWindowRectangle( int& x, int& y, int& width, int& height )
|
|
||||||
{
|
|
||||||
if ( _window )
|
|
||||||
{
|
|
||||||
const QRect& geom = _window->geometry();
|
|
||||||
x = geom.x();
|
|
||||||
y = geom.y();
|
|
||||||
width = geom.width();
|
|
||||||
height = geom.height();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt5::setWindowDecorationImplementation( bool windowDecoration )
|
|
||||||
{
|
|
||||||
Qt::WindowFlags flags = Qt::Window|Qt::CustomizeWindowHint;//|Qt::WindowStaysOnTopHint;
|
|
||||||
if ( windowDecoration )
|
|
||||||
flags |= Qt::WindowTitleHint|Qt::WindowMinMaxButtonsHint|Qt::WindowSystemMenuHint;
|
|
||||||
_traits->windowDecoration = windowDecoration;
|
|
||||||
|
|
||||||
if ( _window )
|
|
||||||
{
|
|
||||||
_window->setFlags( flags );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt5::getWindowDecoration() const
|
|
||||||
{
|
|
||||||
return _traits->windowDecoration;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::grabFocus()
|
|
||||||
{
|
|
||||||
if ( _window )
|
|
||||||
_window->requestActivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::grabFocusIfPointerInWindow()
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
if ( _widget->underMouse() )
|
|
||||||
_widget->setFocus( Qt::ActiveWindowFocusReason );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::raiseWindow()
|
|
||||||
{
|
|
||||||
if ( _window )
|
|
||||||
_window->raise();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::setWindowName( const std::string& name )
|
|
||||||
{
|
|
||||||
if ( _window )
|
|
||||||
_window->setTitle( QString::fromUtf8(name.c_str()) );
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GraphicsWindowQt5::getWindowName()
|
|
||||||
{
|
|
||||||
return _window ? _window->title().toStdString() : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::useCursor( bool cursorOn )
|
|
||||||
{
|
|
||||||
if ( _window )
|
|
||||||
{
|
|
||||||
_traits->useCursor = cursorOn;
|
|
||||||
if ( !cursorOn ) _window->setCursor( Qt::BlankCursor );
|
|
||||||
else _window->setCursor( _currentCursor );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::setCursor( MouseCursor cursor )
|
|
||||||
{
|
|
||||||
if ( cursor==InheritCursor && _window )
|
|
||||||
{
|
|
||||||
_window->unsetCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ( cursor )
|
|
||||||
{
|
|
||||||
case NoCursor: _currentCursor = Qt::BlankCursor; break;
|
|
||||||
case RightArrowCursor: case LeftArrowCursor: _currentCursor = Qt::ArrowCursor; break;
|
|
||||||
case InfoCursor: _currentCursor = Qt::SizeAllCursor; break;
|
|
||||||
case DestroyCursor: _currentCursor = Qt::ForbiddenCursor; break;
|
|
||||||
case HelpCursor: _currentCursor = Qt::WhatsThisCursor; break;
|
|
||||||
case CycleCursor: _currentCursor = Qt::ForbiddenCursor; break;
|
|
||||||
case SprayCursor: _currentCursor = Qt::SizeAllCursor; break;
|
|
||||||
case WaitCursor: _currentCursor = Qt::WaitCursor; break;
|
|
||||||
case TextCursor: _currentCursor = Qt::IBeamCursor; break;
|
|
||||||
case CrosshairCursor: _currentCursor = Qt::CrossCursor; break;
|
|
||||||
case HandCursor: _currentCursor = Qt::OpenHandCursor; break;
|
|
||||||
case UpDownCursor: _currentCursor = Qt::SizeVerCursor; break;
|
|
||||||
case LeftRightCursor: _currentCursor = Qt::SizeHorCursor; break;
|
|
||||||
case TopSideCursor: case BottomSideCursor: _currentCursor = Qt::UpArrowCursor; break;
|
|
||||||
case LeftSideCursor: case RightSideCursor: _currentCursor = Qt::SizeHorCursor; break;
|
|
||||||
case TopLeftCorner: _currentCursor = Qt::SizeBDiagCursor; break;
|
|
||||||
case TopRightCorner: _currentCursor = Qt::SizeFDiagCursor; break;
|
|
||||||
case BottomRightCorner: _currentCursor = Qt::SizeBDiagCursor; break;
|
|
||||||
case BottomLeftCorner: _currentCursor = Qt::SizeFDiagCursor; break;
|
|
||||||
default: break;
|
|
||||||
};
|
|
||||||
if ( _window ) _window->setCursor( _currentCursor );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt5::valid() const
|
|
||||||
{
|
|
||||||
return _window.get() != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt5::realizeImplementation()
|
|
||||||
{
|
|
||||||
WindowData* windowData = _traits.get() ? dynamic_cast<WindowData*>(_traits->inheritedWindowData.get()) : nullptr;
|
|
||||||
if (windowData->createFullscreen) {
|
|
||||||
_window->showFullScreen();
|
|
||||||
// work-around for resize events being discarded by EventQueue::setStartTick
|
|
||||||
_sendResizeOnEventCheck = true;
|
|
||||||
} else {
|
|
||||||
_window->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the event queue has the correct window rectangle size and input range
|
|
||||||
getEventQueue()->syncWindowRectangleWithGraphicsContext();
|
|
||||||
|
|
||||||
getEventQueue()->getCurrentEventState()->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS);
|
|
||||||
|
|
||||||
_realized = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt5::isRealizedImplementation() const
|
|
||||||
{
|
|
||||||
return _realized;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::closeImplementation()
|
|
||||||
{
|
|
||||||
if ( _window ) {
|
|
||||||
_window->close();
|
|
||||||
_window.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
_context.reset();
|
|
||||||
_realized = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::runOperations()
|
|
||||||
{
|
|
||||||
// While in graphics thread this is last chance to do something useful before
|
|
||||||
// graphics thread will execute its operations.
|
|
||||||
if (_updateContextNeeded || (QOpenGLContext::currentContext() != _context.get())) {
|
|
||||||
makeCurrent();
|
|
||||||
_updateContextNeeded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_window->beforeRendering();
|
|
||||||
|
|
||||||
GraphicsWindow::runOperations();
|
|
||||||
|
|
||||||
_window->afterRendering();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt5::makeCurrentImplementation()
|
|
||||||
{
|
|
||||||
if (!_context) {
|
|
||||||
if ( _traits->sharedContext.valid() ) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "share contexts not supported";
|
|
||||||
}
|
|
||||||
|
|
||||||
_context.reset(new QOpenGLContext());
|
|
||||||
_context->setFormat(_window->format());
|
|
||||||
bool result = _context->create();
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
OSG_WARN << "GraphicsWindowQt5: Can't create QOpenGLContext'" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_context->makeCurrent(_window.get());
|
|
||||||
// allow derived classes to do work now the context is initalised
|
|
||||||
contextInitalised();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_context && (QThread::currentThread() != _context->thread())) {
|
|
||||||
qWarning() << "attempt to make context current on wrong thread";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_context->makeCurrent(_window.get());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt5::releaseContextImplementation()
|
|
||||||
{
|
|
||||||
_context->doneCurrent();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::swapBuffersImplementation()
|
|
||||||
{
|
|
||||||
_context->swapBuffers(_window.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::requestWarpPointer( float x, float y )
|
|
||||||
{
|
|
||||||
if ( _window )
|
|
||||||
QCursor::setPos( _window->mapToGlobal(QPoint((int)x,(int)y)) );
|
|
||||||
|
|
||||||
getEventQueue()->mouseWarped(x,y);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GraphicsWindowQt5::checkEvents()
|
|
||||||
{
|
|
||||||
if (_sendResizeOnEventCheck) {
|
|
||||||
_sendResizeOnEventCheck = false;
|
|
||||||
_window->syncGeometryWithOSG();
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo - only if not running inside QApplication::exec; can we check this?
|
|
||||||
QCoreApplication::processEvents(QEventLoop::AllEvents);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::setViewer(osgViewer::ViewerBase* viewer)
|
|
||||||
{
|
|
||||||
osg::ref_ptr<osgViewer::ViewerBase> previous(_viewer);
|
|
||||||
_viewer = viewer;
|
|
||||||
viewerChanged(previous.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::viewerChanged(osgViewer::ViewerBase*)
|
|
||||||
{
|
|
||||||
// nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::requestRedraw()
|
|
||||||
{
|
|
||||||
_window->requestUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::requestContinuousUpdate(bool needed)
|
|
||||||
{
|
|
||||||
_continousUpdate = needed;
|
|
||||||
GraphicsWindow::requestContinuousUpdate(needed);
|
|
||||||
if (_continousUpdate) {
|
|
||||||
_window->requestUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GraphicsWindowQt5::setFullscreen(bool isFullscreen)
|
|
||||||
{
|
|
||||||
if (isFullscreen) {
|
|
||||||
_window->showFullScreen();
|
|
||||||
} else {
|
|
||||||
// FIXME should restore previous state?
|
|
||||||
_window->showNormal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Qt5WindowingSystem : public osg::GraphicsContext::WindowingSystemInterface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
Qt5WindowingSystem()
|
|
||||||
{
|
|
||||||
#if OSG_VERSION_GREATER_THAN(3,5,9)
|
|
||||||
setName("FlightGearQt5");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
~Qt5WindowingSystem()
|
|
||||||
{
|
|
||||||
if (osg::Referenced::getDeleteHandler())
|
|
||||||
{
|
|
||||||
osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
|
|
||||||
osg::Referenced::getDeleteHandler()->flushAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Access the Qt windowing system through this singleton class.
|
|
||||||
static Qt5WindowingSystem* getInterface()
|
|
||||||
{
|
|
||||||
static Qt5WindowingSystem* qtInterface = new Qt5WindowingSystem;
|
|
||||||
return qtInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the number of screens present in the system
|
|
||||||
virtual unsigned int getNumScreens( const osg::GraphicsContext::ScreenIdentifier& /*si*/ )
|
|
||||||
{
|
|
||||||
return QGuiApplication::screens().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the resolution of specified screen
|
|
||||||
// (0,0) is returned if screen is unknown
|
|
||||||
virtual void getScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si,
|
|
||||||
osg::GraphicsContext::ScreenSettings& resolution )
|
|
||||||
{
|
|
||||||
QScreen* screen = qScreenFromSI(si);
|
|
||||||
if (!screen) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "no screen for identifier" << QString::fromStdString(si.displayName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolution.width = screen->size().width();
|
|
||||||
resolution.height = screen->size().height();
|
|
||||||
resolution.colorDepth = screen->depth();
|
|
||||||
resolution.refreshRate = screen->refreshRate();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the resolution for given screen
|
|
||||||
virtual bool setScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*si*/, const osg::GraphicsContext::ScreenSettings & /*resolution*/ )
|
|
||||||
{
|
|
||||||
OSG_WARN << "osgQt: setScreenSettings() not implemented yet." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enumerates available resolutions
|
|
||||||
virtual void enumerateScreenSettings( const osg::GraphicsContext::ScreenIdentifier& si,
|
|
||||||
osg::GraphicsContext::ScreenSettingsList & resolutions )
|
|
||||||
{
|
|
||||||
QScreen* screen = qScreenFromSI(si);
|
|
||||||
if (!screen) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "no screen for identifier" << QString::fromStdString(si.displayName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolutions.clear();
|
|
||||||
osg::GraphicsContext::ScreenSettings ss;
|
|
||||||
ss.width = screen->size().width();
|
|
||||||
ss.height = screen->size().height();
|
|
||||||
ss.colorDepth = screen->depth();
|
|
||||||
ss.refreshRate = screen->refreshRate();
|
|
||||||
resolutions.push_back(ss);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a graphics context with given traits
|
|
||||||
virtual osg::GraphicsContext* createGraphicsContext( osg::GraphicsContext::Traits* traits )
|
|
||||||
{
|
|
||||||
if (traits->pbuffer)
|
|
||||||
{
|
|
||||||
OSG_WARN << "osgQt: createGraphicsContext - pbuffer not implemented yet." << std::endl;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
osg::ref_ptr< GraphicsWindowQt5 > window = new GraphicsWindowQt5( traits );
|
|
||||||
if (window->valid()) {
|
|
||||||
return window.release();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qWarning() << "window is not valid";
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QScreen* qScreenFromSI(const osg::GraphicsContext::ScreenIdentifier& si)
|
|
||||||
{
|
|
||||||
QList<QScreen*> screens = QGuiApplication::screens();
|
|
||||||
if (screens.size() < si.screenNum) {
|
|
||||||
return screens.at(si.screenNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
return QGuiApplication::primaryScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
// No implementation for these
|
|
||||||
Qt5WindowingSystem( const Qt5WindowingSystem& );
|
|
||||||
Qt5WindowingSystem& operator=( const Qt5WindowingSystem& );
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace flightgear
|
|
||||||
{
|
|
||||||
|
|
||||||
void initQtWindowingSystem()
|
|
||||||
{
|
|
||||||
#if OSG_VERSION_LESS_THAN(3,5,2)
|
|
||||||
osg::GraphicsContext::setWindowingSystemInterface(Qt5WindowingSystem::getInterface());
|
|
||||||
#else
|
|
||||||
osg::GraphicsContext::getWindowingSystemInterfaces()->addWindowingSystemInterface(Qt5WindowingSystem::getInterface());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} // of namespace flightgear
|
|
|
@ -1,193 +0,0 @@
|
||||||
// Copyright (C) 2017 James Turner
|
|
||||||
// derived from OSG GraphicsWindowQt by Wang Rui
|
|
||||||
//
|
|
||||||
// This program is free software; you can redistribute it and/or
|
|
||||||
// modify it under the terms of the GNU General Public License as
|
|
||||||
// published by the Free Software Foundation; either version 2 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program 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 GNU
|
|
||||||
// General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program; if not, write to the Free Software
|
|
||||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
|
|
||||||
#ifndef FGFS_GRAPHICSWINDOWQT
|
|
||||||
#define FGFS_GRAPHICSWINDOWQT
|
|
||||||
|
|
||||||
#include <QWindow>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <osgViewer/GraphicsWindow>
|
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QQueue>
|
|
||||||
#include <QSet>
|
|
||||||
|
|
||||||
class QInputEvent;
|
|
||||||
class QGestureEvent;
|
|
||||||
class QOpenGLContext;
|
|
||||||
|
|
||||||
namespace osgViewer {
|
|
||||||
class ViewerBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace flightgear
|
|
||||||
{
|
|
||||||
|
|
||||||
// forward declarations
|
|
||||||
class GraphicsWindowQt5;
|
|
||||||
|
|
||||||
/// The function sets the WindowingSystem to Qt.
|
|
||||||
void initQtWindowingSystem();
|
|
||||||
|
|
||||||
class GLWindow : public QWindow
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
typedef QWindow inherited;
|
|
||||||
|
|
||||||
public:
|
|
||||||
GLWindow();
|
|
||||||
|
|
||||||
virtual ~GLWindow();
|
|
||||||
|
|
||||||
virtual void setGraphicsWindow( GraphicsWindowQt5* gw ) { _gw = gw; }
|
|
||||||
virtual GraphicsWindowQt5* getGraphicsWindow() { return _gw; }
|
|
||||||
virtual const GraphicsWindowQt5* getGraphicsWindow() const { return _gw; }
|
|
||||||
|
|
||||||
inline bool getForwardKeyEvents() const { return _forwardKeyEvents; }
|
|
||||||
virtual void setForwardKeyEvents( bool f ) { _forwardKeyEvents = f; }
|
|
||||||
|
|
||||||
void setKeyboardModifiers(const Qt::KeyboardModifiers qtMods);
|
|
||||||
|
|
||||||
virtual void keyPressEvent( QKeyEvent* event );
|
|
||||||
virtual void keyReleaseEvent( QKeyEvent* event );
|
|
||||||
virtual void mousePressEvent( QMouseEvent* event );
|
|
||||||
virtual void mouseReleaseEvent( QMouseEvent* event );
|
|
||||||
virtual void mouseDoubleClickEvent( QMouseEvent* event );
|
|
||||||
virtual void mouseMoveEvent( QMouseEvent* event );
|
|
||||||
virtual void wheelEvent( QWheelEvent* event );
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void beforeRendering();
|
|
||||||
void afterRendering();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onScreenChanged();
|
|
||||||
|
|
||||||
void processUpdateEvent();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void syncGeometryWithOSG();
|
|
||||||
|
|
||||||
void updateEventQueueModifiers(QKeyEvent* event);
|
|
||||||
|
|
||||||
|
|
||||||
friend class GraphicsWindowQt5;
|
|
||||||
GraphicsWindowQt5* _gw = nullptr; // back-pointer
|
|
||||||
|
|
||||||
bool _forwardKeyEvents = false;
|
|
||||||
qreal _devicePixelRatio = 1.0;
|
|
||||||
|
|
||||||
// is this the primary (GUI) window
|
|
||||||
bool _isPrimaryWindow = false;
|
|
||||||
|
|
||||||
virtual void resizeEvent( QResizeEvent* event );
|
|
||||||
virtual void moveEvent( QMoveEvent* event );
|
|
||||||
virtual bool event( QEvent* event );
|
|
||||||
};
|
|
||||||
|
|
||||||
class GraphicsWindowQt5 : public osgViewer::GraphicsWindow
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GraphicsWindowQt5( osg::GraphicsContext::Traits* traits = 0);
|
|
||||||
virtual ~GraphicsWindowQt5();
|
|
||||||
|
|
||||||
inline GLWindow* getGLWindow() { return _window.get(); }
|
|
||||||
inline const GLWindow* getGLWindow() const { return _window.get(); }
|
|
||||||
|
|
||||||
struct WindowData : public osg::Referenced
|
|
||||||
{
|
|
||||||
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 );
|
|
||||||
|
|
||||||
static QSurfaceFormat traits2qSurfaceFormat( const osg::GraphicsContext::Traits* traits );
|
|
||||||
static void qSurfaceFormat2traits( const QSurfaceFormat& format, osg::GraphicsContext::Traits* traits );
|
|
||||||
static osg::GraphicsContext::Traits* createTraits( const QWindow* window );
|
|
||||||
|
|
||||||
virtual bool setWindowRectangleImplementation( int x, int y, int width, int height );
|
|
||||||
virtual void getWindowRectangle( int& x, int& y, int& width, int& height );
|
|
||||||
virtual bool setWindowDecorationImplementation( bool windowDecoration );
|
|
||||||
virtual bool getWindowDecoration() const;
|
|
||||||
virtual void grabFocus();
|
|
||||||
virtual void grabFocusIfPointerInWindow();
|
|
||||||
virtual void raiseWindow();
|
|
||||||
virtual void setWindowName( const std::string& name );
|
|
||||||
virtual std::string getWindowName();
|
|
||||||
virtual void useCursor( bool cursorOn );
|
|
||||||
virtual void setCursor( MouseCursor cursor );
|
|
||||||
// inline bool getTouchEventsEnabled() const { return _widget->getTouchEventsEnabled(); }
|
|
||||||
// virtual void setTouchEventsEnabled( bool e ) { _widget->setTouchEventsEnabled(e); }
|
|
||||||
|
|
||||||
|
|
||||||
virtual bool valid() const;
|
|
||||||
virtual bool realizeImplementation();
|
|
||||||
virtual bool isRealizedImplementation() const;
|
|
||||||
virtual void closeImplementation();
|
|
||||||
virtual bool makeCurrentImplementation();
|
|
||||||
virtual bool releaseContextImplementation();
|
|
||||||
virtual void swapBuffersImplementation();
|
|
||||||
virtual void runOperations();
|
|
||||||
virtual bool checkEvents();
|
|
||||||
|
|
||||||
virtual void requestRedraw();
|
|
||||||
virtual void requestContinuousUpdate(bool needed=true);
|
|
||||||
|
|
||||||
virtual void requestWarpPointer( float x, float y );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* set the viewer for this window. This will be refreshed when then
|
|
||||||
* QGuiApplication event loop runs (via exec), or when the window
|
|
||||||
* needs to be updated.
|
|
||||||
*/
|
|
||||||
void setViewer( osgViewer::ViewerBase *viewer );
|
|
||||||
|
|
||||||
virtual void contextInitalised() { ; }
|
|
||||||
|
|
||||||
void setFullscreen(bool isFullscreen);
|
|
||||||
protected:
|
|
||||||
virtual void viewerChanged(osgViewer::ViewerBase*);
|
|
||||||
|
|
||||||
friend class GLWindow;
|
|
||||||
std::unique_ptr<GLWindow> _window;
|
|
||||||
std::unique_ptr<QOpenGLContext> _context;
|
|
||||||
QOpenGLContext* _shareContext = nullptr;
|
|
||||||
bool _ownsWidget;
|
|
||||||
QCursor _currentCursor;
|
|
||||||
bool _realized = false;
|
|
||||||
bool _updateContextNeeded = false;
|
|
||||||
bool _continousUpdate = false;
|
|
||||||
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
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Add table
Reference in a new issue