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