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