| /*************************************************************************** |
| ** |
| ** Copyright (C) 2013 BlackBerry Limited. All rights reserved. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the plugins of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qqnxglobal.h" |
| |
| #include "qqnxintegration.h" |
| #include "qqnxscreeneventthread.h" |
| #include "qqnxnativeinterface.h" |
| #include "qqnxrasterbackingstore.h" |
| #include "qqnxscreen.h" |
| #include "qqnxscreeneventhandler.h" |
| #include "qqnxwindow.h" |
| #include "qqnxnavigatoreventhandler.h" |
| #include "qqnxabstractnavigator.h" |
| #include "qqnxabstractvirtualkeyboard.h" |
| #include "qqnxservices.h" |
| |
| #include "qqnxforeignwindow.h" |
| #include "qqnxrasterwindow.h" |
| #if !defined(QT_NO_OPENGL) |
| #include "qqnxeglwindow.h" |
| #endif |
| |
| #if QT_CONFIG(qqnx_pps) |
| #include "qqnxnavigatorpps.h" |
| #include "qqnxnavigatoreventnotifier.h" |
| #include "qqnxvirtualkeyboardpps.h" |
| #endif |
| |
| #if QT_CONFIG(qqnx_pps) |
| # include "qqnxbuttoneventnotifier.h" |
| # include "qqnxclipboard.h" |
| # if QT_CONFIG(qqnx_imf) |
| # include "qqnxinputcontext_imf.h" |
| # else |
| # include "qqnxinputcontext_noimf.h" |
| # endif |
| #endif |
| |
| #include <qpa/qplatforminputcontextfactory_p.h> |
| #include <qpa/qplatforminputcontext.h> |
| |
| #include "private/qgenericunixfontdatabase_p.h" |
| #include "private/qgenericunixeventdispatcher_p.h" |
| |
| #include <qpa/qplatformwindow.h> |
| #include <qpa/qwindowsysteminterface.h> |
| |
| #include <QtGui/private/qguiapplication_p.h> |
| |
| #if !defined(QT_NO_OPENGL) |
| #include "qqnxglcontext.h" |
| #include <QtGui/QOpenGLContext> |
| #endif |
| |
| #include <private/qsimpledrag_p.h> |
| |
| #include <QtCore/QDebug> |
| #include <QtCore/QJsonDocument> |
| #include <QtCore/QJsonObject> |
| #include <QtCore/QJsonArray> |
| #include <QtCore/QFile> |
| #include <errno.h> |
| |
| #if defined(QQNXINTEGRATION_DEBUG) |
| #define qIntegrationDebug qDebug |
| #else |
| #define qIntegrationDebug QT_NO_QDEBUG_MACRO |
| #endif |
| |
| QT_BEGIN_NAMESPACE |
| |
| QQnxIntegration *QQnxIntegration::ms_instance; |
| |
| static inline QQnxIntegration::Options parseOptions(const QStringList ¶mList) |
| { |
| QQnxIntegration::Options options = QQnxIntegration::NoOptions; |
| if (!paramList.contains(QLatin1String("no-fullscreen"))) { |
| options |= QQnxIntegration::FullScreenApplication; |
| } |
| |
| if (paramList.contains(QLatin1String("flush-screen-context"))) { |
| options |= QQnxIntegration::AlwaysFlushScreenContext; |
| } |
| |
| if (paramList.contains(QLatin1String("rootwindow"))) { |
| options |= QQnxIntegration::RootWindow; |
| } |
| |
| if (!paramList.contains(QLatin1String("disable-EGL_KHR_surfaceless_context"))) { |
| options |= QQnxIntegration::SurfacelessEGLContext; |
| } |
| |
| return options; |
| } |
| |
| static inline int getContextCapabilities(const QStringList ¶mList) |
| { |
| QString contextCapabilitiesPrefix = QStringLiteral("screen-context-capabilities="); |
| int contextCapabilities = SCREEN_APPLICATION_CONTEXT; |
| for (const QString ¶m : paramList) { |
| if (param.startsWith(contextCapabilitiesPrefix)) { |
| QStringRef value = param.midRef(contextCapabilitiesPrefix.length()); |
| bool ok = false; |
| contextCapabilities = value.toInt(&ok, 0); |
| if (!ok) |
| contextCapabilities = SCREEN_APPLICATION_CONTEXT; |
| } |
| } |
| return contextCapabilities; |
| } |
| |
| QQnxIntegration::QQnxIntegration(const QStringList ¶mList) |
| : QPlatformIntegration() |
| , m_screenContextId(256, 0) |
| , m_screenEventThread(0) |
| , m_navigatorEventHandler(new QQnxNavigatorEventHandler()) |
| , m_virtualKeyboard(0) |
| #if QT_CONFIG(qqnx_pps) |
| , m_navigatorEventNotifier(0) |
| , m_inputContext(0) |
| , m_buttonsNotifier(new QQnxButtonEventNotifier()) |
| #endif |
| , m_qpaInputContext(0) |
| , m_services(0) |
| , m_fontDatabase(new QGenericUnixFontDatabase()) |
| , m_eventDispatcher(createUnixEventDispatcher()) |
| , m_nativeInterface(new QQnxNativeInterface(this)) |
| , m_screenEventHandler(new QQnxScreenEventHandler(this)) |
| #if !defined(QT_NO_CLIPBOARD) |
| , m_clipboard(0) |
| #endif |
| , m_navigator(0) |
| #if QT_CONFIG(draganddrop) |
| , m_drag(new QSimpleDrag()) |
| #endif |
| #if QT_CONFIG(opengl) |
| , m_eglDisplay(EGL_NO_DISPLAY) |
| #endif |
| { |
| ms_instance = this; |
| m_options = parseOptions(paramList); |
| qIntegrationDebug(); |
| |
| // Open connection to QNX composition manager |
| if (screen_create_context(&m_screenContext, getContextCapabilities(paramList))) { |
| qFatal("%s - Screen: Failed to create screen context - Error: %s (%i)", |
| Q_FUNC_INFO, strerror(errno), errno); |
| } |
| screen_get_context_property_cv(m_screenContext, |
| SCREEN_PROPERTY_ID, |
| m_screenContextId.size(), |
| m_screenContextId.data()); |
| m_screenContextId.resize(strlen(m_screenContextId.constData())); |
| |
| #if QT_CONFIG(qqnx_pps) |
| // Create/start navigator event notifier |
| m_navigatorEventNotifier = new QQnxNavigatorEventNotifier(m_navigatorEventHandler); |
| |
| // delay invocation of start() to the time the event loop is up and running |
| // needed to have the QThread internals of the main thread properly initialized |
| QMetaObject::invokeMethod(m_navigatorEventNotifier, "start", Qt::QueuedConnection); |
| #endif |
| |
| #if QT_CONFIG(opengl) |
| createEglDisplay(); |
| #endif |
| |
| // Create/start event thread |
| m_screenEventThread = new QQnxScreenEventThread(m_screenContext); |
| m_screenEventHandler->setScreenEventThread(m_screenEventThread); |
| m_screenEventThread->start(); |
| |
| m_qpaInputContext = QPlatformInputContextFactory::create(); |
| |
| #if QT_CONFIG(qqnx_pps) |
| if (!m_qpaInputContext) { |
| // Create/start the keyboard class. |
| m_virtualKeyboard = new QQnxVirtualKeyboardPps(); |
| |
| // delay invocation of start() to the time the event loop is up and running |
| // needed to have the QThread internals of the main thread properly initialized |
| QMetaObject::invokeMethod(m_virtualKeyboard, "start", Qt::QueuedConnection); |
| } |
| #endif |
| |
| #if QT_CONFIG(qqnx_pps) |
| m_navigator = new QQnxNavigatorPps(); |
| #endif |
| |
| // Create services handling class |
| if (m_navigator) |
| m_services = new QQnxServices(m_navigator); |
| |
| createDisplays(); |
| |
| if (m_virtualKeyboard) { |
| // TODO check if we need to do this for all screens or only the primary one |
| QObject::connect(m_virtualKeyboard, SIGNAL(heightChanged(int)), |
| primaryDisplay(), SLOT(keyboardHeightChanged(int))); |
| |
| #if QT_CONFIG(qqnx_pps) |
| // Set up the input context |
| m_inputContext = new QQnxInputContext(this, *m_virtualKeyboard); |
| #if QT_CONFIG(qqnx_imf) |
| m_screenEventHandler->addScreenEventFilter(m_inputContext); |
| #endif |
| #endif |
| } |
| |
| #if QT_CONFIG(qqnx_pps) |
| // delay invocation of start() to the time the event loop is up and running |
| // needed to have the QThread internals of the main thread properly initialized |
| QMetaObject::invokeMethod(m_buttonsNotifier, "start", Qt::QueuedConnection); |
| #endif |
| } |
| |
| QQnxIntegration::~QQnxIntegration() |
| { |
| qIntegrationDebug("platform plugin shutdown begin"); |
| delete m_nativeInterface; |
| |
| #if QT_CONFIG(draganddrop) |
| // Destroy the drag object |
| delete m_drag; |
| #endif |
| |
| #if !defined(QT_NO_CLIPBOARD) |
| // Delete the clipboard |
| delete m_clipboard; |
| #endif |
| |
| // Stop/destroy navigator event notifier |
| #if QT_CONFIG(qqnx_pps) |
| delete m_navigatorEventNotifier; |
| #endif |
| delete m_navigatorEventHandler; |
| |
| // Stop/destroy screen event thread |
| delete m_screenEventThread; |
| |
| // In case the event-dispatcher was never transferred to QCoreApplication |
| delete m_eventDispatcher; |
| |
| delete m_screenEventHandler; |
| |
| // Destroy all displays |
| destroyDisplays(); |
| |
| // Close connection to QNX composition manager |
| screen_destroy_context(m_screenContext); |
| |
| #if QT_CONFIG(opengl) |
| destroyEglDisplay(); |
| #endif |
| |
| #if QT_CONFIG(qqnx_pps) |
| // Destroy the hardware button notifier |
| delete m_buttonsNotifier; |
| |
| // Destroy input context |
| delete m_inputContext; |
| #endif |
| delete m_qpaInputContext; |
| |
| // Destroy the keyboard class. |
| delete m_virtualKeyboard; |
| |
| // Destroy services class |
| delete m_services; |
| |
| // Destroy navigator interface |
| delete m_navigator; |
| |
| ms_instance = nullptr; |
| |
| qIntegrationDebug("platform plugin shutdown end"); |
| } |
| |
| bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const |
| { |
| qIntegrationDebug(); |
| switch (cap) { |
| case MultipleWindows: |
| case ForeignWindows: |
| case ThreadedPixmaps: |
| return true; |
| #if !defined(QT_NO_OPENGL) |
| case OpenGL: |
| case ThreadedOpenGL: |
| case BufferQueueingOpenGL: |
| return true; |
| #endif |
| default: |
| return QPlatformIntegration::hasCapability(cap); |
| } |
| } |
| |
| QPlatformWindow *QQnxIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const |
| { |
| screen_window_t screenWindow = reinterpret_cast<screen_window_t>(nativeHandle); |
| if (this->window(screenWindow)) { |
| qWarning() << "QWindow already created for foreign window" |
| << screenWindow; |
| return nullptr; |
| } |
| |
| return new QQnxForeignWindow(window, m_screenContext, screenWindow); |
| } |
| |
| QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const |
| { |
| qIntegrationDebug(); |
| QSurface::SurfaceType surfaceType = window->surfaceType(); |
| const bool needRootWindow = options() & RootWindow; |
| switch (surfaceType) { |
| case QSurface::RasterSurface: |
| return new QQnxRasterWindow(window, m_screenContext, needRootWindow); |
| #if !defined(QT_NO_OPENGL) |
| case QSurface::OpenGLSurface: |
| return new QQnxEglWindow(window, m_screenContext, needRootWindow); |
| #endif |
| default: |
| qFatal("QQnxWindow: unsupported window API"); |
| } |
| return 0; |
| } |
| |
| QPlatformBackingStore *QQnxIntegration::createPlatformBackingStore(QWindow *window) const |
| { |
| qIntegrationDebug(); |
| return new QQnxRasterBackingStore(window); |
| } |
| |
| #if !defined(QT_NO_OPENGL) |
| QPlatformOpenGLContext *QQnxIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const |
| { |
| qIntegrationDebug(); |
| |
| // Get color channel sizes from window format |
| QSurfaceFormat format = context->format(); |
| int alphaSize = format.alphaBufferSize(); |
| int redSize = format.redBufferSize(); |
| int greenSize = format.greenBufferSize(); |
| int blueSize = format.blueBufferSize(); |
| |
| // Check if all channels are don't care |
| if (alphaSize == -1 && redSize == -1 && greenSize == -1 && blueSize == -1) { |
| // Set color channels based on depth of window's screen |
| QQnxScreen *screen = static_cast<QQnxScreen*>(context->screen()->handle()); |
| int depth = screen->depth(); |
| if (depth == 32) { |
| // SCREEN_FORMAT_RGBA8888 |
| alphaSize = 8; |
| redSize = 8; |
| greenSize = 8; |
| blueSize = 8; |
| } else { |
| // SCREEN_FORMAT_RGB565 |
| alphaSize = 0; |
| redSize = 5; |
| greenSize = 6; |
| blueSize = 5; |
| } |
| } else { |
| // Choose best match based on supported pixel formats |
| if (alphaSize <= 0 && redSize <= 5 && greenSize <= 6 && blueSize <= 5) { |
| // SCREEN_FORMAT_RGB565 |
| alphaSize = 0; |
| redSize = 5; |
| greenSize = 6; |
| blueSize = 5; |
| } else { |
| // SCREEN_FORMAT_RGBA8888 |
| alphaSize = 8; |
| redSize = 8; |
| greenSize = 8; |
| blueSize = 8; |
| } |
| } |
| |
| // Update color channel sizes in window format |
| format.setAlphaBufferSize(alphaSize); |
| format.setRedBufferSize(redSize); |
| format.setGreenBufferSize(greenSize); |
| format.setBlueBufferSize(blueSize); |
| context->setFormat(format); |
| |
| QQnxGLContext *ctx = new QQnxGLContext(context->format(), context->shareHandle()); |
| return ctx; |
| } |
| #endif |
| |
| QPlatformInputContext *QQnxIntegration::inputContext() const |
| { |
| qIntegrationDebug(); |
| if (m_qpaInputContext) |
| return m_qpaInputContext; |
| return m_inputContext; |
| } |
| |
| void QQnxIntegration::moveToScreen(QWindow *window, int screen) |
| { |
| qIntegrationDebug() << "w =" << window << ", s =" << screen; |
| |
| // get platform window used by widget |
| QQnxWindow *platformWindow = static_cast<QQnxWindow *>(window->handle()); |
| |
| // lookup platform screen by index |
| QQnxScreen *platformScreen = m_screens.at(screen); |
| |
| // move the platform window to the platform screen |
| platformWindow->setScreen(platformScreen); |
| } |
| |
| QAbstractEventDispatcher *QQnxIntegration::createEventDispatcher() const |
| { |
| qIntegrationDebug(); |
| |
| // We transfer ownersip of the event-dispatcher to QtCoreApplication |
| QAbstractEventDispatcher *eventDispatcher = m_eventDispatcher; |
| m_eventDispatcher = 0; |
| |
| return eventDispatcher; |
| } |
| |
| QPlatformNativeInterface *QQnxIntegration::nativeInterface() const |
| { |
| return m_nativeInterface; |
| } |
| |
| #if !defined(QT_NO_CLIPBOARD) |
| QPlatformClipboard *QQnxIntegration::clipboard() const |
| { |
| qIntegrationDebug(); |
| |
| #if QT_CONFIG(qqnx_pps) |
| if (!m_clipboard) |
| m_clipboard = new QQnxClipboard; |
| #endif |
| return m_clipboard; |
| } |
| #endif |
| |
| #if QT_CONFIG(draganddrop) |
| QPlatformDrag *QQnxIntegration::drag() const |
| { |
| return m_drag; |
| } |
| #endif |
| |
| QVariant QQnxIntegration::styleHint(QPlatformIntegration::StyleHint hint) const |
| { |
| qIntegrationDebug(); |
| if ((hint == ShowIsFullScreen) && (m_options & FullScreenApplication)) |
| return true; |
| |
| return QPlatformIntegration::styleHint(hint); |
| } |
| |
| QPlatformServices * QQnxIntegration::services() const |
| { |
| return m_services; |
| } |
| |
| QWindow *QQnxIntegration::window(screen_window_t qnxWindow) const |
| { |
| qIntegrationDebug(); |
| QMutexLocker locker(&m_windowMapperMutex); |
| Q_UNUSED(locker); |
| return m_windowMapper.value(qnxWindow, 0); |
| } |
| |
| void QQnxIntegration::addWindow(screen_window_t qnxWindow, QWindow *window) |
| { |
| qIntegrationDebug(); |
| QMutexLocker locker(&m_windowMapperMutex); |
| Q_UNUSED(locker); |
| m_windowMapper.insert(qnxWindow, window); |
| } |
| |
| void QQnxIntegration::removeWindow(screen_window_t qnxWindow) |
| { |
| qIntegrationDebug(); |
| QMutexLocker locker(&m_windowMapperMutex); |
| Q_UNUSED(locker); |
| m_windowMapper.remove(qnxWindow); |
| } |
| |
| /*! |
| Get display ID for given \a display |
| |
| Returns -1 for failure, otherwise returns display ID |
| */ |
| static int getIdOfDisplay(screen_display_t display) |
| { |
| int displayId; |
| if (screen_get_display_property_iv(display, |
| SCREEN_PROPERTY_ID, |
| &displayId) == 0) { |
| return displayId; |
| } |
| return -1; |
| } |
| |
| /*! |
| Read JSON configuration file for the QNX display order |
| |
| Returns true if file was read successfully and fills \a requestedDisplays |
| */ |
| static bool getRequestedDisplays(QJsonArray &requestedDisplays) |
| { |
| // Check if display configuration file is provided |
| QByteArray json = qgetenv("QT_QPA_QNX_DISPLAY_CONFIG"); |
| if (json.isEmpty()) |
| return false; |
| |
| // Check if configuration file exists |
| QFile file(QString::fromUtf8(json)); |
| if (!file.open(QFile::ReadOnly)) { |
| qWarning() << "Could not open config file" << json << "for reading"; |
| return false; |
| } |
| |
| // Read config file and check it's json |
| const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); |
| if (!doc.isObject()) { |
| qWarning() << "Invalid config file" << json |
| << "- no top-level JSON object"; |
| return false; |
| } |
| |
| // Read the requested display order |
| const QJsonObject object = doc.object(); |
| requestedDisplays = object.value(QLatin1String("displayOrder")).toArray(); |
| |
| return true; |
| } |
| |
| /*! |
| Match \a availableDisplays with display order defined in a json file |
| pointed to by QT_QPA_QNX_DISPLAY_CONFIG. Display order must use same |
| identifiers as defined for displays in graphics.conf. Number of |
| available displays must be specified in \a displayCount |
| |
| An example configuration is below: |
| \badcode |
| { |
| "displayOrder": [ 3, 1 ] |
| } |
| \endcode |
| |
| Returns ordered list of displays. If no order was specified, returns |
| displays in the same order as in the original list. |
| */ |
| QList<screen_display_t *> QQnxIntegration::sortDisplays(screen_display_t *availableDisplays, int displayCount) |
| { |
| // Intermediate list for sorting |
| QList<screen_display_t *> allDisplays; |
| for (int i = 0; i < displayCount; i++) |
| allDisplays.append(&availableDisplays[i]); |
| |
| // Read requested display order if available |
| QJsonArray requestedDisplays; |
| if (!getRequestedDisplays(requestedDisplays)) |
| return allDisplays; |
| |
| // Go through all the requested displays IDs |
| QList<screen_display_t *> orderedDisplays; |
| for (const QJsonValue &value : qAsConst(requestedDisplays)) { |
| int requestedValue = value.toInt(); |
| |
| // Move all displays with matching ID from the intermediate list |
| // to the beginning of the ordered list |
| for (auto it = allDisplays.begin(), end = allDisplays.end(); it != end; ++it) { |
| screen_display_t *display = *it; |
| if (getIdOfDisplay(*display) == requestedValue) { |
| orderedDisplays.append(display); |
| allDisplays.erase(it); |
| break; |
| } |
| } |
| } |
| |
| // Place all unordered displays to the end of list |
| orderedDisplays.append(allDisplays); |
| |
| return orderedDisplays; |
| } |
| |
| void QQnxIntegration::createDisplays() |
| { |
| qIntegrationDebug(); |
| // Query number of displays |
| int displayCount = 0; |
| int result = screen_get_context_property_iv(m_screenContext, SCREEN_PROPERTY_DISPLAY_COUNT, |
| &displayCount); |
| Q_SCREEN_CRITICALERROR(result, "Failed to query display count"); |
| |
| if (Q_UNLIKELY(displayCount < 1)) { |
| // Never happens, even if there's no display, libscreen returns 1 |
| qFatal("QQnxIntegration: displayCount=%d", displayCount); |
| } |
| |
| // Get all displays |
| screen_display_t *displays = (screen_display_t *)alloca(sizeof(screen_display_t) * displayCount); |
| result = screen_get_context_property_pv(m_screenContext, SCREEN_PROPERTY_DISPLAYS, |
| (void **)displays); |
| QList<screen_display_t *> orderedDisplays = sortDisplays(displays, displayCount); |
| Q_SCREEN_CRITICALERROR(result, "Failed to query displays"); |
| |
| // If it's primary, we create a QScreen for it even if it's not attached |
| // since Qt will dereference QGuiApplication::primaryScreen() |
| createDisplay(*orderedDisplays[0], /*isPrimary=*/true); |
| |
| for (int i=1; i<displayCount; i++) { |
| int isAttached = 1; |
| result = screen_get_display_property_iv(*orderedDisplays[i], SCREEN_PROPERTY_ATTACHED, |
| &isAttached); |
| Q_SCREEN_CHECKERROR(result, "Failed to query display attachment"); |
| |
| if (!isAttached) { |
| qIntegrationDebug("Skipping non-attached display %d", i); |
| continue; |
| } |
| |
| qIntegrationDebug("Creating screen for display %d", i); |
| createDisplay(*orderedDisplays[i], /*isPrimary=*/false); |
| } // of displays iteration |
| } |
| |
| void QQnxIntegration::createDisplay(screen_display_t display, bool isPrimary) |
| { |
| QQnxScreen *screen = new QQnxScreen(m_screenContext, display, isPrimary); |
| m_screens.append(screen); |
| QWindowSystemInterface::handleScreenAdded(screen); |
| screen->adjustOrientation(); |
| |
| QObject::connect(m_screenEventHandler, SIGNAL(newWindowCreated(void*)), |
| screen, SLOT(newWindowCreated(void*))); |
| QObject::connect(m_screenEventHandler, SIGNAL(windowClosed(void*)), |
| screen, SLOT(windowClosed(void*))); |
| |
| QObject::connect(m_navigatorEventHandler, SIGNAL(rotationChanged(int)), screen, SLOT(setRotation(int))); |
| QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupActivated(QByteArray)), screen, SLOT(activateWindowGroup(QByteArray))); |
| QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupDeactivated(QByteArray)), screen, SLOT(deactivateWindowGroup(QByteArray))); |
| QObject::connect(m_navigatorEventHandler, SIGNAL(windowGroupStateChanged(QByteArray,Qt::WindowState)), |
| screen, SLOT(windowGroupStateChanged(QByteArray,Qt::WindowState))); |
| } |
| |
| void QQnxIntegration::removeDisplay(QQnxScreen *screen) |
| { |
| Q_CHECK_PTR(screen); |
| Q_ASSERT(m_screens.contains(screen)); |
| m_screens.removeAll(screen); |
| QWindowSystemInterface::handleScreenRemoved(screen); |
| } |
| |
| void QQnxIntegration::destroyDisplays() |
| { |
| qIntegrationDebug(); |
| Q_FOREACH (QQnxScreen *screen, m_screens) { |
| QWindowSystemInterface::handleScreenRemoved(screen); |
| } |
| m_screens.clear(); |
| } |
| |
| QQnxScreen *QQnxIntegration::screenForNative(screen_display_t qnxScreen) const |
| { |
| Q_FOREACH (QQnxScreen *screen, m_screens) { |
| if (screen->nativeDisplay() == qnxScreen) |
| return screen; |
| } |
| |
| return 0; |
| } |
| |
| QQnxScreen *QQnxIntegration::primaryDisplay() const |
| { |
| return m_screens.first(); |
| } |
| |
| QQnxIntegration::Options QQnxIntegration::options() const |
| { |
| return m_options; |
| } |
| |
| screen_context_t QQnxIntegration::screenContext() |
| { |
| return m_screenContext; |
| } |
| |
| QByteArray QQnxIntegration::screenContextId() |
| { |
| return m_screenContextId; |
| } |
| |
| QQnxNavigatorEventHandler *QQnxIntegration::navigatorEventHandler() |
| { |
| return m_navigatorEventHandler; |
| } |
| |
| bool QQnxIntegration::supportsNavigatorEvents() const |
| { |
| // If QQNX_PPS is defined then we have navigator |
| return m_navigator != 0; |
| } |
| |
| #if QT_CONFIG(opengl) |
| void QQnxIntegration::createEglDisplay() |
| { |
| qIntegrationDebug(); |
| |
| // Initialize connection to EGL |
| m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); |
| if (Q_UNLIKELY(m_eglDisplay == EGL_NO_DISPLAY)) |
| qFatal("QQnxiIntegration: failed to obtain EGL display: %x", eglGetError()); |
| |
| EGLBoolean eglResult = eglInitialize(m_eglDisplay, 0, 0); |
| if (Q_UNLIKELY(eglResult != EGL_TRUE)) |
| qFatal("QQnxIntegration: failed to initialize EGL display, err=%d", eglGetError()); |
| } |
| |
| void QQnxIntegration::destroyEglDisplay() |
| { |
| qIntegrationDebug(); |
| |
| // Close connection to EGL |
| eglTerminate(m_eglDisplay); |
| } |
| #endif |
| |
| QT_END_NAMESPACE |