Loading [MathJax]/extensions/TeX/AMSmath.js
Radium Engine  1.6.3
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
WindowQt.cpp
1#include "WindowQt.hpp"
2
3#include <Core/Utils/Log.hpp>
4#include <QApplication>
5#include <QDebug>
6#include <QOpenGLContext>
7#include <QResizeEvent>
8#include <QScreen>
9#include <QSurfaceFormat>
10#include <ostream>
11#include <string>
12
13using namespace Ra::Core::Utils; // log
14
15namespace Ra {
16namespace Gui {
17
18WindowQt* WindowQt::s_getProcAddressHelper = nullptr;
19
20QSurfaceFormat defaultFormat() {
21 QSurfaceFormat format;
22 format.setProfile( QSurfaceFormat::CoreProfile );
23#ifndef NDEBUG
24 format.setOption( QSurfaceFormat::DebugContext );
25#endif
26 return format;
27}
28
29WindowQt::WindowQt( QScreen* screen ) :
30 QWindow( screen ), m_context( nullptr ), m_updatePending( false ), m_glInitialized( false ) {
31
32 setSurfaceType( QWindow::OpenGLSurface );
33 if ( !s_getProcAddressHelper ) { s_getProcAddressHelper = this; }
34
35 // No need to create as this window is used as widget (and actually segfault on Qt 5.12.3)
36 // Surface format set in BaseApplication
37
38 m_context = std::make_unique<QOpenGLContext>( this );
39 m_context->setFormat( QSurfaceFormat::defaultFormat() );
40
41 if ( !m_context->create() ) {
42 LOG( logINFO ) << "Could not create OpenGL context.";
43 QApplication::quit();
44 }
45
46 m_screenObserver = connect(
47 this->screen(), &QScreen::physicalDotsPerInchChanged, this, &WindowQt::physicalDpiChanged );
48 connect( this, &QWindow::screenChanged, this, &WindowQt::screenChanged );
49
50 // cleanup connection is set in BaseApplication
51}
52
53WindowQt::~WindowQt() {
54 // cannot deinitialize OpenGL here as it would require the call of a virtual member function
55}
56
57void WindowQt::screenChanged() {
58 disconnect( m_screenObserver );
59 m_screenObserver = connect(
60 this->screen(), &QScreen::physicalDotsPerInchChanged, this, &WindowQt::physicalDpiChanged );
61 emit dpiChanged();
62 QSize s { size().width(), size().height() };
63 QResizeEvent patchEvent { s, s };
64 resizeInternal( &patchEvent );
65}
66
67void WindowQt::physicalDpiChanged( qreal /*dpi*/ ) {
68 emit dpiChanged();
69#ifdef OS_WINDOWS
70 // on windows, no resize event generated when dpi change, force resize
71 QSize s { size().width(), size().height() };
72 QResizeEvent patchEvent { s, s };
73 resizeInternal( &patchEvent );
74#endif
75}
76
77QOpenGLContext* WindowQt::context() {
78 return m_context.get();
79}
80
81void WindowQt::makeCurrent() {
82 if ( QOpenGLContext::currentContext() != m_context.get() ) {
83 m_context->makeCurrent( this );
84 // reset counter (in case another viewer has broken our context activation counter)
85 m_contextActivationCount = 0;
86 }
87 else { ++m_contextActivationCount; }
88}
89
90void WindowQt::doneCurrent() {
91 if ( m_contextActivationCount == 0 ) { m_context->doneCurrent(); }
92 else { --m_contextActivationCount; }
93}
94
95void WindowQt::resizeEvent( QResizeEvent* event ) {
96 resizeInternal( event );
97}
98
99void WindowQt::exposeEvent( QExposeEvent* ) {
100 initialize();
101}
102
103void WindowQt::initialize() {
104 if ( !m_glInitialized.load() ) {
105 makeCurrent();
106 initializeGL();
107 doneCurrent();
108 }
109}
110
111void WindowQt::showEvent( QShowEvent* /*ev*/ ) {
112 initialize();
113}
114
115void WindowQt::resizeInternal( QResizeEvent* event ) {
116#ifdef OS_MACOS
117 // Ugly patch since Qt seems buggy on this point on macos, raise two resize call the first time.
118 if ( event->size().width() < minimumSize().width() ||
119 event->size().height() < minimumSize().height() ) {
120 QSize size { std::max( event->size().width(), minimumSize().width() ),
121 std::max( event->size().height(), minimumSize().height() ) };
122 QResizeEvent* patchEvent = new QResizeEvent( size, event->oldSize() );
123 event = patchEvent;
124 QWindow::resize( size );
125 }
126#endif
127
128 initialize();
129
130 resizeGL( event );
131}
132
134/*
135bool WindowQt::event( QEvent* event ) {
136 switch ( event->type() )
137 {
138 case QEvent::UpdateRequest:
139 // paint();
140 return true;
141
142 case QEvent::Enter:
143 enterEvent( event );
144 return true;
145
146 case QEvent::Leave:
147 leaveEvent( event );
148 return true;
149
150 default:
151 return QWindow::event( event );
152 }
153}*/
154
155bool WindowQt::initializeGL() {
156 // this simple window do not init GL
157 m_glInitialized = false;
158 return m_glInitialized;
159}
160
161void WindowQt::cleanupGL() {
162 if ( m_glInitialized.load() ) {
163 makeCurrent();
164
165 deinitializeGL();
166
167 doneCurrent();
168 }
169}
170
171void WindowQt::deinitializeGL() {}
172
173void WindowQt::resizeGL( QResizeEvent* ) {}
174
176
177void WindowQt::enterEvent( QEvent* ) {}
178
179void WindowQt::leaveEvent( QEvent* ) {}
180
181glbinding::ProcAddress WindowQt::getProcAddress( const char* name ) {
182 if ( !s_getProcAddressHelper || name == nullptr ) { return nullptr; }
183
184 const auto symbol = std::string( name );
185
186 const auto qtSymbol = QByteArray::fromStdString( symbol );
187
188 return s_getProcAddressHelper->m_context->getProcAddress( qtSymbol );
189}
190
191} // namespace Gui
192} // namespace Ra
Base class for OpenGL widgets, compatble with Qt and globjects/glbindings.
Definition WindowQt.hpp:32
T max(T... args)
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:4