diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index d9cde868a9..0b4c6dde3d 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -9,54 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// FIXME ordering of headers #include "Application.h" #include "GLCanvas.h" -#include -#include #include #include "MainWindow.h" #include "Menu.h" -static QGLFormat& getDesiredGLFormat() { - // Specify an OpenGL 3.3 format using the Core profile. - // That is, no old-school fixed pipeline functionality - static QGLFormat glFormat; - static std::once_flag once; - std::call_once(once, [] { - glFormat.setVersion(4, 1); - glFormat.setProfile(QGLFormat::CoreProfile); // Requires >=Qt-4.8.0 - glFormat.setSampleBuffers(false); - glFormat.setDepth(false); - glFormat.setStencil(false); - }); - return glFormat; -} - -GLCanvas::GLCanvas() : QGLWidget(getDesiredGLFormat()) { -#ifdef Q_OS_LINUX - // Cause GLCanvas::eventFilter to be called. - // It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux. - qApp->installEventFilter(this); -#endif -} - -int GLCanvas::getDeviceWidth() const { - return width() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f); -} - -int GLCanvas::getDeviceHeight() const { - return height() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f); -} - -void GLCanvas::initializeGL() { - setAttribute(Qt::WA_AcceptTouchEvents); - setAcceptDrops(true); - // Note, we *DO NOT* want Qt to automatically swap buffers for us. This results in the "ringing" bug mentioned in WL#19514 when we're throttling the framerate. - setAutoBufferSwap(false); -} - void GLCanvas::paintGL() { PROFILE_RANGE(__FUNCTION__); @@ -74,68 +35,8 @@ void GLCanvas::resizeGL(int width, int height) { } bool GLCanvas::event(QEvent* event) { - switch (event->type()) { - case QEvent::MouseMove: - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseButtonDblClick: - case QEvent::KeyPress: - case QEvent::KeyRelease: - case QEvent::FocusIn: - case QEvent::FocusOut: - case QEvent::Resize: - case QEvent::TouchBegin: - case QEvent::TouchEnd: - case QEvent::TouchUpdate: - case QEvent::Wheel: - case QEvent::DragEnter: - case QEvent::Drop: - if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) { - return true; - } - break; - case QEvent::Paint: - // Ignore paint events that occur after we've decided to quit - if (qApp->isAboutToQuit()) { - return true; - } - break; - - default: - break; + if (QEvent::Paint == event->type() && qApp->isAboutToQuit()) { + return true; } - return QGLWidget::event(event); -} - - -// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the -// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to -// receive keyPress events for the Alt (and Meta) key in a reliable manner. -// -// This filter catches events before QMenuBar can steal the keyboard focus. -// The idea was borrowed from -// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html - -bool GLCanvas::eventFilter(QObject*, QEvent* event) { - switch (event->type()) { - case QEvent::KeyPress: - case QEvent::KeyRelease: - case QEvent::ShortcutOverride: - { - QKeyEvent* keyEvent = static_cast(event); - if (keyEvent->key() == Qt::Key_Alt || keyEvent->key() == Qt::Key_Meta) { - if (event->type() == QEvent::KeyPress) { - keyPressEvent(keyEvent); - } else if (event->type() == QEvent::KeyRelease) { - keyReleaseEvent(keyEvent); - } else { - QGLWidget::event(event); - } - return true; - } - } - default: - break; - } - return false; + return GLWidget::event(event); } diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index 73c5b5e8bf..0442159eeb 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -12,31 +12,15 @@ #ifndef hifi_GLCanvas_h #define hifi_GLCanvas_h -#include -#include -#include +#include /// customized canvas that simply forwards requests/events to the singleton application -class GLCanvas : public QGLWidget { +class GLCanvas : public GLWidget { Q_OBJECT - -public: - GLCanvas(); - - int getDeviceWidth() const; - int getDeviceHeight() const; - QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); } - protected: - - virtual void initializeGL(); - virtual void paintGL(); - virtual void resizeGL(int width, int height); - virtual bool event(QEvent* event); - -private slots: - bool eventFilter(QObject*, QEvent* event); - + virtual void paintGL() override; + virtual void resizeGL(int width, int height) override; + virtual bool event(QEvent* event) override; }; diff --git a/libraries/gl/src/gl/GLHelpers.cpp b/libraries/gl/src/gl/GLHelpers.cpp index f67f9e9120..9022f0ffcc 100644 --- a/libraries/gl/src/gl/GLHelpers.cpp +++ b/libraries/gl/src/gl/GLHelpers.cpp @@ -1,15 +1,37 @@ #include "GLHelpers.h" +#include -QSurfaceFormat getDefaultOpenGlSurfaceFormat() { - QSurfaceFormat format; - // Qt Quick may need a depth and stencil buffer. Always make sure these are available. - format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS); - format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS); - format.setVersion(4, 1); +#include +#include + +const QSurfaceFormat& getDefaultOpenGlSurfaceFormat() { + static QSurfaceFormat format; + static std::once_flag once; + std::call_once(once, [] { + // Qt Quick may need a depth and stencil buffer. Always make sure these are available. + format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS); + format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS); + format.setVersion(4, 1); #ifdef DEBUG - format.setOption(QSurfaceFormat::DebugContext); + format.setOption(QSurfaceFormat::DebugContext); #endif - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); - return format; + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); + }); + return format; +} + +const QGLFormat& getDefaultGLFormat() { + // Specify an OpenGL 3.3 format using the Core profile. + // That is, no old-school fixed pipeline functionality + static QGLFormat glFormat; + static std::once_flag once; + std::call_once(once, [] { + glFormat.setVersion(4, 1); + glFormat.setProfile(QGLFormat::CoreProfile); // Requires >=Qt-4.8.0 + glFormat.setSampleBuffers(false); + glFormat.setDepth(false); + glFormat.setStencil(false); + }); + return glFormat; } diff --git a/libraries/gl/src/gl/GLHelpers.h b/libraries/gl/src/gl/GLHelpers.h index dc9f0f3140..de9e8f5d85 100644 --- a/libraries/gl/src/gl/GLHelpers.h +++ b/libraries/gl/src/gl/GLHelpers.h @@ -10,14 +10,15 @@ #ifndef hifi_GLHelpers_h #define hifi_GLHelpers_h -#include - // 16 bits of depth precision #define DEFAULT_GL_DEPTH_BUFFER_BITS 16 // 8 bits of stencil buffer (typically you really only need 1 bit for functionality // but GL implementations usually just come with buffer sizes in multiples of 8) #define DEFAULT_GL_STENCIL_BUFFER_BITS 8 -QSurfaceFormat getDefaultOpenGlSurfaceFormat(); +class QSurfaceFormat; +class QGLFormat; +const QSurfaceFormat& getDefaultOpenGlSurfaceFormat(); +const QGLFormat& getDefaultGLFormat(); #endif diff --git a/libraries/gl/src/gl/GLWidget.cpp b/libraries/gl/src/gl/GLWidget.cpp new file mode 100644 index 0000000000..b274b39da7 --- /dev/null +++ b/libraries/gl/src/gl/GLWidget.cpp @@ -0,0 +1,107 @@ +// +// GLWidget.cpp +// interface/src +// +// Created by Stephen Birarda on 8/14/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "GLWidget.h" + +#include + +#include +#include +#include + +#include +#include + +#include "GLHelpers.h" + +GLWidget::GLWidget() : QGLWidget(getDefaultGLFormat()) { +#ifdef Q_OS_LINUX + // Cause GLWidget::eventFilter to be called. + // It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux. + qApp->installEventFilter(this); +#endif +} + +int GLWidget::getDeviceWidth() const { + return width() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f); +} + +int GLWidget::getDeviceHeight() const { + return height() * (windowHandle() ? (float)windowHandle()->devicePixelRatio() : 1.0f); +} + +void GLWidget::initializeGL() { + setAttribute(Qt::WA_AcceptTouchEvents); + setAcceptDrops(true); + // Note, we *DO NOT* want Qt to automatically swap buffers for us. This results in the "ringing" bug mentioned in WL#19514 when we're throttling the framerate. + setAutoBufferSwap(false); +} + +bool GLWidget::event(QEvent* event) { + switch (event->type()) { + case QEvent::MouseMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::FocusIn: + case QEvent::FocusOut: + case QEvent::Resize: + case QEvent::TouchBegin: + case QEvent::TouchEnd: + case QEvent::TouchUpdate: + case QEvent::Wheel: + case QEvent::DragEnter: + case QEvent::Drop: + if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) { + return true; + } + break; + + default: + break; + } + return QGLWidget::event(event); +} + + +// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the +// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to +// receive keyPress events for the Alt (and Meta) key in a reliable manner. +// +// This filter catches events before QMenuBar can steal the keyboard focus. +// The idea was borrowed from +// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html + +bool GLWidget::eventFilter(QObject*, QEvent* event) { + switch (event->type()) { + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::ShortcutOverride: + { + QKeyEvent* keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Alt || keyEvent->key() == Qt::Key_Meta) { + if (event->type() == QEvent::KeyPress) { + keyPressEvent(keyEvent); + } else if (event->type() == QEvent::KeyRelease) { + keyReleaseEvent(keyEvent); + } else { + QGLWidget::event(event); + } + return true; + } + } + default: + break; + } + return false; +} diff --git a/libraries/gl/src/gl/GLWidget.h b/libraries/gl/src/gl/GLWidget.h new file mode 100644 index 0000000000..040ce542e9 --- /dev/null +++ b/libraries/gl/src/gl/GLWidget.h @@ -0,0 +1,36 @@ +// +// GLWidget.h +// interface/src +// +// Created by Stephen Birarda on 8/14/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_GLWidget_h +#define hifi_GLWidget_h + +#include + +/// customized canvas that simply forwards requests/events to the singleton application +class GLWidget : public QGLWidget { + Q_OBJECT + +public: + GLWidget(); + int getDeviceWidth() const; + int getDeviceHeight() const; + QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); } + +protected: + virtual void initializeGL() override; + virtual bool event(QEvent* event) override; + +private slots: + virtual bool eventFilter(QObject*, QEvent* event) override; +}; + + +#endif // hifi_GLCanvas_h