Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqnxscreen.cpp
Go to the documentation of this file.
1// Copyright (C) 2011 - 2013 BlackBerry Limited. All rights reserved.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
6
7#include "qqnxglobal.h"
8
9#include "qqnxscreen.h"
10#include "qqnxwindow.h"
11#include "qqnxcursor.h"
12
13#include <QtCore/QThread>
14#include <QtCore/QDebug>
15#include <qpa/qwindowsysteminterface.h>
16
17#include <errno.h>
18
19#if defined(QQNX_PHYSICAL_SCREEN_WIDTH) && QQNX_PHYSICAL_SCREEN_WIDTH > 0
20 && defined(QQNX_PHYSICAL_SCREEN_HEIGHT) && QQNX_PHYSICAL_SCREEN_HEIGHT > 0
21#define QQNX_PHYSICAL_SCREEN_SIZE_DEFINED
22#elif defined(QQNX_PHYSICAL_SCREEN_WIDTH) || defined(QQNX_PHYSICAL_SCREEN_HEIGHT)
23#error Please define QQNX_PHYSICAL_SCREEN_WIDTH and QQNX_PHYSICAL_SCREEN_HEIGHT to values greater than zero
24#endif
25
26// The maximum z-order at which a foreign window will be considered
27// an underlay.
28static const int MAX_UNDERLAY_ZORDER = -1;
29
31
32Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen");
33
34static QSize determineScreenSize(screen_display_t display, bool primaryScreen) {
35 int val[2];
36
37 const int result = screen_get_display_property_iv(display, SCREEN_PROPERTY_PHYSICAL_SIZE, val);
38 Q_SCREEN_CHECKERROR(result, "Failed to query display physical size");
39 if (result != 0) {
40 return QSize(150, 90);
41 }
42
43 if (val[0] > 0 && val[1] > 0)
44 return QSize(val[0], val[1]);
45
46 qCDebug(lcQpaScreen, "QQnxScreen: screen_get_display_property_iv() reported an invalid "
47 "physical screen size (%dx%d). Falling back to QQNX_PHYSICAL_SCREEN_SIZE "
48 "environment variable.", val[0], val[1]);
49
50 const QString envPhySizeStr = qgetenv("QQNX_PHYSICAL_SCREEN_SIZE");
51 if (!envPhySizeStr.isEmpty()) {
52 const auto envPhySizeStrList = QStringView{envPhySizeStr}.split(u',');
53 const int envWidth = envPhySizeStrList.size() == 2 ? envPhySizeStrList[0].toInt() : -1;
54 const int envHeight = envPhySizeStrList.size() == 2 ? envPhySizeStrList[1].toInt() : -1;
55
56 if (envWidth <= 0 || envHeight <= 0) {
57 qWarning("QQnxScreen: The value of QQNX_PHYSICAL_SCREEN_SIZE must be in the format "
58 "\"width,height\" in mm, with width, height > 0. Defaulting to 150x90. "
59 "Example: QQNX_PHYSICAL_SCREEN_SIZE=150,90");
60 return QSize(150, 90);
61 }
62
63 return QSize(envWidth, envHeight);
64 }
65
66#if defined(QQNX_PHYSICAL_SCREEN_SIZE_DEFINED)
67 const QSize defSize(QQNX_PHYSICAL_SCREEN_WIDTH, QQNX_PHYSICAL_SCREEN_HEIGHT);
68 qWarning("QQnxScreen: QQNX_PHYSICAL_SCREEN_SIZE variable not set. Falling back to defines "
69 "QQNX_PHYSICAL_SCREEN_WIDTH/QQNX_PHYSICAL_SCREEN_HEIGHT (%dx%d)",
70 defSize.width(), defSize.height());
71 return defSize;
72#else
73 if (primaryScreen)
74 qWarning("QQnxScreen: QQNX_PHYSICAL_SCREEN_SIZE variable not set. "
75 "Could not determine physical screen size. Defaulting to 150x90.");
76 return QSize(150, 90);
77#endif
78}
79
80QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display, bool primaryScreen)
81 : m_screenContext(screenContext),
82 m_display(display),
83 m_rootWindow(0),
84 m_primaryScreen(primaryScreen),
85 m_keyboardHeight(0),
86 m_nativeOrientation(Qt::PrimaryOrientation),
87 m_coverWindow(0),
88 m_cursor(new QQnxCursor(screenContext))
89{
90 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
91 // Cache initial orientation of this display
92 int result = screen_get_display_property_iv(m_display, SCREEN_PROPERTY_ROTATION,
93 &m_initialRotation);
94 Q_SCREEN_CHECKERROR(result, "Failed to query display rotation");
95
96 m_currentRotation = m_initialRotation;
97
98 // Cache size of this display in pixels
99 int val[2];
100 Q_SCREEN_CRITICALERROR(screen_get_display_property_iv(m_display, SCREEN_PROPERTY_SIZE, val),
101 "Failed to query display size");
102
103 m_currentGeometry = m_initialGeometry = QRect(0, 0, val[0], val[1]);
104
105 char name[100];
106 Q_SCREEN_CHECKERROR(screen_get_display_property_cv(m_display, SCREEN_PROPERTY_ID_STRING, 100,
107 name), "Failed to query display name");
108 m_name = QString::fromUtf8(name);
109
110 // Cache size of this display in millimeters. We have to take care of the orientation.
111 // libscreen always reports the physical size dimensions as width and height in the
112 // native orientation. Contrary to this, QPlatformScreen::physicalSize() expects the
113 // returned dimensions to follow the current orientation.
114 const QSize screenSize = determineScreenSize(m_display, primaryScreen);
115
116 m_nativeOrientation = screenSize.width() >= screenSize.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
117
118 const int angle = screen()->angleBetween(m_nativeOrientation, orientation());
119 if (angle == 0 || angle == 180)
120 m_currentPhysicalSize = m_initialPhysicalSize = screenSize;
121 else
122 m_currentPhysicalSize = m_initialPhysicalSize = screenSize.transposed();
123}
124
126{
127 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
128 Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
129 childWindow->setScreen(0);
130
131 if (m_coverWindow)
132 m_coverWindow->setScreen(0);
133
134 delete m_cursor;
135}
136
137QPixmap QQnxScreen::grabWindow(WId window, int x, int y, int width, int height) const
138{
139 QQnxWindow *qnxWin = findWindow(reinterpret_cast<screen_window_t>(window));
140 if (!qnxWin) {
141 qWarning("grabWindow: unknown window");
142 return QPixmap();
143 }
144
145 QRect bound = qnxWin->geometry();
146
147 if (width < 0)
148 width = bound.width();
149 if (height < 0)
150 height = bound.height();
151
152 bound &= QRect(x + bound.x(), y + bound.y(), width, height);
153
154 if (bound.width() <= 0 || bound.height() <= 0) {
155 qWarning("grabWindow: size is null");
156 return QPixmap();
157 }
158
159 // Create new context, only SCREEN_DISPLAY_MANAGER_CONTEXT can read from screen
160 screen_context_t context;
161 if (screen_create_context(&context, SCREEN_DISPLAY_MANAGER_CONTEXT)) {
162 if (errno == EPERM)
163 qWarning("grabWindow: root privileges required");
164 else
165 qWarning("grabWindow: cannot create context");
166 return QPixmap();
167 }
168
169 // Find corresponding display in SCREEN_DISPLAY_MANAGER_CONTEXT
170 int count = 0;
171 screen_display_t display = 0;
172 screen_get_context_property_iv(context, SCREEN_PROPERTY_DISPLAY_COUNT, &count);
173 if (count > 0) {
174 const size_t idLen = 30;
175 char matchId[idLen];
176 char id[idLen];
177 bool found = false;
178
179 screen_display_t *displays = static_cast<screen_display_t*>
180 (calloc(count, sizeof(screen_display_t)));
181 screen_get_context_property_pv(context, SCREEN_PROPERTY_DISPLAYS, (void **)displays);
182 screen_get_display_property_cv(m_display, SCREEN_PROPERTY_ID_STRING, idLen, matchId);
183
184 while (count && !found) {
185 --count;
186 screen_get_display_property_cv(displays[count], SCREEN_PROPERTY_ID_STRING, idLen, id);
187 found = !strncmp(id, matchId, idLen);
188 }
189
190 if (found)
191 display = displays[count];
192
193 free(displays);
194 }
195
196 // Create screen and Qt pixmap
197 screen_pixmap_t pixmap;
198 QPixmap result;
199 if (display && !screen_create_pixmap(&pixmap, context)) {
200 screen_buffer_t buffer;
201 void *pointer;
202 int stride;
203 const int rect[4] = { bound.x(), bound.y(), bound.width(), bound.height() };
204
205 int val = SCREEN_USAGE_READ | SCREEN_USAGE_NATIVE;
206 screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_USAGE, &val);
207 val = SCREEN_FORMAT_RGBA8888;
208 screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_FORMAT, &val);
209
210 int err = screen_set_pixmap_property_iv(pixmap, SCREEN_PROPERTY_BUFFER_SIZE, rect+2);
211 err = err || screen_create_pixmap_buffer(pixmap);
212 err = err || screen_get_pixmap_property_pv(pixmap, SCREEN_PROPERTY_RENDER_BUFFERS,
213 reinterpret_cast<void**>(&buffer));
214 err = err || screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER, &pointer);
215 err = err || screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE, &stride);
216 err = err || screen_read_display(display, buffer, 1, rect, 0);
217
218 if (!err) {
219 const QImage img(static_cast<unsigned char*>(pointer),
220 bound.width(), bound.height(), stride, QImage::Format_ARGB32);
221 result = QPixmap::fromImage(img);
222 } else {
223 qWarning("grabWindow: capture error");
224 }
225 screen_destroy_pixmap(pixmap);
226 } else {
227 qWarning("grabWindow: display/pixmap error ");
228 }
229 screen_destroy_context(context);
230
231 return result;
232}
233
234static int defaultDepth()
235{
236 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
237 static int defaultDepth = 0;
238 if (defaultDepth == 0) {
239 // check if display depth was specified in environment variable;
240 // use default value if no valid value found
241 defaultDepth = qEnvironmentVariableIntValue("QQNX_DISPLAY_DEPTH");
242 if (defaultDepth != 16 && defaultDepth != 32)
243 defaultDepth = 32;
244 }
245 return defaultDepth;
246}
247
249{
250 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
251 // available geometry = total geometry - keyboard
252 return QRect(m_currentGeometry.x(), m_currentGeometry.y(),
253 m_currentGeometry.width(), m_currentGeometry.height() - m_keyboardHeight);
254}
255
256int QQnxScreen::depth() const
257{
258 return defaultDepth();
259}
260
262{
263 screen_display_mode_t displayMode;
264 int result = screen_get_display_property_pv(m_display, SCREEN_PROPERTY_MODE, reinterpret_cast<void **>(&displayMode));
265 // Screen shouldn't really return 0 but it does so default to 60 or things break.
266 if (result != 0 || displayMode.refresh == 0) {
267 qWarning("QQnxScreen: Failed to query screen mode. Using default value of 60Hz");
268 return 60.0;
269 }
270 qCDebug(lcQpaScreen, "screen mode:\n"
271 " width = %u\n"
272 " height = %u\n"
273 " refresh = %u\n"
274 " interlaced = %u",
275 uint(displayMode.width), uint(displayMode.height), uint(displayMode.refresh), uint(displayMode.interlaced));
276 return static_cast<qreal>(displayMode.refresh);
277}
278
280{
281 return m_nativeOrientation;
282}
283
285{
286 Qt::ScreenOrientation orient;
287 if (m_nativeOrientation == Qt::LandscapeOrientation) {
288 // Landscape devices e.g. PlayBook
289 if (m_currentRotation == 0)
290 orient = Qt::LandscapeOrientation;
291 else if (m_currentRotation == 90)
292 orient = Qt::PortraitOrientation;
293 else if (m_currentRotation == 180)
294 orient = Qt::InvertedLandscapeOrientation;
295 else
296 orient = Qt::InvertedPortraitOrientation;
297 } else {
298 // Portrait devices e.g. Phones
299 // ###TODO Check these on an actual phone device
300 if (m_currentRotation == 0)
301 orient = Qt::PortraitOrientation;
302 else if (m_currentRotation == 90)
303 orient = Qt::LandscapeOrientation;
304 else if (m_currentRotation == 180)
305 orient = Qt::InvertedPortraitOrientation;
306 else
307 orient = Qt::InvertedLandscapeOrientation;
308 }
309 qCDebug(lcQpaScreen) << Q_FUNC_INFO << "Orientation =" << orient;
310 return orient;
311}
312
313QWindow *QQnxScreen::topLevelAt(const QPoint &point) const
314{
315 for (auto it = m_childWindows.rbegin(), end = m_childWindows.rend(); it != end; ++it) {
316 QWindow *win = (*it)->window();
317 if (win->geometry().contains(point))
318 return win;
319 }
320 return 0;
321}
322
323/*!
324 Check if the supplied angles are perpendicular to each other.
325*/
326static bool isOrthogonal(int angle1, int angle2)
327{
328 return ((angle1 - angle2) % 180) != 0;
329}
330
331void QQnxScreen::setRotation(int rotation)
332{
333 qCDebug(lcQpaScreen) << Q_FUNC_INFO << "orientation =" << rotation;
334 // Check if rotation changed
335 // We only want to rotate if we are the primary screen
336 if (m_currentRotation != rotation && isPrimaryScreen()) {
337 // Update rotation of root window
338 if (rootWindow())
340
341 const QRect previousScreenGeometry = geometry();
342
343 // Swap dimensions if we've rotated 90 or 270 from initial orientation
344 if (isOrthogonal(m_initialRotation, rotation)) {
345 m_currentGeometry = QRect(0, 0, m_initialGeometry.height(), m_initialGeometry.width());
346 m_currentPhysicalSize = QSize(m_initialPhysicalSize.height(), m_initialPhysicalSize.width());
347 } else {
348 m_currentGeometry = QRect(0, 0, m_initialGeometry.width(), m_initialGeometry.height());
349 m_currentPhysicalSize = m_initialPhysicalSize;
350 }
351
352 // Resize root window if we've rotated 90 or 270 from previous orientation
353 if (isOrthogonal(m_currentRotation, rotation)) {
354 qCDebug(lcQpaScreen) << Q_FUNC_INFO << "resize, size =" << m_currentGeometry.size();
355 if (rootWindow())
356 rootWindow()->setGeometry(QRect(QPoint(0,0), m_currentGeometry.size()));
357
358 resizeWindows(previousScreenGeometry);
359 } else {
360 // TODO: Find one global place to flush display updates
361 // Force immediate display update if no geometry changes required
362 screen_flush_context(nativeContext(), 0);
363 }
364
365 // Save new rotation
366 m_currentRotation = rotation;
367
368 // TODO: check if other screens are supposed to rotate as well and/or whether this depends
369 // on if clone mode is being used.
370 // Rotating only the primary screen is what we had in the navigator event handler before refactoring
371 if (m_primaryScreen) {
372 QWindowSystemInterface::handleScreenOrientationChange(screen(), orientation());
373 QWindowSystemInterface::handleScreenGeometryChange(screen(), m_currentGeometry, availableGeometry());
374 }
375
376 // Flush everything, so that the windows rotations are applied properly.
377 // Needed for non-maximized windows
378 screen_flush_context( m_screenContext, 0 );
379 }
380}
381
382/*!
383 Resize the given window proportionally to the screen geometry
384*/
385void QQnxScreen::resizeNativeWidgetWindow(QQnxWindow *w, const QRect &previousScreenGeometry) const
386{
387 const qreal relativeX = static_cast<qreal>(w->geometry().topLeft().x()) / previousScreenGeometry.width();
388 const qreal relativeY = static_cast<qreal>(w->geometry().topLeft().y()) / previousScreenGeometry.height();
389 const qreal relativeWidth = static_cast<qreal>(w->geometry().width()) / previousScreenGeometry.width();
390 const qreal relativeHeight = static_cast<qreal>(w->geometry().height()) / previousScreenGeometry.height();
391
392 const QRect windowGeometry(relativeX * geometry().width(), relativeY * geometry().height(),
393 relativeWidth * geometry().width(), relativeHeight * geometry().height());
394
395 w->setGeometry(windowGeometry);
396}
397
398/*!
399 Resize the given window to fit the screen geometry
400*/
401void QQnxScreen::resizeTopLevelWindow(QQnxWindow *w, const QRect &previousScreenGeometry) const
402{
403 QRect windowGeometry = w->geometry();
404
405 const qreal relativeCenterX = static_cast<qreal>(w->geometry().center().x()) / previousScreenGeometry.width();
406 const qreal relativeCenterY = static_cast<qreal>(w->geometry().center().y()) / previousScreenGeometry.height();
407 const QPoint newCenter(relativeCenterX * geometry().width(), relativeCenterY * geometry().height());
408
409 windowGeometry.moveCenter(newCenter);
410
411 // adjust center position in case the window
412 // is clipped
413 if (!geometry().contains(windowGeometry)) {
414 const int x1 = windowGeometry.x();
415 const int y1 = windowGeometry.y();
416 const int x2 = x1 + windowGeometry.width();
417 const int y2 = y1 + windowGeometry.height();
418
419 if (x1 < 0) {
420 const int centerX = qMin(qAbs(x1) + windowGeometry.center().x(),
421 geometry().center().x());
422
423 windowGeometry.moveCenter(QPoint(centerX, windowGeometry.center().y()));
424 }
425
426 if (y1 < 0) {
427 const int centerY = qMin(qAbs(y1) + windowGeometry.center().y(),
428 geometry().center().y());
429
430 windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), centerY));
431 }
432
433 if (x2 > geometry().width()) {
434 const int centerX = qMax(windowGeometry.center().x() - (x2 - geometry().width()),
435 geometry().center().x());
436
437 windowGeometry.moveCenter(QPoint(centerX, windowGeometry.center().y()));
438 }
439
440 if (y2 > geometry().height()) {
441 const int centerY = qMax(windowGeometry.center().y() - (y2 - geometry().height()),
442 geometry().center().y());
443
444 windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), centerY));
445 }
446 }
447
448 // at this point, if the window is still clipped,
449 // it means that it's too big to fit on the screen,
450 // so we need to proportionally shrink it
451 if (!geometry().contains(windowGeometry)) {
452 QSize newSize = windowGeometry.size();
453 newSize.scale(geometry().size(), Qt::KeepAspectRatio);
454 windowGeometry.setSize(newSize);
455
456 if (windowGeometry.x() < 0)
457 windowGeometry.moveCenter(QPoint(geometry().center().x(), windowGeometry.center().y()));
458
459 if (windowGeometry.y() < 0)
460 windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), geometry().center().y()));
461 }
462
463 w->setGeometry(windowGeometry);
464}
465
466/*!
467 Adjust windows to the new screen geometry.
468*/
469void QQnxScreen::resizeWindows(const QRect &previousScreenGeometry)
470{
471 resizeMaximizedWindows();
472
473 Q_FOREACH (QQnxWindow *w, m_childWindows) {
474
475 if (w->window()->windowState() & Qt::WindowFullScreen || w->window()->windowState() & Qt::WindowMaximized)
476 continue;
477
478 if (w->parent()) {
479 // This is a native (non-alien) widget window
480 resizeNativeWidgetWindow(w, previousScreenGeometry);
481 } else {
482 // This is a toplevel window
483 resizeTopLevelWindow(w, previousScreenGeometry);
484 }
485 }
486}
487
488QQnxWindow *QQnxScreen::findWindow(screen_window_t windowHandle) const
489{
490 Q_FOREACH (QQnxWindow *window, m_childWindows) {
491 QQnxWindow * const result = window->findWindow(windowHandle);
492 if (result)
493 return result;
494 }
495
496 return 0;
497}
498
500{
501 qCDebug(lcQpaScreen) << Q_FUNC_INFO << "Window =" << window;
502
503 if (m_childWindows.contains(window))
504 return;
505
506 if (window->window()->type() != Qt::CoverWindow) {
507 m_childWindows.push_back(window);
509 }
510}
511
513{
514 qCDebug(lcQpaScreen) << Q_FUNC_INFO << "Window =" << window;
515
516 if (window != m_coverWindow) {
517 const int numWindowsRemoved = m_childWindows.removeAll(window);
518 if (window == m_rootWindow) //We just removed the root window
519 m_rootWindow = 0; //TODO we need a new root window ;)
520 if (numWindowsRemoved > 0)
522 } else {
523 m_coverWindow = 0;
524 }
525}
526
528{
529 qCDebug(lcQpaScreen) << Q_FUNC_INFO << "Window =" << window;
530
531 if (window != m_coverWindow) {
532 removeWindow(window);
533 m_childWindows.push_back(window);
534 }
535}
536
538{
539 qCDebug(lcQpaScreen) << Q_FUNC_INFO << "Window =" << window;
540
541 if (window != m_coverWindow) {
542 removeWindow(window);
543 m_childWindows.push_front(window);
544 }
545}
546
548{
549 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
550
551 QList<QQnxWindow*>::const_iterator it;
552 int result;
553 int topZorder = 0;
554
555 errno = 0;
556 if (rootWindow()) {
557 result = screen_get_window_property_iv(rootWindow()->nativeHandle(), SCREEN_PROPERTY_ZORDER, &topZorder);
558 if (result != 0) { //This can happen if we use winId in QWidgets
559 topZorder = 10;
560 qWarning("QQnxScreen: failed to query root window z-order, errno=%d", errno);
561 }
562 } else {
563 topZorder = 0; //We do not need z ordering on the secondary screen, because only one window
564 //is supported there
565 }
566
567 topZorder++; // root window has the lowest z-order in the windowgroup
568
569 int underlayZorder = -1;
570 // Underlays sit immediately above the root window in the z-ordering
571 Q_FOREACH (screen_window_t underlay, m_underlays) {
572 // Do nothing when this fails. This can happen if we have stale windows in m_underlays,
573 // which in turn can happen because a window was removed but we didn't get a notification
574 // yet.
575 screen_set_window_property_iv(underlay, SCREEN_PROPERTY_ZORDER, &underlayZorder);
576 underlayZorder--;
577 }
578
579 // Normal Qt windows come next above the root window z-ordering
580 for (it = m_childWindows.constBegin(); it != m_childWindows.constEnd(); ++it)
581 (*it)->updateZorder(topZorder);
582
583 // Finally overlays sit above all else in the z-ordering
584 Q_FOREACH (screen_window_t overlay, m_overlays) {
585 // No error handling, see underlay logic above
586 screen_set_window_property_iv(overlay, SCREEN_PROPERTY_ZORDER, &topZorder);
587 topZorder++;
588 }
589
590 // After a hierarchy update, we need to force a flush on all screens.
591 // Right now, all screens share a context.
592 screen_flush_context(m_screenContext, 0);
593}
594
596{
597 if (!m_primaryScreen)
598 return;
599
600 bool ok = false;
601 const int rotation = qEnvironmentVariableIntValue("ORIENTATION", &ok);
602
603 if (ok)
604 setRotation(rotation);
605}
606
608{
609 return m_cursor;
610}
611
612void QQnxScreen::keyboardHeightChanged(int height)
613{
614 if (height == m_keyboardHeight)
615 return;
616
617 m_keyboardHeight = height;
618
619 QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
620}
621
622void QQnxScreen::addOverlayWindow(screen_window_t window)
623{
624 m_overlays.append(window);
626}
627
628void QQnxScreen::addUnderlayWindow(screen_window_t window)
629{
630 m_underlays.append(window);
632}
633
634void QQnxScreen::removeOverlayOrUnderlayWindow(screen_window_t window)
635{
636 const int numRemoved = m_overlays.removeAll(window) + m_underlays.removeAll(window);
637 if (numRemoved > 0) {
639 Q_EMIT foreignWindowClosed(window);
640 }
641}
642
643void QQnxScreen::newWindowCreated(void *window)
644{
645 Q_ASSERT(thread() == QThread::currentThread());
646 const screen_window_t windowHandle = reinterpret_cast<screen_window_t>(window);
647 screen_display_t display = 0;
648 if (screen_get_window_property_pv(windowHandle, SCREEN_PROPERTY_DISPLAY, (void**)&display) != 0) {
649 qWarning("QQnx: Failed to get screen for window, errno=%d", errno);
650 return;
651 }
652
653 int zorder;
654 if (screen_get_window_property_iv(windowHandle, SCREEN_PROPERTY_ZORDER, &zorder) != 0) {
655 qWarning("QQnx: Failed to get z-order for window, errno=%d", errno);
656 zorder = 0;
657 }
658
659 char windowNameBuffer[256] = { 0 };
660 QByteArray windowName;
661
662 if (screen_get_window_property_cv(windowHandle, SCREEN_PROPERTY_ID_STRING,
663 sizeof(windowNameBuffer) - 1, windowNameBuffer) != 0) {
664 qWarning("QQnx: Failed to get id for window, errno=%d", errno);
665 }
666
667 windowName = QByteArray(windowNameBuffer);
668
669 if (display != nativeDisplay())
670 return;
671
672 // A window was created on this screen. If we don't know about this window yet, it means
673 // it was not created by Qt, but by some foreign library.
674 //
675 // Treat all foreign windows as overlays or underlays. A window will
676 // be treated as an underlay if its Z-order is less or equal than
677 // MAX_UNDERLAY_ZORDER. Otherwise, it will be treated as an overlay.
678 if (findWindow(windowHandle))
679 return;
680
681 if (zorder <= MAX_UNDERLAY_ZORDER)
682 addUnderlayWindow(windowHandle);
683 else
684 addOverlayWindow(windowHandle);
685
686 Q_EMIT foreignWindowCreated(windowHandle);
687}
688
689void QQnxScreen::windowClosed(void *window)
690{
691 Q_ASSERT(thread() == QThread::currentThread());
692 const screen_window_t windowHandle = reinterpret_cast<screen_window_t>(window);
693
694 removeOverlayOrUnderlayWindow(windowHandle);
695}
696
697void QQnxScreen::windowGroupStateChanged(const QByteArray &id, Qt::WindowState state)
698{
699 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
700
701 if (!rootWindow() || id != rootWindow()->groupName())
702 return;
703
704 QWindow * const window = rootWindow()->window();
705
706 if (!window)
707 return;
708
709 QWindowSystemInterface::handleWindowStateChanged(window, state);
710}
711
712void QQnxScreen::activateWindowGroup(const QByteArray &id)
713{
714 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
715
716 if (!rootWindow() || id != rootWindow()->groupName())
717 return;
718
719 QWindow * const window = rootWindow()->window();
720
721 if (!window)
722 return;
723
724 Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
725 childWindow->setExposed(true);
726
727 if (m_coverWindow)
728 m_coverWindow->setExposed(false);
729}
730
731void QQnxScreen::deactivateWindowGroup(const QByteArray &id)
732{
733 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
734
735 if (!rootWindow() || id != rootWindow()->groupName())
736 return;
737
738 if (m_coverWindow)
739 m_coverWindow->setExposed(true);
740
741 Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
742 childWindow->setExposed(false);
743}
744
746{
747 return m_rootWindow;
748}
749
751{
752 // Optionally disable the screen power save
753 bool ok = false;
754 const int disablePowerSave = qEnvironmentVariableIntValue("QQNX_DISABLE_POWER_SAVE", &ok);
755 if (ok && disablePowerSave) {
756 const int mode = SCREEN_IDLE_MODE_KEEP_AWAKE;
757 int result = screen_set_window_property_iv(window->nativeHandle(), SCREEN_PROPERTY_IDLE_MODE, &mode);
758 if (result != 0)
759 qWarning("QQnxRootWindow: failed to disable power saving mode");
760 }
761 m_rootWindow = window;
762}
763
764QT_END_NAMESPACE
void windowClosed(void *window)
Qt::ScreenOrientation nativeOrientation() const override
Reimplement this function in subclass to return the native orientation of the screen,...
QPlatformCursor * cursor() const override
Reimplement this function in subclass to return the cursor of the screen.
Qt::ScreenOrientation orientation() const override
Reimplement this function in subclass to return the current orientation of the screen,...
QWindow * topLevelAt(const QPoint &point) const override
Return the given top level window for a given position.
void lowerWindow(QQnxWindow *window)
bool isPrimaryScreen() const
Definition qqnxscreen.h:60
void raiseWindow(QQnxWindow *window)
void activateWindowGroup(const QByteArray &id)
void removeWindow(QQnxWindow *child)
void addWindow(QQnxWindow *child)
QRect availableGeometry() const override
Reimplement in subclass to return the pixel geometry of the available space This normally is the desk...
void deactivateWindowGroup(const QByteArray &id)
QPixmap grabWindow(WId window, int x, int y, int width, int height) const override
This function is called when Qt needs to be able to grab the content of a window.
QQnxWindow * findWindow(screen_window_t windowHandle) const
void setRootWindow(QQnxWindow *)
int depth() const override
Reimplement in subclass to return current depth of the screen.
void adjustOrientation()
QQnxWindow * rootWindow() const
void newWindowCreated(void *window)
qreal refreshRate() const override
Reimplement this function in subclass to return the vertical refresh rate of the screen,...
void updateHierarchy()
void windowGroupStateChanged(const QByteArray &id, Qt::WindowState state)
The QQnxWindow is the base class of the various classes used as instances of QPlatformWindow in the Q...
Definition qqnxwindow.h:32
void setExposed(bool exposed)
void setScreen(QQnxScreen *platformScreen)
void setRotation(int rotation)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
#define Q_SCREEN_CRITICALERROR(x, message)
Definition qqnxglobal.h:20
#define Q_SCREEN_CHECKERROR(x, message)
Definition qqnxglobal.h:17
static const int MAX_UNDERLAY_ZORDER
static bool isOrthogonal(int angle1, int angle2)
Check if the supplied angles are perpendicular to each other.
static int defaultDepth()
static QSize determineScreenSize(screen_display_t display, bool primaryScreen)