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),
86 m_nativeOrientation(Qt::PrimaryOrientation),
88 m_cursor(
new QQnxCursor(screenContext))
90 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
92 int result = screen_get_display_property_iv(m_display, SCREEN_PROPERTY_ROTATION,
96 m_currentRotation = m_initialRotation;
101 "Failed to query display size");
103 m_currentGeometry = m_initialGeometry = QRect(0, 0, val[0], val[1]);
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);
114 const QSize screenSize = determineScreenSize(m_display, primaryScreen);
116 m_nativeOrientation = screenSize.width() >= screenSize.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
118 const int angle = screen()->angleBetween(m_nativeOrientation, orientation());
119 if (angle == 0 || angle == 180)
120 m_currentPhysicalSize = m_initialPhysicalSize = screenSize;
122 m_currentPhysicalSize = m_initialPhysicalSize = screenSize.transposed();
127 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
128 Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
129 childWindow->setScreen(0);
139 QQnxWindow *qnxWin = findWindow(
reinterpret_cast<screen_window_t>(window));
141 qWarning(
"grabWindow: unknown window");
145 QRect bound = qnxWin->geometry();
148 width = bound.width();
150 height = bound.height();
152 bound &= QRect(x + bound.x(), y + bound.y(), width, height);
154 if (bound.width() <= 0 || bound.height() <= 0) {
155 qWarning(
"grabWindow: size is null");
160 screen_context_t context;
161 if (screen_create_context(&context, SCREEN_DISPLAY_MANAGER_CONTEXT)) {
163 qWarning(
"grabWindow: root privileges required");
165 qWarning(
"grabWindow: cannot create context");
171 screen_display_t display = 0;
172 screen_get_context_property_iv(context, SCREEN_PROPERTY_DISPLAY_COUNT, &count);
174 const size_t idLen = 30;
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);
184 while (count && !found) {
186 screen_get_display_property_cv(displays[count], SCREEN_PROPERTY_ID_STRING, idLen, id);
187 found = !strncmp(id, matchId, idLen);
191 display = displays[count];
197 screen_pixmap_t pixmap;
199 if (display && !screen_create_pixmap(&pixmap, context)) {
200 screen_buffer_t buffer;
203 const int rect[4] = { bound.x(), bound.y(), bound.width(), bound.height() };
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);
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);
219 const QImage img(
static_cast<
unsigned char*>(pointer),
220 bound.width(), bound.height(), stride, QImage::Format_ARGB32);
221 result = QPixmap::fromImage(img);
223 qWarning(
"grabWindow: capture error");
225 screen_destroy_pixmap(pixmap);
227 qWarning(
"grabWindow: display/pixmap error ");
229 screen_destroy_context(context);
236 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
237 static int defaultDepth = 0;
238 if (defaultDepth == 0) {
241 defaultDepth = qEnvironmentVariableIntValue(
"QQNX_DISPLAY_DEPTH");
242 if (defaultDepth != 16 && defaultDepth != 32)
250 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
252 return QRect(m_currentGeometry.x(), m_currentGeometry.y(),
253 m_currentGeometry.width(), m_currentGeometry.height() - m_keyboardHeight);
263 screen_display_mode_t displayMode;
264 int result = screen_get_display_property_pv(m_display, SCREEN_PROPERTY_MODE,
reinterpret_cast<
void **>(&displayMode));
266 if (result != 0 || displayMode.refresh == 0) {
267 qWarning(
"QQnxScreen: Failed to query screen mode. Using default value of 60Hz");
270 qCDebug(lcQpaScreen,
"screen mode:\n"
275 uint(displayMode.width), uint(displayMode.height), uint(displayMode.refresh), uint(displayMode.interlaced));
276 return static_cast<qreal>(displayMode.refresh);
281 return m_nativeOrientation;
286 Qt::ScreenOrientation orient;
287 if (m_nativeOrientation == Qt::LandscapeOrientation) {
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;
296 orient = Qt::InvertedPortraitOrientation;
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;
307 orient = Qt::InvertedLandscapeOrientation;
309 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"Orientation =" << orient;
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))
324
325
328 return ((angle1 - angle2) % 180) != 0;
333 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"orientation =" << rotation;
341 const QRect previousScreenGeometry = geometry();
345 m_currentGeometry = QRect(0, 0, m_initialGeometry.height(), m_initialGeometry.width());
346 m_currentPhysicalSize = QSize(m_initialPhysicalSize.height(), m_initialPhysicalSize.width());
348 m_currentGeometry = QRect(0, 0, m_initialGeometry.width(), m_initialGeometry.height());
349 m_currentPhysicalSize = m_initialPhysicalSize;
354 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"resize, size =" << m_currentGeometry.size();
356 rootWindow()->setGeometry(QRect(QPoint(0,0), m_currentGeometry.size()));
358 resizeWindows(previousScreenGeometry);
362 screen_flush_context(nativeContext(), 0);
366 m_currentRotation = rotation;
371 if (m_primaryScreen) {
372 QWindowSystemInterface::handleScreenOrientationChange(screen(), orientation());
373 QWindowSystemInterface::handleScreenGeometryChange(screen(), m_currentGeometry, availableGeometry());
378 screen_flush_context( m_screenContext, 0 );
383
384
385void QQnxScreen::resizeNativeWidgetWindow(
QQnxWindow *w,
const QRect &previousScreenGeometry)
const
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();
392 const QRect windowGeometry(relativeX * geometry().width(), relativeY * geometry().height(),
393 relativeWidth * geometry().width(), relativeHeight * geometry().height());
395 w->setGeometry(windowGeometry);
399
400
403 QRect windowGeometry = w->geometry();
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());
409 windowGeometry.moveCenter(newCenter);
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();
420 const int centerX = qMin(qAbs(x1) + windowGeometry.center().x(),
421 geometry().center().x());
423 windowGeometry.moveCenter(QPoint(centerX, windowGeometry.center().y()));
427 const int centerY = qMin(qAbs(y1) + windowGeometry.center().y(),
428 geometry().center().y());
430 windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), centerY));
433 if (x2 > geometry().width()) {
434 const int centerX = qMax(windowGeometry.center().x() - (x2 - geometry().width()),
435 geometry().center().x());
437 windowGeometry.moveCenter(QPoint(centerX, windowGeometry.center().y()));
440 if (y2 > geometry().height()) {
441 const int centerY = qMax(windowGeometry.center().y() - (y2 - geometry().height()),
442 geometry().center().y());
444 windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), centerY));
451 if (!geometry().contains(windowGeometry)) {
452 QSize newSize = windowGeometry.size();
453 newSize.scale(geometry().size(), Qt::KeepAspectRatio);
454 windowGeometry.setSize(newSize);
456 if (windowGeometry.x() < 0)
457 windowGeometry.moveCenter(QPoint(geometry().center().x(), windowGeometry.center().y()));
459 if (windowGeometry.y() < 0)
460 windowGeometry.moveCenter(QPoint(windowGeometry.center().x(), geometry().center().y()));
463 w->setGeometry(windowGeometry);
467
468
469void QQnxScreen::resizeWindows(
const QRect &previousScreenGeometry)
471 resizeMaximizedWindows();
473 Q_FOREACH (QQnxWindow *w, m_childWindows) {
475 if (w->window()->windowState() & Qt::WindowFullScreen || w->window()->windowState() & Qt::WindowMaximized)
480 resizeNativeWidgetWindow(w, previousScreenGeometry);
483 resizeTopLevelWindow(w, previousScreenGeometry);
490 Q_FOREACH (QQnxWindow *window, m_childWindows) {
491 QQnxWindow *
const result = window->findWindow(windowHandle);
501 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"Window =" << window;
503 if (m_childWindows.contains(window))
506 if (window->window()->type() != Qt::CoverWindow) {
507 m_childWindows.push_back(window);
514 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"Window =" << window;
516 if (window != m_coverWindow) {
517 const int numWindowsRemoved = m_childWindows.removeAll(window);
518 if (window == m_rootWindow)
520 if (numWindowsRemoved > 0)
529 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"Window =" << window;
531 if (window != m_coverWindow) {
533 m_childWindows.push_back(window);
539 qCDebug(lcQpaScreen) << Q_FUNC_INFO <<
"Window =" << window;
541 if (window != m_coverWindow) {
543 m_childWindows.push_front(window);
549 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
551 QList<QQnxWindow*>::const_iterator it;
557 result = screen_get_window_property_iv(
rootWindow()->nativeHandle(), SCREEN_PROPERTY_ZORDER, &topZorder);
560 qWarning(
"QQnxScreen: failed to query root window z-order, errno=%d", errno);
569 int underlayZorder = -1;
571 Q_FOREACH (screen_window_t underlay, m_underlays) {
575 screen_set_window_property_iv(underlay, SCREEN_PROPERTY_ZORDER, &underlayZorder);
580 for (it = m_childWindows.constBegin(); it != m_childWindows.constEnd(); ++it)
581 (*it)->updateZorder(topZorder);
584 Q_FOREACH (screen_window_t overlay, m_overlays) {
586 screen_set_window_property_iv(overlay, SCREEN_PROPERTY_ZORDER, &topZorder);
592 screen_flush_context(m_screenContext, 0);
597 if (!m_primaryScreen)
601 const int rotation = qEnvironmentVariableIntValue(
"ORIENTATION", &ok);
604 setRotation(rotation);
612void QQnxScreen::keyboardHeightChanged(
int height)
614 if (height == m_keyboardHeight)
617 m_keyboardHeight = height;
619 QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
622void QQnxScreen::addOverlayWindow(screen_window_t window)
624 m_overlays.append(window);
628void QQnxScreen::addUnderlayWindow(screen_window_t window)
630 m_underlays.append(window);
634void QQnxScreen::removeOverlayOrUnderlayWindow(screen_window_t window)
636 const int numRemoved = m_overlays.removeAll(window) + m_underlays.removeAll(window);
637 if (numRemoved > 0) {
639 Q_EMIT foreignWindowClosed(window);
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);
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);
659 char windowNameBuffer[256] = { 0 };
660 QByteArray windowName;
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);
667 windowName = QByteArray(windowNameBuffer);
669 if (display != nativeDisplay())
678 if (findWindow(windowHandle))
681 if (zorder <= MAX_UNDERLAY_ZORDER)
682 addUnderlayWindow(windowHandle);
684 addOverlayWindow(windowHandle);
686 Q_EMIT foreignWindowCreated(windowHandle);
691 Q_ASSERT(thread() == QThread::currentThread());
692 const screen_window_t windowHandle =
reinterpret_cast<screen_window_t>(window);
694 removeOverlayOrUnderlayWindow(windowHandle);
699 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
709 QWindowSystemInterface::handleWindowStateChanged(window, state);
714 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
724 Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
725 childWindow->setExposed(
true);
733 qCDebug(lcQpaScreen) << Q_FUNC_INFO;
741 Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
742 childWindow->setExposed(
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);
759 qWarning(
"QQnxRootWindow: failed to disable power saving mode");
761 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)