13#include <QtCore/QThread>
14#include <QtCore/QDebug>
15#include <qpa/qwindowsysteminterface.h>
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
37 const int result = screen_get_display_property_iv(display, SCREEN_PROPERTY_PHYSICAL_SIZE, val);
40 return QSize(150, 90);
43 if (val[0] > 0 && val[1] > 0)
44 return QSize(val[0], val[1]);
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]);
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;
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);
63 return QSize(envWidth, envHeight);
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());
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);
80QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display,
bool primaryScreen)
81 : m_screenContext(screenContext),
84 m_primaryScreen(primaryScreen),
87 m_nativeOrientation(Qt::PrimaryOrientation),
89 m_cursor(
new QQnxCursor(screenContext))
91 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
93 Q_SCREEN_CHECKERROR(screen_get_display_property_iv(m_display, SCREEN_PROPERTY_ID, &m_displayId),
94 "Failed to query display id");
97 int result = screen_get_display_property_iv(m_display, SCREEN_PROPERTY_ROTATION,
101 m_currentRotation = m_initialRotation;
106 "Failed to query display size");
108 m_currentGeometry = m_initialGeometry = QRect(0, 0, val[0], val[1]);
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);
119 const QSize screenSize = determineScreenSize(m_display, primaryScreen);
121 m_nativeOrientation = screenSize.width() >= screenSize.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
123 const int angle = screen()->angleBetween(m_nativeOrientation, orientation());
124 if (angle == 0 || angle == 180)
125 m_currentPhysicalSize = m_initialPhysicalSize = screenSize;
127 m_currentPhysicalSize = m_initialPhysicalSize = screenSize.transposed();
132 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
133 Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
134 childWindow->setScreen(0);
144 QQnxWindow *qnxWin = findWindow(
reinterpret_cast<screen_window_t>(window));
146 qWarning(
"grabWindow: unknown window");
150 QRect bound = qnxWin->geometry();
153 width = bound.width();
155 height = bound.height();
157 bound &= QRect(x + bound.x(), y + bound.y(), width, height);
159 if (bound.width() <= 0 || bound.height() <= 0) {
160 qWarning(
"grabWindow: size is null");
165 screen_context_t context;
166 if (screen_create_context(&context, SCREEN_DISPLAY_MANAGER_CONTEXT)) {
168 qWarning(
"grabWindow: root privileges required");
170 qWarning(
"grabWindow: cannot create context");
176 screen_display_t display = 0;
177 screen_get_context_property_iv(context, SCREEN_PROPERTY_DISPLAY_COUNT, &count);
179 const size_t idLen = 30;
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);
189 while (count && !found) {
191 screen_get_display_property_cv(displays[count], SCREEN_PROPERTY_ID_STRING, idLen, id);
192 found = !strncmp(id, matchId, idLen);
196 display = displays[count];
202 screen_pixmap_t pixmap;
204 if (display && !screen_create_pixmap(&pixmap, context)) {
205 screen_buffer_t buffer;
208 const int rect[4] = { bound.x(), bound.y(), bound.width(), bound.height() };
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);
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);
224 const QImage img(
static_cast<
unsigned char*>(pointer),
225 bound.width(), bound.height(), stride, QImage::Format_ARGB32);
226 result = QPixmap::fromImage(img);
228 qWarning(
"grabWindow: capture error");
230 screen_destroy_pixmap(pixmap);
232 qWarning(
"grabWindow: display/pixmap error ");
234 screen_destroy_context(context);
241 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
242 static int defaultDepth = 0;
243 if (defaultDepth == 0) {
246 defaultDepth = qEnvironmentVariableIntValue(
"QQNX_DISPLAY_DEPTH");
247 if (defaultDepth != 16 && defaultDepth != 32)
255 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
257 return QRect(m_currentGeometry.x(), m_currentGeometry.y(),
258 m_currentGeometry.width(), m_currentGeometry.height() - m_keyboardHeight);
268 screen_display_mode_t displayMode;
269 int result = screen_get_display_property_pv(m_display, SCREEN_PROPERTY_MODE,
reinterpret_cast<
void **>(&displayMode));
271 if (result != 0 || displayMode.refresh == 0) {
272 qWarning(
"QQnxScreen: Failed to query screen mode. Using default value of 60Hz");
275 qCDebug(lcQpaScreen,
"screen mode:\n"
280 uint(displayMode.width), uint(displayMode.height), uint(displayMode.refresh), uint(displayMode.interlaced));
281 return static_cast<qreal>(displayMode.refresh);
286 return m_nativeOrientation;
291 Qt::ScreenOrientation orient;
292 if (m_nativeOrientation == Qt::LandscapeOrientation) {
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;
301 orient = Qt::InvertedPortraitOrientation;
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;
312 orient = Qt::InvertedLandscapeOrientation;
314 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"Orientation =" << orient;
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))
329
330
333 return ((angle1 - angle2) % 180) != 0;
338 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"orientation =" << rotation;
346 const QRect previousScreenGeometry = geometry();
350 m_currentGeometry = QRect(0, 0, m_initialGeometry.height(), m_initialGeometry.width());
351 m_currentPhysicalSize = QSize(m_initialPhysicalSize.height(), m_initialPhysicalSize.width());
353 m_currentGeometry = QRect(0, 0, m_initialGeometry.width(), m_initialGeometry.height());
354 m_currentPhysicalSize = m_initialPhysicalSize;
359 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"resize, size =" << m_currentGeometry.size();
361 rootWindow()->setGeometry(QRect(QPoint(0,0), m_currentGeometry.size()));
363 resizeWindows(previousScreenGeometry);
367 screen_flush_context(nativeContext(), 0);
371 m_currentRotation = rotation;
376 if (m_primaryScreen) {
377 QWindowSystemInterface::handleScreenOrientationChange(screen(), orientation());
378 QWindowSystemInterface::handleScreenGeometryChange(screen(), m_currentGeometry, availableGeometry());
383 screen_flush_context( m_screenContext, 0 );
388
389
390void QQnxScreen::resizeNativeWidgetWindow(
QQnxWindow *w,
const QRect &previousScreenGeometry)
const
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();
397 const QRect windowGeometry(relativeX * geometry().width(), relativeY * geometry().height(),
398 relativeWidth * geometry().width(), relativeHeight * geometry().height());
400 w->setGeometry(windowGeometry);
404
405
408 QRect windowGeometry = w->geometry();
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());
414 windowGeometry.moveCenter(newCenter);
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();
425 const int centerX = qMin(qAbs(x1) + windowGeometry.center().x(),
426 geometry().center().x());
428 windowGeometry.moveCenter(QPoint(centerX, windowGeometry.center().y()));
432 const int centerY = qMin(qAbs(y1) + windowGeometry.center().y(),
433 geometry().center().y());
435 windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), centerY));
438 if (x2 > geometry().width()) {
439 const int centerX = qMax(windowGeometry.center().x() - (x2 - geometry().width()),
440 geometry().center().x());
442 windowGeometry.moveCenter(QPoint(centerX, windowGeometry.center().y()));
445 if (y2 > geometry().height()) {
446 const int centerY = qMax(windowGeometry.center().y() - (y2 - geometry().height()),
447 geometry().center().y());
449 windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), centerY));
456 if (!geometry().contains(windowGeometry)) {
457 QSize newSize = windowGeometry.size();
458 newSize.scale(geometry().size(), Qt::KeepAspectRatio);
459 windowGeometry.setSize(newSize);
461 if (windowGeometry.x() < 0)
462 windowGeometry.moveCenter(QPoint(geometry().center().x(), windowGeometry.center().y()));
464 if (windowGeometry.y() < 0)
465 windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), geometry().center().y()));
468 w->setGeometry(windowGeometry);
472
473
474void QQnxScreen::resizeWindows(
const QRect &previousScreenGeometry)
476 resizeMaximizedWindows();
478 Q_FOREACH (QQnxWindow *w, m_childWindows) {
480 if (w->window()->windowState() & Qt::WindowFullScreen || w->window()->windowState() & Qt::WindowMaximized)
485 resizeNativeWidgetWindow(w, previousScreenGeometry);
488 resizeTopLevelWindow(w, previousScreenGeometry);
495 Q_FOREACH (QQnxWindow *window, m_childWindows) {
496 QQnxWindow *
const result = window->findWindow(windowHandle);
506 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"Window =" << window;
508 if (m_childWindows.contains(window))
511 if (window->window()->type() != Qt::CoverWindow) {
512 m_childWindows.push_back(window);
519 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"Window =" << window;
521 if (window != m_coverWindow) {
522 const int numWindowsRemoved = m_childWindows.removeAll(window);
523 if (window == m_rootWindow)
525 if (numWindowsRemoved > 0)
534 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"Window =" << window;
536 if (window != m_coverWindow) {
538 m_childWindows.push_back(window);
544 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"Window =" << window;
546 if (window != m_coverWindow) {
548 m_childWindows.push_front(window);
554 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
556 QList<QQnxWindow*>::const_iterator it;
562 result = screen_get_window_property_iv(
rootWindow()->nativeHandle(), SCREEN_PROPERTY_ZORDER, &topZorder);
565 qWarning(
"QQnxScreen: failed to query root window z-order, errno=%d", errno);
574 int underlayZorder = -1;
576 Q_FOREACH (screen_window_t underlay, m_underlays) {
580 screen_set_window_property_iv(underlay, SCREEN_PROPERTY_ZORDER, &underlayZorder);
585 for (it = m_childWindows.constBegin(); it != m_childWindows.constEnd(); ++it)
586 (*it)->updateZorder(topZorder);
589 Q_FOREACH (screen_window_t overlay, m_overlays) {
591 screen_set_window_property_iv(overlay, SCREEN_PROPERTY_ZORDER, &topZorder);
597 screen_flush_context(m_screenContext, 0);
602 if (!m_primaryScreen)
606 const int rotation = qEnvironmentVariableIntValue(
"ORIENTATION", &ok);
609 setRotation(rotation);
617void QQnxScreen::keyboardHeightChanged(
int height)
619 if (height == m_keyboardHeight)
622 m_keyboardHeight = height;
624 QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
627void QQnxScreen::addOverlayWindow(screen_window_t window)
629 m_overlays.append(window);
633void QQnxScreen::addUnderlayWindow(screen_window_t window)
635 m_underlays.append(window);
639void QQnxScreen::removeOverlayOrUnderlayWindow(screen_window_t window)
641 const int numRemoved = m_overlays.removeAll(window) + m_underlays.removeAll(window);
642 if (numRemoved > 0) {
644 Q_EMIT foreignWindowClosed(window);
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);
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);
664 char windowNameBuffer[256] = { 0 };
665 QByteArray windowName;
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);
672 windowName = QByteArray(windowNameBuffer);
674 if (display != nativeDisplay())
683 if (findWindow(windowHandle))
686 if (zorder <= MAX_UNDERLAY_ZORDER)
687 addUnderlayWindow(windowHandle);
689 addOverlayWindow(windowHandle);
691 Q_EMIT foreignWindowCreated(windowHandle);
696 Q_ASSERT(thread() == QThread::currentThread());
697 const screen_window_t windowHandle =
reinterpret_cast<screen_window_t>(window);
699 removeOverlayOrUnderlayWindow(windowHandle);
704 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
714 QWindowSystemInterface::handleWindowStateChanged(window, state);
719 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
729 Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
730 childWindow->setExposed(
true);
738 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
746 Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
747 childWindow->setExposed(
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);
764 qWarning(
"QQnxRootWindow: failed to disable power saving mode");
766 m_rootWindow = window;
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
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.
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 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...
void setExposed(bool exposed)
void setScreen(QQnxScreen *platformScreen)
void setRotation(int rotation)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
#define Q_SCREEN_CRITICALERROR(x, message)
#define Q_SCREEN_CHECKERROR(x, message)
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)