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