NDEVR
API Documentation
WindowContainer.h
1#pragma once
2#include <QWindow>
3#include <QTimer>
4#include <QPainter>
5#include <QHBoxLayout>
6#include <QResizeEvent>
7#include <QFrame>
8#if defined(ANDROID)
9 #define FORCE_HIDE_WINDOW 0
10 #define NDEVR_SPECIAL_GRAPHICS_WINDOW 1
11 #define USE_WINDOW_WIDGET 0
12 //typedef QAbstractScrollArea BaseWindowContainer;
13 typedef QFrame BaseWindowContainer;
14#elif defined(Q_OS_WASM)
15 #include <QFrame>
16 #define FORCE_HIDE_WINDOW 0
17 #define USE_WINDOW_WIDGET 0
18 #define NDEVR_SPECIAL_GRAPHICS_WINDOW 0
19 typedef QFrame BaseWindowContainer;
20#else
21 #include <QFrame>
22 #define FORCE_HIDE_WINDOW 0
23 #define USE_WINDOW_WIDGET 0
24 #define NDEVR_SPECIAL_GRAPHICS_WINDOW 1
25 typedef QFrame BaseWindowContainer;
26#endif
27
28namespace NDEVR
29{
36 class WindowContainer : public BaseWindowContainer
37 {
38 public:
41 WindowContainer(QWidget* parent = nullptr)
42 : BaseWindowContainer(parent)
43 , m_location_timer(new QTimer(this))
45 , m_window(nullptr)
46 , m_container(nullptr)
47 {
48/*#ifdef ANDROID
49 connect(m_location_timer, &QTimer::timeout, this, [this] {
50 updateSize();
51 });
52 m_location_timer->setInterval(1);
53 m_location_timer->setSingleShot(false);
54 m_location_timer->start();
55#endif*/
56 //setAttribute(Qt::WA_NoSystemBackground);
57 //setAttribute(Qt::WA_OpaquePaintEvent);
58 //setAutoFillBackground(true);
59 }
61 {
62 if (m_window)
63 m_window->setVisible(QWindow::Visibility::Hidden);
64 }
67 static Qt::WindowFlags windowFlags()
68 {
69 #if USE_WINDOW_WIDGET
70 return Qt::WindowFlags();//Qt::WindowFlags(Qt::Window | Qt::WindowDoesNotAcceptFocus | Qt::WindowTransparentForInput | Qt::WindowStaysOnBottomHint);
71 #else
72 #if defined(ANDROID)
73 return Qt::WindowFlags();//Qt::WindowDoesNotAcceptFocus | Qt::WindowTransparentForInput);
74 #elif defined(Q_OS_WASM)
75 return Qt::WindowFlags(Qt::WindowStaysOnBottomHint | Qt::Widget | Qt::WindowDoesNotAcceptFocus);
76 #else
77 return Qt::WindowFlags();// Qt::WindowFlags(Qt::Widget | Qt::WindowDoesNotAcceptFocus | Qt::WindowTransparentForInput);
78 #endif
79 #endif
80 }
81
84 QPoint windowOffset() const
85 {
86#if USE_WINDOW_WIDGET
87 return mapToGlobal(QPoint(0, 0));
88#else
89 return QPoint(0,0);
90#endif
91 }
92
94 void setWidget(QWidget* window)
95 {
96 if (m_container == window)
97 return;
98 if (m_container)
99 {
100 m_container->deleteLater();
101 m_container = nullptr;
102 }
103 m_window = nullptr;
104 m_container = window;
105 if (m_container)
106 {
107#if NDEVR_SPECIAL_GRAPHICS_WINDOW
108 QHBoxLayout* layout = new QHBoxLayout();
109 layout->setContentsMargins(0, 0, 0, 0);
110#endif
111 //m_container->setAttribute(Qt::WA_NoSystemBackground);
112 m_container->setParent(this);
113 m_container->setMouseTracking(true);
114#if NDEVR_SPECIAL_GRAPHICS_WINDOW
115 layout->addWidget(m_container);
116 setLayout(layout);
117#endif
118 }
119 }
120
122 void setWindow(QWindow* window)
123 {
124 if (window == m_window)
125 return;
126 if (m_container)
127 {
128 m_container->deleteLater();
129 m_container = nullptr;
130 }
131 m_window = window;
132 if (m_window)
133 {
134 m_window->setVisible(QWindow::Visibility::Hidden);
135#if NDEVR_SPECIAL_GRAPHICS_WINDOW
136 QHBoxLayout* layout = new QHBoxLayout();
137 layout->setContentsMargins(0, 0, 0, 0);
138#endif
139 m_container = QWidget::createWindowContainer(m_window, this, windowFlags());
140 //m_container->setAttribute(Qt::WA_ShowWithoutActivating);
141 //m_container->installEventFilter(this);
142 m_container->setMouseTracking(true);
143#if NDEVR_SPECIAL_GRAPHICS_WINDOW
144 layout->addWidget(m_container);
145 setLayout(layout);
146#endif
147
148 //m_container->setEnabled(false);
149 //m_window->resize(size());
150 }
151 }
152
154 {
155#if !NDEVR_SPECIAL_GRAPHICS_WINDOW
156 /*QTimer::singleShot(1000, this, [this]
157 {
158 QWidget* widget = new QWidget(this, windowFlags());
159 widget->setAttribute(Qt::WidgetAttribute::WA_PaintOnScreen, false);
160 widget->show();
161 qApp->setActiveWindow(this);
162 widget->deleteLater();
163 });*/
164#endif
165 }
166
167 void paintEvent(QPaintEvent* event) override
168 {
169#if !NDEVR_SPECIAL_GRAPHICS_WINDOW
170 updateSize();
171#endif
172 /*QSize new_size = size();
173 QSize old_size = QSize(0, 0);// window()->size();
174
175 if (new_size.width() == 0 || new_size.height() == 0)
176 return;
177 if (old_size.width() < new_size.width() || old_size.height() < new_size.height())
178 {
179
180 QRect current_size_x(QPoint(old_size.width(), 0), QSize(new_size.width() - old_size.width(), height()));
181 QRect current_size_y(QPoint(0, old_size.height()), QSize(new_size.width(), new_size.height() - old_size.height()));
182 QPalette pal = palette();
183
184 QPainter painter(this);
185 QRegion region;
186 if (current_size_x.size().width() > 0)
187 region += current_size_x;
188 if (current_size_y.size().height() > 0)
189 region += current_size_y;
190 if (current_size_x.size().width() > 0)
191 painter.fillRect(current_size_x, pal.color(backgroundRole()));
192 if (current_size_y.size().height() > 0)
193 painter.fillRect(current_size_y, pal.color(backgroundRole()));
194 painter.end();
195 m_last_paint_size = size();
196 }*/
197 BaseWindowContainer::paintEvent(event);
198 }
199
201 virtual void updateSize()
202 {
203#if !NDEVR_SPECIAL_GRAPHICS_WINDOW
204 if(isVisible())
205 {
206 QRect rect = QRect(windowOffset(), size());
207 if (m_container && m_container->geometry() != rect)
208 {
209 m_container->setGeometry(rect);
210 //m_window->resize(size());
211 }
212 }
213 else
214 {
215 if(m_container)
216 {
217 m_container->setVisible(false);
218 m_container->resize(1,1);
219 }
220 }
221#endif
222 }
223
224 bool event(QEvent* event) override
225 {
226 QEvent::Type event_type = event->type();
227 switch (event_type)
228 {
229 case QEvent::Show:
230 if (m_container)
231 m_container->setVisible(true);
232 if (m_window)
233 m_window->setVisibility(QWindow::Visibility::Windowed);
234 break;
235 case QEvent::Hide:
236 if (m_container)
237 m_container->setVisible(false);
238 if (m_window)
239 m_window->setVisibility(QWindow::Visibility::Hidden);
240 break;
241 default:
242 break;
243 }
246 //return false;
247 return BaseWindowContainer::event(event);
248 }
249
251 void setEventForwarder(const std::function<bool(QEvent * event)>& forwarder)
252 {
253 m_event_forwarder = forwarder;
254 }
255#if defined(ANDROID)
258 void setVisible(bool visible) override
259 {
260 BaseWindowContainer::setVisible(visible);
261 if (m_container)
262 m_container->setVisible(visible);
263 if (m_window)
264 m_window->setVisible(visible ? QWindow::Visibility::Windowed
265 : QWindow::Visibility::Hidden);
266 }
267
269 void resizeEvent(QResizeEvent* resize_event) override
270 {
271 BaseWindowContainer::resizeEvent(resize_event);
272 QSize s = resize_event->size();
273 if (m_container)
274 m_container->resize(s);
275 if (m_window)
276 m_window->resize(s);
277 }
278#endif
279 protected:
280 std::function<bool(QEvent * event)> m_event_forwarder;
283 QWindow* m_window;
284 QWidget* m_container;
285 };
286}
A (hacky) class for storing a window into a container.
QPoint windowOffset() const
Returns the global position offset for the embedded window.
void setWindow(QWindow *window)
Sets a QWindow as the contained window, wrapping it in a QWidget container.
bool event(QEvent *event) override
Handles show/hide events and forwards all events to the optional event forwarder.
QWindow * m_window
The embedded QWindow, if set via setWindow().
static Qt::WindowFlags windowFlags()
Returns the platform-specific window flags for the embedded window.
void setWidget(QWidget *window)
Sets a QWidget as the contained child widget.
virtual void updateSize()
Updates the geometry of the embedded container to match this widget's size and position.
QSize m_last_paint_size
The size at the last paint event, used for incremental repainting.
QWidget * m_container
The QWidget wrapping the embedded window or set directly via setWidget().
WindowContainer(QWidget *parent=nullptr)
Constructs a WindowContainer with an optional parent.
void visibleHack()
Workaround to force proper visibility of the embedded window on some platforms.
QTimer * m_location_timer
Timer used on some platforms to poll and update window position.
void paintEvent(QPaintEvent *event) override
Handles paint events, updating the embedded window size on non-special-window platforms.
std::function< bool(QEvent *event)> m_event_forwarder
Optional callback that receives all events for custom handling.
void setEventForwarder(const std::function< bool(QEvent *event)> &forwarder)
Sets a callback function that receives all events for custom processing.
The primary namespace for the NDEVR SDK.