diff options
Diffstat (limited to 'src/plugins/platforms/qnx')
20 files changed, 505 insertions, 525 deletions
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro index e2c25add0b..100db54a5c 100644 --- a/src/plugins/platforms/qnx/qnx.pro +++ b/src/plugins/platforms/qnx/qnx.pro @@ -5,18 +5,7 @@ QT += platformsupport-private core-private gui-private # Uncomment this to build with support for IMF once it becomes available in the BBNDK #CONFIG += qqnx_imf -# Uncomment this to build with support for PPS based platform integration -#CONFIG += qqnx_pps - -CONFIG(blackberry) { - CONFIG += qqnx_pps - - # Uncomment following line to enable screen event - # handling through a dedicated thread. - # CONFIG += qqnx_screeneventthread -} else { - CONFIG += qqnx_screeneventthread -} +!blackberry:CONFIG += qqnx_screeneventthread # Uncomment these to enable debugging output for various aspects of the plugin #DEFINES += QQNXBPSEVENTFILTER_DEBUG @@ -33,7 +22,6 @@ CONFIG(blackberry) { #DEFINES += QQNXNAVIGATOREVENTNOTIFIER_DEBUG #DEFINES += QQNXNAVIGATOR_DEBUG #DEFINES += QQNXRASTERBACKINGSTORE_DEBUG -#DEFINES += QQNXROOTWINDOW_DEBUG #DEFINES += QQNXSCREENEVENTTHREAD_DEBUG #DEFINES += QQNXSCREENEVENT_DEBUG #DEFINES += QQNXSCREEN_DEBUG @@ -50,7 +38,6 @@ SOURCES = main.cpp \ qqnxscreen.cpp \ qqnxwindow.cpp \ qqnxrasterbackingstore.cpp \ - qqnxrootwindow.cpp \ qqnxscreeneventhandler.cpp \ qqnxnativeinterface.cpp \ qqnxnavigatoreventhandler.cpp \ @@ -67,7 +54,6 @@ HEADERS = main.h \ qqnxscreen.h \ qqnxwindow.h \ qqnxrasterbackingstore.h \ - qqnxrootwindow.h \ qqnxscreeneventhandler.h \ qqnxnativeinterface.h \ qqnxnavigatoreventhandler.h \ @@ -144,7 +130,8 @@ CONFIG(qqnx_pps) { qqnxclipboard.h \ qqnxbuttoneventnotifier.h - LIBS += -lpps -lclipboard + LIBS += -lpps + !contains(DEFINES, QT_NO_CLIPBOARD): LIBS += -lclipboard CONFIG(qqnx_imf) { DEFINES += QQNX_IMF diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.cpp b/src/plugins/platforms/qnx/qqnxeglwindow.cpp index e8fcdd692b..b57227a60b 100644 --- a/src/plugins/platforms/qnx/qqnxeglwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxeglwindow.cpp @@ -42,6 +42,7 @@ #include "qqnxeglwindow.h" #include "qqnxscreen.h" +#include "qqnxglcontext.h" #include <QDebug> @@ -55,14 +56,15 @@ QT_BEGIN_NAMESPACE -QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context) : - QQnxWindow(window, context), - m_requestedBufferSize(window->geometry().size()), +QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context, bool needRootWindow) : + QQnxWindow(window, context, needRootWindow), m_platformOpenGLContext(0), m_newSurfaceRequested(true), m_eglSurface(EGL_NO_SURFACE) { initWindow(); + m_requestedBufferSize = screen()->rootWindow() == this ? + screen()->geometry().size() : window->geometry().size(); } QQnxEglWindow::~QQnxEglWindow() @@ -98,8 +100,6 @@ void QQnxEglWindow::createEGLSurface() QQnxGLContext::checkEGLError("eglCreateWindowSurface"); qFatal("QQNX: failed to create EGL surface, err=%d", eglGetError()); } - - screen()->onWindowPost(0); } void QQnxEglWindow::destroyEGLSurface() @@ -146,6 +146,9 @@ EGLSurface QQnxEglWindow::getSurface() void QQnxEglWindow::setGeometry(const QRect &rect) { + //If this is the root window, it has to be shown fullscreen + const QRect &newGeometry = screen()->rootWindow() == this ? screen()->geometry() : rect; + //We need to request that the GL context updates // the EGLsurface on which it is rendering. { @@ -153,11 +156,11 @@ void QQnxEglWindow::setGeometry(const QRect &rect) // setting m_requestedBufferSize and therefore extended the scope to include // that test. const QMutexLocker locker(&m_mutex); - m_requestedBufferSize = rect.size(); - if (m_platformOpenGLContext != 0 && bufferSize() != rect.size()) + m_requestedBufferSize = newGeometry.size(); + if (m_platformOpenGLContext != 0 && bufferSize() != newGeometry.size()) m_newSurfaceRequested.testAndSetRelease(false, true); } - QQnxWindow::setGeometry(rect); + QQnxWindow::setGeometry(newGeometry); } QSize QQnxEglWindow::requestedBufferSize() const @@ -166,6 +169,13 @@ QSize QQnxEglWindow::requestedBufferSize() const return m_requestedBufferSize; } +void QQnxEglWindow::adjustBufferSize() +{ + const QSize windowSize = window()->size(); + if (windowSize != bufferSize()) + setBufferSize(windowSize); +} + void QQnxEglWindow::setPlatformOpenGLContext(QQnxGLContext *platformOpenGLContext) { // This function does not take ownership of the platform gl context. @@ -175,6 +185,9 @@ void QQnxEglWindow::setPlatformOpenGLContext(QQnxGLContext *platformOpenGLContex int QQnxEglWindow::pixelFormat() const { + if (!m_platformOpenGLContext) //The platform GL context was not set yet + return -1; + const QSurfaceFormat format = m_platformOpenGLContext->format(); // Extract size of color channels from window format const int redSize = format.redBufferSize(); diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.h b/src/plugins/platforms/qnx/qqnxeglwindow.h index e7dae6a458..fc53afcd7a 100644 --- a/src/plugins/platforms/qnx/qqnxeglwindow.h +++ b/src/plugins/platforms/qnx/qqnxeglwindow.h @@ -43,8 +43,6 @@ #define QQNXEGLWINDOW_H #include "qqnxwindow.h" -#include "qqnxglcontext.h" - #include <QtCore/QMutex> QT_BEGIN_NAMESPACE @@ -54,7 +52,7 @@ class QQnxGLContext; class QQnxEglWindow : public QQnxWindow { public: - QQnxEglWindow(QWindow *window, screen_context_t context); + QQnxEglWindow(QWindow *window, screen_context_t context, bool needRootWindow); ~QQnxEglWindow(); void createEGLSurface(); @@ -70,7 +68,7 @@ public: // Called by QQnxGLContext::createSurface() QSize requestedBufferSize() const; - WindowType windowType() const Q_DECL_OVERRIDE { return EGL; } + void adjustBufferSize(); protected: int pixelFormat() const; diff --git a/src/plugins/platforms/qnx/qqnxglcontext.h b/src/plugins/platforms/qnx/qqnxglcontext.h index ff57861498..2b12657da9 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.h +++ b/src/plugins/platforms/qnx/qqnxglcontext.h @@ -75,6 +75,8 @@ public: static EGLDisplay getEglDisplay(); EGLConfig getEglConfig() const { return m_eglConfig;} + EGLContext getEglContext() const { return m_eglContext; } + private: //Can be static because different displays returne the same handle static EGLDisplay ms_eglDisplay; diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index 09054b9eb9..5695ef433a 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -122,6 +122,17 @@ static inline QQnxIntegration::Options parseOptions(const QStringList ¶mList if (!paramList.contains(QLatin1String("no-fullscreen"))) { options |= QQnxIntegration::FullScreenApplication; } + +// On Blackberry the first window is treated as a root window +#ifdef Q_OS_BLACKBERRY + if (!paramList.contains(QLatin1String("no-rootwindow"))) { + options |= QQnxIntegration::RootWindow; + } +#else + if (paramList.contains(QLatin1String("rootwindow"))) { + options |= QQnxIntegration::RootWindow; + } +#endif return options; } @@ -326,9 +337,10 @@ bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const { qIntegrationDebug() << Q_FUNC_INFO; switch (cap) { + case MultipleWindows: case ThreadedPixmaps: return true; -#if defined(QT_OPENGL_ES) +#if !defined(QT_NO_OPENGL) case OpenGL: case ThreadedOpenGL: case BufferQueueingOpenGL: @@ -343,12 +355,13 @@ QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const { qIntegrationDebug() << Q_FUNC_INFO; QSurface::SurfaceType surfaceType = window->surfaceType(); + const bool needRootWindow = options() & RootWindow; switch (surfaceType) { case QSurface::RasterSurface: - return new QQnxRasterWindow(window, m_screenContext); + return new QQnxRasterWindow(window, m_screenContext, needRootWindow); #if !defined(QT_NO_OPENGL) case QSurface::OpenGLSurface: - return new QQnxEglWindow(window, m_screenContext); + return new QQnxEglWindow(window, m_screenContext, needRootWindow); #endif default: qFatal("QQnxWindow: unsupported window API"); diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h index ab0d6a3156..8b5614fe4f 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.h +++ b/src/plugins/platforms/qnx/qqnxintegration.h @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2011 - 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -84,7 +84,8 @@ class QQnxIntegration : public QPlatformIntegration public: enum Option { // Options to be passed on command line. NoOptions = 0x0, - FullScreenApplication = 0x1 + FullScreenApplication = 0x1, + RootWindow = 0x2 }; Q_DECLARE_FLAGS(Options, Option) explicit QQnxIntegration(const QStringList ¶mList); diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp index 4dd3444832..6e7fc35a82 100644 --- a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp +++ b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp @@ -41,8 +41,11 @@ #include "qqnxnativeinterface.h" +#include "qqnxglcontext.h" #include "qqnxscreen.h" +#include "qqnxwindow.h" +#include <QtGui/QOpenGLContext> #include <QtGui/QScreen> #include <QtGui/QWindow> @@ -70,4 +73,20 @@ void *QQnxNativeInterface::nativeResourceForScreen(const QByteArray &resource, Q return 0; } +void *QQnxNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) +{ + if (resource == "eglcontext" && context) + return static_cast<QQnxGLContext*>(context->handle())->getEglContext(); + + return 0; +} + +void QQnxNativeInterface::setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value) +{ + if (name == QStringLiteral("mmRendererWindowName")) { + QQnxWindow *qnxWindow = static_cast<QQnxWindow*>(window); + qnxWindow->setMMRendererWindowName(value.toString()); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.h b/src/plugins/platforms/qnx/qqnxnativeinterface.h index 6692da2576..dfd386214e 100644 --- a/src/plugins/platforms/qnx/qqnxnativeinterface.h +++ b/src/plugins/platforms/qnx/qqnxnativeinterface.h @@ -51,6 +51,8 @@ class QQnxNativeInterface : public QPlatformNativeInterface public: void *nativeResourceForWindow(const QByteArray &resource, QWindow *window); void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen); + void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context); + void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp index 16ff9d7519..1f974b268d 100644 --- a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp @@ -54,8 +54,8 @@ QT_BEGIN_NAMESPACE -QQnxRasterWindow::QQnxRasterWindow(QWindow *window, screen_context_t context) : - QQnxWindow(window, context), +QQnxRasterWindow::QQnxRasterWindow(QWindow *window, screen_context_t context, bool needRootWindow) : + QQnxWindow(window, context, needRootWindow), m_currentBufferIndex(-1), m_previousBufferIndex(-1) { @@ -115,9 +115,6 @@ void QQnxRasterWindow::post(const QRegion &dirty) // Save modified region and clear scrolled region m_previousDirty = dirty; m_scrolled = QRegion(); - // Notify screen that window posted - if (screen() != 0) - screen()->onWindowPost(this); if (m_cover) m_cover->updateCover(); @@ -169,6 +166,15 @@ QQnxBuffer &QQnxRasterWindow::renderBuffer() return m_buffers[m_currentBufferIndex]; } +void QQnxRasterWindow::adjustBufferSize() +{ + // When having a raster window we don't need any buffers, since + // Qt will draw to the parent TLW backing store. + const QSize windowSize = m_parentWindow ? QSize(1,1) : window()->size(); + if (windowSize != bufferSize()) + setBufferSize(windowSize); +} + int QQnxRasterWindow::pixelFormat() const { return screen()->nativeFormat(); diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.h b/src/plugins/platforms/qnx/qqnxrasterwindow.h index 8bd42bc320..ad34b3ccf2 100644 --- a/src/plugins/platforms/qnx/qqnxrasterwindow.h +++ b/src/plugins/platforms/qnx/qqnxrasterwindow.h @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE class QQnxRasterWindow : public QQnxWindow { public: - QQnxRasterWindow(QWindow *window, screen_context_t context); + QQnxRasterWindow(QWindow *window, screen_context_t context, bool needRootWindow); void post(const QRegion &dirty); @@ -60,7 +60,7 @@ public: bool hasBuffers() const { return !bufferSize().isEmpty(); } - WindowType windowType() const Q_DECL_OVERRIDE { return Raster; } + void adjustBufferSize(); protected: int pixelFormat() const; @@ -69,6 +69,9 @@ protected: // Copies content from the previous buffer (back buffer) to the current buffer (front buffer) void blitPreviousToCurrent(const QRegion ®ion, int dx, int dy, bool flush=false); + void blitHelper(QQnxBuffer &source, QQnxBuffer &target, const QPoint &sourceOffset, + const QPoint &targetOffset, const QRegion ®ion, bool flush = false); + private: QRegion m_previousDirty; QRegion m_scrolled; diff --git a/src/plugins/platforms/qnx/qqnxrootwindow.cpp b/src/plugins/platforms/qnx/qqnxrootwindow.cpp deleted file mode 100644 index b3f5c87176..0000000000 --- a/src/plugins/platforms/qnx/qqnxrootwindow.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2011 - 2012 Research In Motion -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qqnxrootwindow.h" - -#include "qqnxscreen.h" - -#include <QtCore/QUuid> -#include <QtCore/QDebug> - -#if defined(QQNXROOTWINDOW_DEBUG) -#define qRootWindowDebug qDebug -#else -#define qRootWindowDebug QT_NO_QDEBUG_MACRO -#endif - -#include <errno.h> -#include <unistd.h> - -static const int MAGIC_ZORDER_FOR_NO_NAV = 10; - -QQnxRootWindow::QQnxRootWindow(const QQnxScreen *screen) - : m_screen(screen), - m_window(0), - m_windowGroupName(), - m_translucent(false) -{ - qRootWindowDebug() << Q_FUNC_INFO; - // Create one top-level QNX window to act as a container for child windows - // since navigator only supports one application window - errno = 0; - int result = screen_create_window(&m_window, m_screen->nativeContext()); - int val[2]; - if (result != 0) - qFatal("QQnxRootWindow: failed to create window, errno=%d", errno); - - // Move window to proper display - errno = 0; - screen_display_t display = m_screen->nativeDisplay(); - result = screen_set_window_property_pv(m_window, SCREEN_PROPERTY_DISPLAY, (void **)&display); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window display, errno=%d", errno); - - // Make sure window is above navigator but below keyboard if running as root - // since navigator won't automatically set our z-order in this case - if (getuid() == 0) { - errno = 0; - val[0] = MAGIC_ZORDER_FOR_NO_NAV; - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ZORDER, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window z-order, errno=%d", errno); - } - - // Window won't be visible unless it has some buffers so make one dummy buffer that is 1x1 - errno = 0; - val[0] = SCREEN_USAGE_NATIVE; - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_USAGE, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window buffer usage, errno=%d", errno); - - errno = 0; - val[0] = m_screen->nativeFormat(); - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_FORMAT, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window pixel format, errno=%d", errno); - - errno = 0; - val[0] = 1; - val[1] = 1; - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_BUFFER_SIZE, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window buffer size, errno=%d", errno); - - errno = 0; - result = screen_create_window_buffers(m_window, 1); - if (result != 0) - qFatal("QQNX: failed to create window buffer, errno=%d", errno); - - // Window is always the size of the display - errno = 0; - QRect geometry = m_screen->geometry(); - val[0] = geometry.width(); - val[1] = geometry.height(); - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SIZE, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window size, errno=%d", errno); - - // Fill the window with solid black. Note that the LSB of the pixel value - // 0x00000000 just happens to be 0x00, so if and when this root window's - // alpha blending mode is changed from None to Source-Over, it will then - // be interpreted as transparent. - errno = 0; - val[0] = 0; - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_COLOR, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window colour, errno=%d", errno); - - // Make the window opaque - errno = 0; - val[0] = SCREEN_TRANSPARENCY_NONE; - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window transparency, errno=%d", errno); - - // Set the swap interval to 1 - errno = 0; - val[0] = 1; - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SWAP_INTERVAL, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window swap interval, errno=%d", errno); - - // Set viewport size equal to window size but move outside buffer so the fill colour is used exclusively - errno = 0; - val[0] = geometry.width(); - val[1] = geometry.height(); - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window source size, errno=%d", errno); - - errno = 0; - val[0] = 0; - val[1] = 0; - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_POSITION, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window source position, errno=%d", errno); - - // Optionally disable the screen power save - bool ok = false; - const int disablePowerSave = qgetenv("QQNX_DISABLE_POWER_SAVE").toInt(&ok); - if (ok && disablePowerSave) { - const int mode = SCREEN_IDLE_MODE_KEEP_AWAKE; - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_IDLE_MODE, &mode); - if (result != 0) - qWarning("QQnxRootWindow: failed to disable power saving mode"); - } - - createWindowGroup(); - - // Don't post yet. This will be lazily done from QQnxScreen upon first posting of - // a child window. Doing it now pre-emptively would create a flicker if one of - // the QWindow's about to be created sets its Qt::WA_TranslucentBackground flag - // and immediately triggers the buffer re-creation in makeTranslucent(). -} - -void QQnxRootWindow::makeTranslucent() -{ - if (m_translucent) - return; - - int result; - - errno = 0; - const int val = SCREEN_TRANSPARENCY_DISCARD; - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, &val); - if (result != 0) { - qFatal("QQnxRootWindow: failed to set window transparency, errno=%d", errno); - } - - m_translucent = true; - post(); -} - -QQnxRootWindow::~QQnxRootWindow() -{ - // Cleanup top-level QNX window - screen_destroy_window(m_window); -} - -void QQnxRootWindow::post() const -{ - qRootWindowDebug() << Q_FUNC_INFO; - errno = 0; - screen_buffer_t buffer; - int result = screen_get_window_property_pv(m_window, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&buffer); - if (result != 0) - qFatal("QQnxRootWindow: failed to query window buffer, errno=%d", errno); - - errno = 0; - int dirtyRect[] = {0, 0, 1, 1}; - result = screen_post_window(m_window, buffer, 1, dirtyRect, 0); - if (result != 0) - qFatal("QQNX: failed to post window buffer, errno=%d", errno); -} - -void QQnxRootWindow::flush() const -{ - qRootWindowDebug() << Q_FUNC_INFO; - // Force immediate display update - errno = 0; - int result = screen_flush_context(m_screen->nativeContext(), 0); - if (result != 0) - qFatal("QQnxRootWindow: failed to flush context, errno=%d", errno); -} - -void QQnxRootWindow::setRotation(int rotation) -{ - qRootWindowDebug() << Q_FUNC_INFO << "angle =" << rotation; - errno = 0; - int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ROTATION, &rotation); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window rotation, errno=%d", errno); -} - -void QQnxRootWindow::resize(const QSize &size) -{ - errno = 0; - int val[] = {size.width(), size.height()}; - int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SIZE, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window size, errno=%d", errno); - - errno = 0; - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, val); - if (result != 0) - qFatal("QQnxRootWindow: failed to set window source size, errno=%d", errno); - - // NOTE: display will update when child windows relayout and repaint -} - -void QQnxRootWindow::createWindowGroup() -{ - // Generate a random window group name - m_windowGroupName = QUuid::createUuid().toString().toLatin1(); - - // Create window group so child windows can be parented by container window - errno = 0; - int result = screen_create_window_group(m_window, m_windowGroupName.constData()); - if (result != 0) - qFatal("QQnxRootWindow: failed to create app window group, errno=%d", errno); -} diff --git a/src/plugins/platforms/qnx/qqnxrootwindow.h b/src/plugins/platforms/qnx/qqnxrootwindow.h deleted file mode 100644 index ea7c7faace..0000000000 --- a/src/plugins/platforms/qnx/qqnxrootwindow.h +++ /dev/null @@ -1,85 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2011 - 2012 Research In Motion -** Contact: http://www.qt-project.org/legal -** -** 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 Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQNXROOTWINDOW_H -#define QQNXROOTWINDOW_H - -#include <QtCore/QByteArray> -#include <QtCore/QRect> - -#include <screen/screen.h> - -QT_BEGIN_NAMESPACE - -class QQnxScreen; - -class QQnxRootWindow -{ -public: - QQnxRootWindow(const QQnxScreen *screen); - ~QQnxRootWindow(); - - screen_window_t nativeHandle() const { return m_window; } - - void post() const; - void flush() const; - - void setRotation(int rotation); - - void resize(const QSize &size); - - void makeTranslucent(); - - QByteArray groupName() const { return m_windowGroupName; } - -private: - void createWindowGroup(); - - const QQnxScreen *m_screen; - screen_window_t m_window; - QByteArray m_windowGroupName; - - bool m_translucent; -}; - -QT_END_NAMESPACE - -#endif // QQNXROOTWINDOW_H diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp index dd8cf2131a..a09d6ce1f5 100644 --- a/src/plugins/platforms/qnx/qqnxscreen.cpp +++ b/src/plugins/platforms/qnx/qqnxscreen.cpp @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2011 - 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -119,11 +119,43 @@ static QSize determineScreenSize(screen_display_t display, bool primaryScreen) { #endif } +static QQnxWindow *findMultimediaWindow(const QList<QQnxWindow*> windows, + const QByteArray &mmWindowId) +{ + Q_FOREACH (QQnxWindow *sibling, windows) { + if (sibling->mmRendererWindowName() == mmWindowId) + return sibling; + + QQnxWindow *mmWindow = findMultimediaWindow(sibling->children(), mmWindowId); + + if (mmWindow) + return mmWindow; + } + + return 0; +} + +static QQnxWindow *findMultimediaWindow(const QList<QQnxWindow*> windows, + screen_window_t mmWindowId) +{ + Q_FOREACH (QQnxWindow *sibling, windows) { + if (sibling->mmRendererWindow() == mmWindowId) + return sibling; + + QQnxWindow *mmWindow = findMultimediaWindow(sibling->children(), mmWindowId); + + if (mmWindow) + return mmWindow; + } + + return 0; +} + QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display, bool primaryScreen) : m_screenContext(screenContext), m_display(display), + m_rootWindow(0), m_primaryScreen(primaryScreen), - m_posted(false), m_keyboardHeight(0), m_nativeOrientation(Qt::PrimaryOrientation), m_coverWindow(0), @@ -260,7 +292,8 @@ void QQnxScreen::setRotation(int rotation) { qScreenDebug() << Q_FUNC_INFO << "orientation =" << rotation; // Check if rotation changed - if (m_currentRotation != rotation) { + // We only want to rotate if we are the primary screen + if (m_currentRotation != rotation && isPrimaryScreen()) { // Update rotation of root window if (rootWindow()) rootWindow()->setRotation(rotation); @@ -280,15 +313,13 @@ void QQnxScreen::setRotation(int rotation) if (isOrthogonal(m_currentRotation, rotation)) { qScreenDebug() << Q_FUNC_INFO << "resize, size =" << m_currentGeometry.size(); if (rootWindow()) - rootWindow()->resize(m_currentGeometry.size()); + rootWindow()->setGeometry(QRect(QPoint(0,0), m_currentGeometry.size())); - if (m_primaryScreen) - resizeWindows(previousScreenGeometry); + resizeWindows(previousScreenGeometry); } else { // TODO: Find one global place to flush display updates // Force immediate display update if no geometry changes required - if (rootWindow()) - rootWindow()->flush(); + screen_flush_context(nativeContext(), 0); } // Save new rotation @@ -458,6 +489,8 @@ void QQnxScreen::removeWindow(QQnxWindow *window) if (window != m_coverWindow) { const int numWindowsRemoved = m_childWindows.removeAll(window); + if (window == m_rootWindow) //We just removed the root window + m_rootWindow = 0; //TODO we need a new root window ;) if (numWindowsRemoved > 0) updateHierarchy(); } else { @@ -493,13 +526,15 @@ void QQnxScreen::updateHierarchy() QList<QQnxWindow*>::const_iterator it; int result; - int topZorder; + int topZorder = 0; errno = 0; - if (isPrimaryScreen()) { + if (rootWindow()) { result = screen_get_window_property_iv(rootWindow()->nativeHandle(), SCREEN_PROPERTY_ZORDER, &topZorder); - if (result != 0) - qFatal("QQnxScreen: failed to query root window z-order, errno=%d", errno); + if (result != 0) { //This can happen if we use winId in QWidgets + topZorder = 10; + qWarning("QQnxScreen: failed to query root window z-order, errno=%d", errno); + } } else { topZorder = 0; //We do not need z ordering on the secondary screen, because only one window //is supported there @@ -507,16 +542,17 @@ void QQnxScreen::updateHierarchy() topZorder++; // root window has the lowest z-order in the windowgroup + int underlayZorder = -1; // Underlays sit immediately above the root window in the z-ordering Q_FOREACH (screen_window_t underlay, m_underlays) { // Do nothing when this fails. This can happen if we have stale windows in m_underlays, // which in turn can happen because a window was removed but we didn't get a notification // yet. - screen_set_window_property_iv(underlay, SCREEN_PROPERTY_ZORDER, &topZorder); - topZorder++; + screen_set_window_property_iv(underlay, SCREEN_PROPERTY_ZORDER, &underlayZorder); + underlayZorder--; } - // Normal Qt windows come next above underlays in the z-ordering + // Normal Qt windows come next above the root window z-ordering for (it = m_childWindows.constBegin(); it != m_childWindows.constEnd(); ++it) (*it)->updateZorder(topZorder); @@ -532,20 +568,6 @@ void QQnxScreen::updateHierarchy() screen_flush_context( m_screenContext, 0 ); } -void QQnxScreen::onWindowPost(QQnxWindow *window) -{ - qScreenDebug() << Q_FUNC_INFO; - Q_UNUSED(window) - - // post app window (so navigator will show it) after first child window - // has posted; this only needs to happen once as the app window's content - // never changes - if (!m_posted && rootWindow()) { - rootWindow()->post(); - m_posted = true; - } -} - void QQnxScreen::adjustOrientation() { if (!m_primaryScreen) @@ -585,6 +607,19 @@ void QQnxScreen::addUnderlayWindow(screen_window_t window) updateHierarchy(); } +void QQnxScreen::addMultimediaWindow(const QByteArray &id, screen_window_t window) +{ + // find the QnxWindow this mmrenderer window is related to + QQnxWindow *mmWindow = findMultimediaWindow(m_childWindows, id); + + if (!mmWindow) + return; + + mmWindow->setMMRendererWindow(window); + + updateHierarchy(); +} + void QQnxScreen::removeOverlayOrUnderlayWindow(screen_window_t window) { const int numRemoved = m_overlays.removeAll(window) + m_underlays.removeAll(window); @@ -610,17 +645,35 @@ void QQnxScreen::newWindowCreated(void *window) zorder = 0; } + char windowNameBuffer[256] = { 0 }; + QByteArray windowName; + + if (screen_get_window_property_cv(windowHandle, SCREEN_PROPERTY_ID_STRING, + sizeof(windowNameBuffer) - 1, windowNameBuffer) != 0) { + qWarning("QQnx: Failed to get id for window, errno=%d", errno); + } + + windowName = QByteArray(windowNameBuffer); + if (display == nativeDisplay()) { // A window was created on this screen. If we don't know about this window yet, it means // it was not created by Qt, but by some foreign library like the multimedia renderer, which // creates an overlay window when playing a video. // - // Treat all foreign windows as overlays or underlays here. + // Treat all foreign windows as overlays, underlays or as windows + // created by the BlackBerry QtMultimedia plugin. + // + // In the case of the BlackBerry QtMultimedia plugin, we need to + // "attach" the foreign created mmrenderer window to the correct + // platform window (usually the one belonging to QVideoWidget) to + // ensure proper z-ordering. // - // Assume that if a foreign window already has a Z-Order both negative and + // Otherwise, assume that if a foreign window already has a Z-Order both negative and // less than the default Z-Order installed by mmrender on windows it creates, // the windows should be treated as an underlay. Otherwise, we treat it as an overlay. - if (!findWindow(windowHandle)) { + if (!windowName.isEmpty() && windowName.startsWith("BbVideoWindowControl")) { + addMultimediaWindow(windowName, windowHandle); + } else if (!findWindow(windowHandle)) { if (zorder <= MAX_UNDERLAY_ZORDER) addUnderlayWindow(windowHandle); else @@ -634,7 +687,13 @@ void QQnxScreen::windowClosed(void *window) { Q_ASSERT(thread() == QThread::currentThread()); const screen_window_t windowHandle = reinterpret_cast<screen_window_t>(window); - removeOverlayOrUnderlayWindow(windowHandle); + + QQnxWindow *mmWindow = findMultimediaWindow(m_childWindows, windowHandle); + + if (mmWindow) + mmWindow->clearMMRendererWindow(); + else + removeOverlayOrUnderlayWindow(windowHandle); } void QQnxScreen::windowGroupStateChanged(const QByteArray &id, Qt::WindowState state) @@ -644,7 +703,7 @@ void QQnxScreen::windowGroupStateChanged(const QByteArray &id, Qt::WindowState s if (!rootWindow() || id != rootWindow()->groupName()) return; - QWindow * const window = topMostChildWindow(); + QWindow * const window = rootWindow()->window(); if (!window) return; @@ -659,7 +718,7 @@ void QQnxScreen::activateWindowGroup(const QByteArray &id) if (!rootWindow() || id != rootWindow()->groupName()) return; - QWindow * const window = topMostChildWindow(); + QWindow * const window = rootWindow()->window(); if (!window) return; @@ -686,18 +745,28 @@ void QQnxScreen::deactivateWindowGroup(const QByteArray &id) Q_FOREACH (QQnxWindow *childWindow, m_childWindows) childWindow->setExposed(false); - QWindowSystemInterface::handleWindowActivated(0); + QWindowSystemInterface::handleWindowActivated(rootWindow()->window()); } -QSharedPointer<QQnxRootWindow> QQnxScreen::rootWindow() const +QQnxWindow *QQnxScreen::rootWindow() const { - // We only create the root window if we are the primary display. - if (m_primaryScreen && !m_rootWindow) - m_rootWindow = QSharedPointer<QQnxRootWindow>(new QQnxRootWindow(this)); - return m_rootWindow; } +void QQnxScreen::setRootWindow(QQnxWindow *window) +{ + // Optionally disable the screen power save + bool ok = false; + const int disablePowerSave = qgetenv("QQNX_DISABLE_POWER_SAVE").toInt(&ok); + if (ok && disablePowerSave) { + const int mode = SCREEN_IDLE_MODE_KEEP_AWAKE; + int result = screen_set_window_property_iv(window->nativeHandle(), SCREEN_PROPERTY_IDLE_MODE, &mode); + if (result != 0) + qWarning("QQnxRootWindow: failed to disable power saving mode"); + } + m_rootWindow = window; +} + QWindow * QQnxScreen::topMostChildWindow() const { if (!m_childWindows.isEmpty()) { diff --git a/src/plugins/platforms/qnx/qqnxscreen.h b/src/plugins/platforms/qnx/qqnxscreen.h index e11030ea0a..61c47e6c72 100644 --- a/src/plugins/platforms/qnx/qqnxscreen.h +++ b/src/plugins/platforms/qnx/qqnxscreen.h @@ -44,7 +44,7 @@ #include <qpa/qplatformscreen.h> -#include "qqnxrootwindow.h" +#include "qqnxwindow.h" #include <QtCore/QObject> #include <QtCore/QScopedPointer> @@ -91,10 +91,10 @@ public: void lowerWindow(QQnxWindow *window); void updateHierarchy(); - void onWindowPost(QQnxWindow *window); void adjustOrientation(); - QSharedPointer<QQnxRootWindow> rootWindow() const; + QQnxWindow *rootWindow() const; + void setRootWindow(QQnxWindow*); QPlatformCursor *cursor() const; @@ -119,15 +119,15 @@ private: void resizeWindows(const QRect &previousScreenGeometry); void addOverlayWindow(screen_window_t window); void addUnderlayWindow(screen_window_t window); + void addMultimediaWindow(const QByteArray &id, screen_window_t window); void removeOverlayOrUnderlayWindow(screen_window_t window); QWindow *topMostChildWindow() const; screen_context_t m_screenContext; screen_display_t m_display; - mutable QSharedPointer<QQnxRootWindow> m_rootWindow; + QQnxWindow *m_rootWindow; const bool m_primaryScreen; - bool m_posted; int m_initialRotation; int m_currentRotation; diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index a5d6db0985..37071d825c 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -40,6 +40,9 @@ ****************************************************************************/ #include "qqnxscreeneventhandler.h" +#if defined(QQNX_SCREENEVENTTHREAD) +#include "qqnxscreeneventthread.h" +#endif #include "qqnxintegration.h" #include "qqnxkeytranslator.h" #include "qqnxscreen.h" @@ -64,6 +67,9 @@ QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration) , m_lastButtonState(Qt::NoButton) , m_lastMouseWindow(0) , m_touchDevice(0) +#if defined(QQNX_SCREENEVENTTHREAD) + , m_eventThread(0) +#endif { // Create a touch device m_touchDevice = new QTouchDevice; @@ -136,6 +142,10 @@ bool QQnxScreenEventHandler::handleEvent(screen_event_t event, int qnxType) handleDisplayEvent(event); break; + case SCREEN_EVENT_PROPERTY: + handlePropertyEvent(event); + break; + default: // event ignored qScreenEventDebug() << Q_FUNC_INFO << "unknown event" << qnxType; @@ -189,6 +199,43 @@ void QQnxScreenEventHandler::injectKeyboardEvent(int flags, int sym, int modifie } } +#if defined(QQNX_SCREENEVENTTHREAD) +void QQnxScreenEventHandler::setScreenEventThread(QQnxScreenEventThread *eventThread) +{ + m_eventThread = eventThread; +} + +void QQnxScreenEventHandler::processEventsFromScreenThread() +{ + if (!m_eventThread) + return; + + QQnxScreenEventArray *events = m_eventThread->lock(); + + for (int i = 0; i < events->size(); ++i) { + screen_event_t event = events->at(i); + if (!event) + continue; + (*events)[i] = 0; + + m_eventThread->unlock(); + + long result = 0; + QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); + bool handled = dispatcher && dispatcher->filterNativeEvent(QByteArrayLiteral("screen_event_t"), event, &result); + if (!handled) + handleEvent(event); + screen_destroy_event(event); + + m_eventThread->lock(); + } + + events->clear(); + + m_eventThread->unlock(); +} +#endif + void QQnxScreenEventHandler::handleKeyboardEvent(screen_event_t event) { // get flags of key event @@ -412,11 +459,20 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType) if (w) { // get size of screen which contains window QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(w); - QSizeF screenSize = platformScreen->physicalSize(); + QSizeF screenSize = platformScreen->geometry().size(); // update cached position of current touch point - m_touchPoints[touchId].normalPosition = QPointF( static_cast<qreal>(pos[0]) / screenSize.width(), static_cast<qreal>(pos[1]) / screenSize.height() ); - m_touchPoints[touchId].area = QRectF( pos[0], pos[1], 0.0, 0.0 ); + m_touchPoints[touchId].normalPosition = + QPointF(static_cast<qreal>(pos[0]) / screenSize.width(), + static_cast<qreal>(pos[1]) / screenSize.height()); + + m_touchPoints[touchId].area = QRectF(w->geometry().left() + windowPos[0], + w->geometry().top() + windowPos[1], 0.0, 0.0); + QWindow *parent = w->parent(); + while (parent) { + m_touchPoints[touchId].area.translate(parent->geometry().topLeft()); + parent = parent->parent(); + } // determine event type and update state of current touch point QEvent::Type type = QEvent::None; @@ -451,8 +507,8 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType) // inject event into Qt QWindowSystemInterface::handleTouchEvent(w, m_touchDevice, pointList); qScreenEventDebug() << Q_FUNC_INFO << "Qt touch, w =" << w - << ", p=(" << pos[0] << "," << pos[1] - << "), t=" << type; + << ", p=" << m_touchPoints[touchId].area.topLeft() + << ", t=" << type; } } } @@ -523,6 +579,48 @@ void QQnxScreenEventHandler::handleDisplayEvent(screen_event_t event) } } +void QQnxScreenEventHandler::handlePropertyEvent(screen_event_t event) +{ + errno = 0; + int objectType; + if (screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType) != 0) + qFatal("QQNX: failed to query object type property, errno=%d", errno); + + if (objectType != SCREEN_OBJECT_TYPE_WINDOW) + return; + + errno = 0; + screen_window_t window = 0; + if (screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0) + qFatal("QQnx: failed to query window property, errno=%d", errno); + + errno = 0; + int property; + if (screen_get_event_property_iv(event, SCREEN_PROPERTY_NAME, &property) != 0) + qFatal("QQnx: failed to query window property, errno=%d", errno); + + switch (property) { + case SCREEN_PROPERTY_KEYBOARD_FOCUS: + handleKeyboardFocusPropertyEvent(window); + break; + default: + // event ignored + qScreenEventDebug() << Q_FUNC_INFO << "Ignore property event for property: " << property; + } +} + +void QQnxScreenEventHandler::handleKeyboardFocusPropertyEvent(screen_window_t window) +{ + errno = 0; + int focus = 0; + if (window && screen_get_window_property_iv(window, SCREEN_PROPERTY_KEYBOARD_FOCUS, &focus) != 0) + qFatal("QQnx: failed to query keyboard focus property, errno=%d", errno); + + QWindow *w = focus ? QQnxIntegration::window(window) : 0; + + QWindowSystemInterface::handleWindowActivated(w); +} + #include "moc_qqnxscreeneventhandler.cpp" QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h index af0b086eb8..a7bcd449ee 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h @@ -50,6 +50,9 @@ QT_BEGIN_NAMESPACE class QQnxIntegration; class QQnxScreenEventFilter; +#if defined(QQNX_SCREENEVENTTHREAD) +class QQnxScreenEventThread; +#endif class QQnxScreenEventHandler : public QObject { @@ -65,10 +68,19 @@ public: static void injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap); +#if defined(QQNX_SCREENEVENTTHREAD) + void setScreenEventThread(QQnxScreenEventThread *eventThread); +#endif + Q_SIGNALS: void newWindowCreated(void *window); void windowClosed(void *window); +#if defined(QQNX_SCREENEVENTTHREAD) +private Q_SLOTS: + void processEventsFromScreenThread(); +#endif + private: void handleKeyboardEvent(screen_event_t event); void handlePointerEvent(screen_event_t event); @@ -76,6 +88,8 @@ private: void handleCloseEvent(screen_event_t event); void handleCreateEvent(screen_event_t event); void handleDisplayEvent(screen_event_t event); + void handlePropertyEvent(screen_event_t event); + void handleKeyboardFocusPropertyEvent(screen_window_t window); private: enum { @@ -90,6 +104,9 @@ private: QTouchDevice *m_touchDevice; QWindowSystemInterface::TouchPoint m_touchPoints[MaximumTouchPoints]; QList<QQnxScreenEventFilter*> m_eventFilters; +#if defined(QQNX_SCREENEVENTTHREAD) + QQnxScreenEventThread *m_eventThread; +#endif }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp index f3f660bc03..25a597bab9 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp @@ -61,6 +61,9 @@ QQnxScreenEventThread::QQnxScreenEventThread(screen_context_t context, QQnxScree m_screenEventHandler(screenEventHandler), m_quit(false) { + screenEventHandler->setScreenEventThread(this); + connect(this, SIGNAL(eventPending()), screenEventHandler, SLOT(processEventsFromScreenThread()), Qt::QueuedConnection); + connect(this, SIGNAL(finished()), screenEventHandler, SLOT(processEventsFromScreenThread()), Qt::QueuedConnection); } QQnxScreenEventThread::~QQnxScreenEventThread() @@ -74,20 +77,31 @@ void QQnxScreenEventThread::injectKeyboardEvent(int flags, int sym, int mod, int QQnxScreenEventHandler::injectKeyboardEvent(flags, sym, mod, scan, cap); } -void QQnxScreenEventThread::run() +QQnxScreenEventArray *QQnxScreenEventThread::lock() { - screen_event_t event; + m_mutex.lock(); + return &m_events; +} - // create screen event - errno = 0; - int result = screen_create_event(&event); - if (result) - qFatal("QQNX: failed to create screen event, errno=%d", errno); +void QQnxScreenEventThread::unlock() +{ + m_mutex.unlock(); +} +void QQnxScreenEventThread::run() +{ qScreenEventThreadDebug() << Q_FUNC_INFO << "screen event thread started"; // loop indefinitely while (!m_quit) { + screen_event_t event; + + // create screen event + errno = 0; + int result = screen_create_event(&event); + if (result) + qFatal("QQNX: failed to create screen event, errno=%d", errno); + // block until screen event is available errno = 0; @@ -108,14 +122,22 @@ void QQnxScreenEventThread::run() qScreenEventThreadDebug() << Q_FUNC_INFO << "QNX user screen event"; m_quit = true; } else { - m_screenEventHandler->handleEvent(event, qnxType); + m_mutex.lock(); + m_events << event; + m_mutex.unlock(); + emit eventPending(); } } qScreenEventThreadDebug() << Q_FUNC_INFO << "screen event thread stopped"; // cleanup - screen_destroy_event(event); + m_mutex.lock(); + Q_FOREACH (screen_event_t event, m_events) { + screen_destroy_event(event); + } + m_events.clear(); + m_mutex.unlock(); } void QQnxScreenEventThread::shutdown() diff --git a/src/plugins/platforms/qnx/qqnxscreeneventthread.h b/src/plugins/platforms/qnx/qqnxscreeneventthread.h index 5e931819be..cbdb505b3b 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventthread.h +++ b/src/plugins/platforms/qnx/qqnxscreeneventthread.h @@ -43,6 +43,7 @@ #define QQNXSCREENEVENTTHREAD_H #include <QtCore/QThread> +#include <QtCore/QMutex> #include <screen/screen.h> @@ -50,21 +51,33 @@ QT_BEGIN_NAMESPACE class QQnxScreenEventHandler; +typedef QVarLengthArray<screen_event_t, 64> QQnxScreenEventArray; + class QQnxScreenEventThread : public QThread { + Q_OBJECT + public: QQnxScreenEventThread(screen_context_t context, QQnxScreenEventHandler *screenEventHandler); ~QQnxScreenEventThread(); static void injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap); + QQnxScreenEventArray *lock(); + void unlock(); + protected: void run(); +Q_SIGNALS: + void eventPending(); + private: void shutdown(); screen_context_t m_screenContext; + QMutex m_mutex; + QQnxScreenEventArray m_events; QQnxScreenEventHandler *m_screenEventHandler; bool m_quit; }; diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 3969a09098..b25c0b5b29 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2011 - 2013 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -40,15 +40,16 @@ ****************************************************************************/ #include "qqnxwindow.h" -#if !defined(QT_NO_OPENGL) -#include "qqnxglcontext.h" -#endif #include "qqnxintegration.h" #include "qqnxscreen.h" +#include <QUuid> + #include <QtGui/QWindow> #include <qpa/qwindowsysteminterface.h> +#include "private/qguiapplication_p.h" + #include <QtCore/QDebug> #if defined(Q_OS_BLACKBERRY) @@ -69,26 +70,36 @@ QT_BEGIN_NAMESPACE -QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context) +QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow) : QPlatformWindow(window), m_screenContext(context), + m_parentWindow(0), m_window(0), m_screen(0), - m_parentWindow(0), m_visible(false), m_exposed(true), - m_windowState(Qt::WindowNoState) + m_windowState(Qt::WindowNoState), + m_mmRendererWindow(0) { qWindowDebug() << Q_FUNC_INFO << "window =" << window << ", size =" << window->size(); int result; - // Create child QNX window + QQnxScreen *platformScreen = static_cast<QQnxScreen *>(window->screen()->handle()); + + m_isTopLevel = ( needRootWindow && !platformScreen->rootWindow()) + || (!needRootWindow && !parent()) + || window->type() == Qt::CoverWindow; + errno = 0; - if (static_cast<QQnxScreen *>(window->screen()->handle())->isPrimaryScreen() - && window->type() != Qt::CoverWindow) { - result = screen_create_window_type(&m_window, m_screenContext, SCREEN_CHILD_WINDOW); + if (m_isTopLevel) { + result = screen_create_window(&m_window, m_screenContext); // Creates an application window + if (window->type() != Qt::CoverWindow) { + if (needRootWindow) + platformScreen->setRootWindow(this); + createWindowGroup(); + } } else { - result = screen_create_window(&m_window, m_screenContext); + result = screen_create_window_type(&m_window, m_screenContext, SCREEN_CHILD_WINDOW); } if (result != 0) qFatal("QQnxWindow: failed to create window, errno=%d", errno); @@ -115,20 +126,24 @@ QQnxWindow::~QQnxWindow() void QQnxWindow::setGeometry(const QRect &rect) { - const QRect oldGeometry = setGeometryHelper(rect); + QRect newGeometry = rect; + if (screen()->rootWindow() == this) //If this is the root window, it has to be shown fullscreen + newGeometry = screen()->geometry(); + + const QRect oldGeometry = setGeometryHelper(newGeometry); // Send a geometry change event to Qt (triggers resizeEvent() in QWindow/QWidget). // Calling flushWindowSystemEvents() here would flush input events which // could result in re-entering QQnxWindow::setGeometry() again. QWindowSystemInterface::setSynchronousWindowsSystemEvents(true); - QWindowSystemInterface::handleGeometryChange(window(), rect); - QWindowSystemInterface::handleExposeEvent(window(), rect); + QWindowSystemInterface::handleGeometryChange(window(), newGeometry); + QWindowSystemInterface::handleExposeEvent(window(), newGeometry); QWindowSystemInterface::setSynchronousWindowsSystemEvents(false); // Now move all children. if (!oldGeometry.isEmpty()) { - const QPoint offset = rect.topLeft() - oldGeometry.topLeft(); + const QPoint offset = newGeometry.topLeft() - oldGeometry.topLeft(); Q_FOREACH (QQnxWindow *childWindow, m_childWindows) childWindow->setOffset(offset); } @@ -262,16 +277,6 @@ bool QQnxWindow::isExposed() const return m_visible && m_exposed; } -void QQnxWindow::adjustBufferSize() -{ - if (m_parentWindow) - return; - - const QSize windowSize = window()->size(); - if (windowSize != bufferSize()) - setBufferSize(windowSize); -} - void QQnxWindow::setBufferSize(const QSize &size) { qWindowDebug() << Q_FUNC_INFO << "window =" << window() << "size =" << size; @@ -290,6 +295,8 @@ void QQnxWindow::setBufferSize(const QSize &size) // Create window buffers if they do not exist if (m_bufferSize.isEmpty()) { val[0] = pixelFormat(); + if (val[0] == -1) // The platform GL context was not set yet on the window, so we can't procede + return; errno = 0; result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_FORMAT, val); @@ -303,12 +310,6 @@ void QQnxWindow::setBufferSize(const QSize &size) qFatal("QQnxWindow: failed to create window buffers, errno=%d", errno); } - // If the child window has been configured for transparency, lazily create - // a full-screen buffer to back the root window. - if (window()->requestedFormat().hasAlpha()) { - m_screen->rootWindow()->makeTranslucent(); - } - // check if there are any buffers available int bufferCount = 0; result = screen_get_window_property_iv(m_window, SCREEN_PROPERTY_RENDER_BUFFER_COUNT, &bufferCount); @@ -333,6 +334,9 @@ void QQnxWindow::setScreen(QQnxScreen *platformScreen) if (platformScreen == 0) { // The screen has been destroyed m_screen = 0; + Q_FOREACH (QQnxWindow *childWindow, m_childWindows) { + childWindow->setScreen(0); + } return; } @@ -342,26 +346,36 @@ void QQnxWindow::setScreen(QQnxScreen *platformScreen) if (m_screen) { qWindowDebug() << Q_FUNC_INFO << "Moving window to different screen"; m_screen->removeWindow(this); - screen_leave_window_group(m_window); + QQnxIntegration *platformIntegration = static_cast<QQnxIntegration*>(QGuiApplicationPrivate::platformIntegration()); + + if ((platformIntegration->options() & QQnxIntegration::RootWindow)) { + screen_leave_window_group(m_window); + } } - platformScreen->addWindow(this); m_screen = platformScreen; - - // Move window to proper screen/display - errno = 0; - screen_display_t display = platformScreen->nativeDisplay(); - int result = screen_set_window_property_pv(m_window, SCREEN_PROPERTY_DISPLAY, (void **)&display); - if (result != 0) - qFatal("QQnxWindow: failed to set window display, errno=%d", errno); - - - if (m_screen->isPrimaryScreen() && window()->type() != Qt::CoverWindow) { - // Add window to display's window group + if (!m_parentWindow) { + platformScreen->addWindow(this); + } + if (m_isTopLevel) { + // Move window to proper screen/display errno = 0; - result = screen_join_window_group(m_window, platformScreen->windowGroupName()); + screen_display_t display = platformScreen->nativeDisplay(); + int result = screen_set_window_property_pv(m_window, SCREEN_PROPERTY_DISPLAY, (void **)&display); if (result != 0) - qFatal("QQnxWindow: failed to join window group, errno=%d", errno); + qFatal("QQnxWindow: failed to set window display, errno=%d", errno); + } else { + errno = 0; + int result; + if (!parent()) { + result = screen_join_window_group(m_window, platformScreen->windowGroupName()); + if (result != 0) + qFatal("QQnxWindow: failed to join window group, errno=%d", errno); + } else { + result = screen_join_window_group(m_window, static_cast<QQnxWindow*>(parent())->groupName().constData()); + if (result != 0) + qFatal("QQnxWindow: failed to join window group, errno=%d", errno); + } Q_FOREACH (QQnxWindow *childWindow, m_childWindows) { // Only subwindows and tooltips need necessarily be moved to another display with the window. @@ -405,20 +419,12 @@ void QQnxWindow::setParent(const QPlatformWindow *window) setScreen(m_parentWindow->m_screen); m_parentWindow->m_childWindows.push_back(this); - - // we don't need any buffers, since - // Qt will draw to the parent TLW - // backing store. - setBufferSize(QSize(1, 1)); } else { m_screen->addWindow(this); - - // recreate buffers, in case the - // window has been reparented and - // becomes a TLW - adjustBufferSize(); } + adjustBufferSize(); + m_screen->updateHierarchy(); } @@ -489,6 +495,22 @@ void QQnxWindow::gainedFocus() QWindowSystemInterface::handleWindowActivated(window()); } +void QQnxWindow::setMMRendererWindowName(const QString &name) +{ + m_mmRendererWindowName = name; +} + +void QQnxWindow::setMMRendererWindow(screen_window_t handle) +{ + m_mmRendererWindow = handle; +} + +void QQnxWindow::clearMMRendererWindow() +{ + m_mmRendererWindowName.clear(); + m_mmRendererWindow = 0; +} + QQnxWindow *QQnxWindow::findWindow(screen_window_t windowHandle) { if (m_window == windowHandle) @@ -524,6 +546,15 @@ void QQnxWindow::minimize() #endif } +void QQnxWindow::setRotation(int rotation) +{ + qWindowDebug() << Q_FUNC_INFO << "angle =" << rotation; + errno = 0; + int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ROTATION, &rotation); + if (result != 0) + qFatal("QQnxRootWindow: failed to set window rotation, errno=%d", errno); +} + void QQnxWindow::initWindow() { // Alpha channel is always pre-multiplied if present @@ -577,23 +608,48 @@ void QQnxWindow::initWindow() setWindowState(window()->windowState()); if (window()->parent() && window()->parent()->handle()) setParent(window()->parent()->handle()); - setGeometryHelper(window()->geometry()); + + if (screen()->rootWindow() == this) { + setGeometryHelper(screen()->geometry()); + QWindowSystemInterface::handleGeometryChange(window(), screen()->geometry()); + } else { + setGeometryHelper(window()->geometry()); + } } +void QQnxWindow::createWindowGroup() +{ + // Generate a random window group name + m_windowGroupName = QUuid::createUuid().toString().toLatin1(); + + // Create window group so child windows can be parented by container window + errno = 0; + int result = screen_create_window_group(m_window, m_windowGroupName.constData()); + if (result != 0) + qFatal("QQnxRootWindow: failed to create app window group, errno=%d", errno); +} void QQnxWindow::updateZorder(int &topZorder) { - errno = 0; - int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ZORDER, &topZorder); - topZorder++; + updateZorder(m_window, topZorder); - if (result != 0) - qFatal("QQnxWindow: failed to set window z-order=%d, errno=%d, mWindow=%p", topZorder, errno, m_window); + if (m_mmRendererWindow) + updateZorder(m_mmRendererWindow, topZorder); Q_FOREACH (QQnxWindow *childWindow, m_childWindows) childWindow->updateZorder(topZorder); } +void QQnxWindow::updateZorder(screen_window_t window, int &topZorder) +{ + errno = 0; + int result = screen_set_window_property_iv(window, SCREEN_PROPERTY_ZORDER, &topZorder); + topZorder++; + + if (result != 0) + qFatal("QQnxWindow: failed to set window z-order=%d, errno=%d, mWindow=%p", topZorder, errno, window); +} + void QQnxWindow::applyWindowState() { switch (m_windowState) { diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index f96280848a..3c8070b0be 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.h +++ b/src/plugins/platforms/qnx/qqnxwindow.h @@ -66,12 +66,7 @@ class QQnxWindow : public QPlatformWindow { friend class QQnxScreen; public: - enum WindowType { - EGL, - Raster - }; - - QQnxWindow(QWindow *window, screen_context_t context); + QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow); virtual ~QQnxWindow(); void setGeometry(const QRect &rect); @@ -83,7 +78,7 @@ public: WId winId() const { return (WId)m_window; } screen_window_t nativeHandle() const { return m_window; } - void adjustBufferSize(); + virtual void adjustBufferSize() = 0; void setBufferSize(const QSize &size); QSize bufferSize() const { return m_bufferSize; } @@ -99,6 +94,9 @@ public: void propagateSizeHints(); void gainedFocus(); + void setMMRendererWindowName(const QString &name); + void setMMRendererWindow(screen_window_t handle); + void clearMMRendererWindow(); QQnxScreen *screen() const { return m_screen; } const QList<QQnxWindow*>& children() const { return m_childWindows; } @@ -107,7 +105,14 @@ public: void minimize(); - virtual WindowType windowType() const = 0; + QString mmRendererWindowName() const { return m_mmRendererWindowName; } + + screen_window_t mmRendererWindow() const { return m_mmRendererWindow; } + + void setRotation(int rotation); + + QByteArray groupName() const { return m_windowGroupName; } + protected: virtual int pixelFormat() const = 0; virtual void resetBuffers() = 0; @@ -117,12 +122,16 @@ protected: screen_context_t m_screenContext; QScopedPointer<QQnxAbstractCover> m_cover; + QQnxWindow *m_parentWindow; + private: + void createWindowGroup(); QRect setGeometryHelper(const QRect &rect); void removeFromParent(); void setOffset(const QPoint &setOffset); void updateVisibility(bool parentVisible); void updateZorder(int &topZorder); + void updateZorder(screen_window_t window, int &zOrder); void applyWindowState(); screen_window_t m_window; @@ -130,11 +139,16 @@ private: QQnxScreen *m_screen; QList<QQnxWindow*> m_childWindows; - QQnxWindow *m_parentWindow; bool m_visible; bool m_exposed; QRect m_unmaximizedGeometry; Qt::WindowState m_windowState; + QString m_mmRendererWindowName; + screen_window_t m_mmRendererWindow; + + QByteArray m_windowGroupName; + + bool m_isTopLevel; }; QT_END_NAMESPACE |