23#if !defined(QT_NO_OPENGL)
28#include "qqnxvulkanwindow.h"
29#include "qqnxvulkaninstance.h"
32#if QT_CONFIG(qqnx_pps)
33#include "qqnxnavigatorpps.h"
34#include "qqnxnavigatoreventnotifier.h"
35#include "qqnxvirtualkeyboardpps.h"
38#if QT_CONFIG(qqnx_pps)
39# include "qqnxbuttoneventnotifier.h"
42#if QT_CONFIG(qqnx_imf)
43# include "qqnxinputcontext_imf.h"
48#if !defined(QT_NO_CLIPBOARD)
52#include <qpa/qplatforminputcontextfactory_p.h>
53#include <qpa/qplatforminputcontext.h>
54#include <qpa/qplatformtheme.h>
56#include "private/qgenericunixfontdatabase_p.h"
57#include "private/qgenericunixeventdispatcher_p.h"
59#include <qpa/qplatformwindow.h>
60#include <qpa/qwindowsysteminterface.h>
62#include <QtGui/private/qguiapplication_p.h>
63#include <QtGui/private/qrhibackingstore_p.h>
65#if !defined(QT_NO_OPENGL)
67#include <QtGui/QOpenGLContext>
70#include <private/qsimpledrag_p.h>
72#include <QtCore/QDebug>
73#include <QtCore/QJsonDocument>
74#include <QtCore/QJsonObject>
75#include <QtCore/QJsonArray>
76#include <QtCore/QFile>
81using namespace Qt::StringLiterals;
88 if (!paramList.contains(
"no-fullscreen"_L1)) {
92 if (paramList.contains(
"flush-screen-context"_L1)) {
96 if (paramList.contains(
"rootwindow"_L1)) {
100 if (!paramList.contains(
"disable-EGL_KHR_surfaceless_context"_L1)) {
104 if (paramList.contains(
"desktop"_L1)) {
113 constexpr auto contextCapabilitiesPrefix =
"screen-context-capabilities="_L1;
114 int contextCapabilities = SCREEN_APPLICATION_CONTEXT;
115 for (
const QString ¶m : paramList) {
116 if (param.startsWith(contextCapabilitiesPrefix)) {
117 auto value = QStringView{param}.mid(contextCapabilitiesPrefix.length());
119 contextCapabilities = value.toInt(&ok, 0);
121 contextCapabilities = SCREEN_APPLICATION_CONTEXT;
124 return contextCapabilities;
128 : QPlatformIntegration()
129 , m_screenContextId(256, 0)
130 , m_screenEventThread(0)
132 , m_virtualKeyboard(0)
134#if QT_CONFIG(qqnx_pps)
135 , m_navigatorEventNotifier(0)
136 , m_buttonsNotifier(
new QQnxButtonEventNotifier())
138 , m_qpaInputContext(0)
139 , m_fontDatabase(
new QGenericUnixFontDatabase())
140 , m_eventDispatcher(createUnixEventDispatcher())
142 , m_screenEventHandler(
new QQnxScreenEventHandler(
this))
143#if !defined(QT_NO_CLIPBOARD)
147#if QT_CONFIG(draganddrop)
148 , m_drag(
new QSimpleDrag())
151 , m_eglDisplay(EGL_NO_DISPLAY)
155 m_options = parseOptions(paramList);
156 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
159 if (screen_create_context(&m_screenContext, getContextCapabilities(paramList))) {
160 qFatal(
"%s - Screen: Failed to create screen context - Error: %s (%i)",
161 Q_FUNC_INFO, strerror(errno), errno);
163 screen_get_context_property_cv(m_screenContext,
165 m_screenContextId.size(),
166 m_screenContextId.data());
167 m_screenContextId.resize(strlen(m_screenContextId.constData()));
169#if QT_CONFIG(qqnx_pps)
171 m_navigatorEventNotifier =
new QQnxNavigatorEventNotifier(m_navigatorEventHandler);
175 QMetaObject::invokeMethod(m_navigatorEventNotifier,
"start", Qt::QueuedConnection);
183 m_screenEventThread =
new QQnxScreenEventThread(m_screenContext);
185 m_screenEventThread->start();
187 m_qpaInputContext = QPlatformInputContextFactory::create();
189#if QT_CONFIG(qqnx_pps)
190 if (!m_qpaInputContext) {
192 m_virtualKeyboard =
new QQnxVirtualKeyboardPps();
196 QMetaObject::invokeMethod(m_virtualKeyboard,
"start", Qt::QueuedConnection);
200#if QT_CONFIG(qqnx_pps)
201 m_navigator =
new QQnxNavigatorPps();
206 if (m_virtualKeyboard) {
208 QObject::connect(m_virtualKeyboard, SIGNAL(heightChanged(
int)),
209 primaryDisplay(), SLOT(keyboardHeightChanged(
int)));
211#if QT_CONFIG(qqnx_pps)
213 m_inputContext =
new QQnxInputContext(
this, *m_virtualKeyboard);
214#if QT_CONFIG(qqnx_imf)
215 m_screenEventHandler->addScreenEventFilter(m_inputContext);
220#if QT_CONFIG(qqnx_pps)
223 QMetaObject::invokeMethod(m_buttonsNotifier,
"start", Qt::QueuedConnection);
229 qCDebug(lcQpaQnx) <<
"Platform plugin shutdown begin";
230 delete m_nativeInterface;
232#if QT_CONFIG(draganddrop)
237#if !defined(QT_NO_CLIPBOARD)
243#if QT_CONFIG(qqnx_pps)
244 delete m_navigatorEventNotifier;
246 delete m_navigatorEventHandler;
249 delete m_screenEventThread;
252 delete m_eventDispatcher;
254 delete m_screenEventHandler;
260 screen_destroy_context(m_screenContext);
266#if QT_CONFIG(qqnx_pps)
268 delete m_buttonsNotifier;
271 delete m_inputContext;
273 delete m_qpaInputContext;
276 delete m_virtualKeyboard;
284 ms_instance =
nullptr;
286 qCDebug(lcQpaQnx) <<
"Platform plugin shutdown end";
291 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
293 case MultipleWindows:
295 case ThreadedPixmaps:
297#if !defined(QT_NO_OPENGL)
300 case BufferQueueingOpenGL:
304 return QPlatformIntegration::hasCapability(cap);
310 screen_window_t screenWindow =
reinterpret_cast<screen_window_t>(nativeHandle);
311 if (
this->window(screenWindow)) {
312 qWarning() <<
"QWindow already created for foreign window"
317 return new QQnxForeignWindow(window, m_screenContext, screenWindow);
322 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
323 QSurface::SurfaceType surfaceType = window->surfaceType();
324 const bool needRootWindow = options() & RootWindow;
325 switch (surfaceType) {
326 case QSurface::RasterSurface:
327 return new QQnxRasterWindow(window, m_screenContext, needRootWindow);
328#if !defined(QT_NO_OPENGL)
329 case QSurface::OpenGLSurface:
330 return new QQnxEglWindow(window, m_screenContext, needRootWindow);
333 case QSurface::VulkanSurface:
334 return new QQnxVulkanWindow(window, m_screenContext, needRootWindow);
337 qFatal(
"QQnxWindow: unsupported window API");
343QPlatformVulkanInstance *QQnxIntegration::createPlatformVulkanInstance(QVulkanInstance *instance)
const
345 return new QQnxVulkanInstance(instance);
351 QSurface::SurfaceType surfaceType = window->surfaceType();
352 qCDebug(lcQpaQnx) << Q_FUNC_INFO << surfaceType;
353 switch (surfaceType) {
354 case QSurface::RasterSurface:
356#if !defined(QT_NO_OPENGL)
358 case QSurface::OpenGLSurface:
359 return new QRhiBackingStore(window);
362 case QSurface::VulkanSurface:
363 return new QRhiBackingStore(window);
370#if !defined(QT_NO_OPENGL)
371QPlatformOpenGLContext *
QQnxIntegration::createPlatformOpenGLContext(QOpenGLContext *context)
const
373 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
376 QSurfaceFormat format = context->format();
377 int alphaSize = format.alphaBufferSize();
378 int redSize = format.redBufferSize();
379 int greenSize = format.greenBufferSize();
380 int blueSize = format.blueBufferSize();
383 if (alphaSize == -1 && redSize == -1 && greenSize == -1 && blueSize == -1) {
402 if (alphaSize <= 0 && redSize <= 5 && greenSize <= 6 && blueSize <= 5) {
418 format.setAlphaBufferSize(alphaSize);
419 format.setRedBufferSize(redSize);
420 format.setGreenBufferSize(greenSize);
421 format.setBlueBufferSize(blueSize);
422 context->setFormat(format);
431 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
432 if (m_qpaInputContext)
433 return m_qpaInputContext;
434 return m_inputContext;
439 qCDebug(lcQpaQnx) << Q_FUNC_INFO <<
"w =" << window <<
", s =" << screen;
445 QQnxScreen *platformScreen = m_screens.at(screen);
453 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
456 QAbstractEventDispatcher *eventDispatcher = m_eventDispatcher;
457 m_eventDispatcher = 0;
459 return eventDispatcher;
464 return m_nativeInterface;
467#if !defined(QT_NO_CLIPBOARD)
470 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
478#if QT_CONFIG(draganddrop)
479QPlatformDrag *QQnxIntegration::drag()
const
487 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
488 if ((hint == ShowIsFullScreen) && (m_options & FullScreenApplication))
491 return QPlatformIntegration::styleHint(hint);
501class QQnxTheme :
public QPlatformTheme
504 QVariant themeHint(ThemeHint hint)
const override
506 if (hint == QPlatformTheme::StyleNames)
507 return QStringList{ QStringLiteral(
"Fusion") };
508 return QPlatformTheme::themeHint(hint);
517 return QStringList{ QStringLiteral(
"qnx") };
525 return name ==
"qnx"_L1 ?
new QQnxTheme :
nullptr;
531 if (m_navigator && !m_services)
539 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
540 QMutexLocker locker(&m_windowMapperMutex);
542 return m_windowMapper.value(qnxWindow, 0);
545void QQnxIntegration::addWindow(screen_window_t qnxWindow, QWindow *window)
547 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
548 QMutexLocker locker(&m_windowMapperMutex);
550 m_windowMapper.insert(qnxWindow, window);
555 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
556 QMutexLocker locker(&m_windowMapperMutex);
558 m_windowMapper.remove(qnxWindow);
562
563
564
565
569 if (screen_get_display_property_iv(display,
578
579
580
581
585 QByteArray json = qgetenv(
"QT_QPA_QNX_DISPLAY_CONFIG");
590 QFile file(QString::fromUtf8(json));
591 if (!file.open(QFile::ReadOnly)) {
592 qWarning() <<
"Could not open config file" << json <<
"for reading";
597 const QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
598 if (!doc.isObject()) {
599 qWarning() <<
"Invalid config file" << json
600 <<
"- no top-level JSON object";
605 const QJsonObject object = doc.object();
606 requestedDisplays = object.value(
"displayOrder"_L1).toArray();
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627QList<screen_display_t *>
QQnxIntegration::sortDisplays(screen_display_t *availableDisplays,
int displayCount)
630 QList<screen_display_t *> allDisplays;
631 for (
int i = 0; i < displayCount; i++)
632 allDisplays.append(&availableDisplays[i]);
635 QJsonArray requestedDisplays;
636 if (!getRequestedDisplays(requestedDisplays))
640 QList<screen_display_t *> orderedDisplays;
641 for (
const QJsonValue &value : std::as_const(requestedDisplays)) {
642 int requestedValue = value.toInt();
646 for (
auto it = allDisplays.begin(), end = allDisplays.end(); it != end; ++it) {
647 screen_display_t *display = *it;
648 if (getIdOfDisplay(*display) == requestedValue) {
649 orderedDisplays.append(display);
650 allDisplays.erase(it);
657 orderedDisplays.append(allDisplays);
659 return orderedDisplays;
664 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
666 int displayCount = 0;
667 int result = screen_get_context_property_iv(m_screenContext, SCREEN_PROPERTY_DISPLAY_COUNT,
671 if (Q_UNLIKELY(displayCount < 1)) {
673 qFatal(
"QQnxIntegration: displayCount=%d", displayCount);
677 screen_display_t *displays = (screen_display_t *)alloca(
sizeof(screen_display_t) * displayCount);
678 result = screen_get_context_property_pv(m_screenContext, SCREEN_PROPERTY_DISPLAYS,
680 QList<screen_display_t *> orderedDisplays = sortDisplays(displays, displayCount);
685 createDisplay(*orderedDisplays[0],
true);
687 for (
int i=1; i<displayCount; i++) {
689 result = screen_get_display_property_iv(*orderedDisplays[i], SCREEN_PROPERTY_ATTACHED,
694 qCDebug(lcQpaQnx) <<
"Skipping non-attached display " << i;
698 qCDebug(lcQpaQnx) <<
"Creating screen for display " << i;
700 createDisplay(*orderedDisplays[i],
false);
706 QQnxScreen *screen =
new QQnxScreen(m_screenContext, display, isPrimary);
707 m_screens.append(screen);
708 QWindowSystemInterface::handleScreenAdded(screen);
711 QObject::connect(m_screenEventHandler, SIGNAL(newWindowCreated(
void*)),
712 screen, SLOT(newWindowCreated(
void*)));
713 QObject::connect(m_screenEventHandler, SIGNAL(windowClosed(
void*)),
714 screen, SLOT(windowClosed(
void*)));
716 QObject::connect(m_navigatorEventHandler, SIGNAL(rotationChanged(
int)), screen, SLOT(setRotation(
int)));
717 QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupActivated(QByteArray)), screen, SLOT(activateWindowGroup(QByteArray)));
718 QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupDeactivated(QByteArray)), screen, SLOT(deactivateWindowGroup(QByteArray)));
719 QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupStateChanged(QByteArray,Qt::WindowState)),
720 screen, SLOT(windowGroupStateChanged(QByteArray,Qt::WindowState)));
726 Q_ASSERT(m_screens.contains(screen));
727 m_screens.removeAll(screen);
728 QWindowSystemInterface::handleScreenRemoved(screen);
733 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
735 Q_FOREACH (QQnxScreen *screen, m_screens) {
736 QWindowSystemInterface::handleScreenRemoved(screen);
743 Q_FOREACH (QQnxScreen *screen, m_screens) {
744 if (screen->nativeDisplay() == qnxScreen)
753 return m_screens.first();
763 return m_screenContext;
768 return m_screenContextId;
773 return m_navigatorEventHandler;
779 return m_navigator != 0;
783void QQnxIntegration::createEglDisplay()
785 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
788 m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
789 if (Q_UNLIKELY(m_eglDisplay == EGL_NO_DISPLAY))
790 qFatal(
"QQnxiIntegration: failed to obtain EGL display: %x", eglGetError());
792 EGLBoolean eglResult = eglInitialize(m_eglDisplay, 0, 0);
793 if (Q_UNLIKELY(eglResult != EGL_TRUE))
794 qFatal(
"QQnxIntegration: failed to initialize EGL display, err=%d", eglGetError());
797void QQnxIntegration::destroyEglDisplay()
799 qCDebug(lcQpaQnx) << Q_FUNC_INFO;
802 eglTerminate(m_eglDisplay);
QAbstractEventDispatcher * createEventDispatcher() const override
Factory function for the GUI event dispatcher.
bool hasCapability(QPlatformIntegration::Capability cap) const override
QPlatformNativeInterface * nativeInterface() const override
QQnxNavigatorEventHandler * navigatorEventHandler()
@ AlwaysFlushScreenContext
QPlatformBackingStore * createPlatformBackingStore(QWindow *window) const override
Factory function for QPlatformBackingStore.
QPlatformWindow * createPlatformWindow(QWindow *window) const override
Factory function for QPlatformWindow.
QPlatformWindow * createForeignWindow(QWindow *window, WId nativeHandle) const override
QStringList themeNames() const override
QQnxScreen * primaryDisplay() const
QPlatformTheme * createPlatformTheme(const QString &name) const override
void removeDisplay(QQnxScreen *screen)
QVariant styleHint(StyleHint hint) const override
QPlatformServices * services() const override
void moveToScreen(QWindow *window, int screen)
QPlatformInputContext * inputContext() const override
Returns the platforms input context.
QByteArray screenContextId()
QQnxScreen * screenForNative(screen_display_t qnxScreen) const
void createDisplay(screen_display_t display, bool isPrimary)
screen_context_t screenContext()
QWindow * window(screen_window_t qnxWindow) const
QPlatformClipboard * clipboard() const override
Accessor for the platform integration's clipboard.
bool supportsNavigatorEvents() const
QQnxNativeInterface(QQnxIntegration *integration)
void setScreenEventThread(QQnxScreenEventThread *eventThread)
int depth() const override
Reimplement in subclass to return current depth of the screen.
QQnxServices(QQnxAbstractNavigator *navigator)
The QQnxWindow is the base class of the various classes used as instances of QPlatformWindow in the Q...
void setScreen(QQnxScreen *platformScreen)
#define Q_SCREEN_CRITICALERROR(x, message)
#define Q_SCREEN_CHECKERROR(x, message)
static bool getRequestedDisplays(QJsonArray &requestedDisplays)
Read JSON configuration file for the QNX display order.
static int getIdOfDisplay(screen_display_t display)
Get display ID for given display.
static int getContextCapabilities(const QStringList ¶mList)
static QQnxIntegration::Options parseOptions(const QStringList ¶mList)