From fd619946be51784dc709363324897be6af144c52 Mon Sep 17 00:00:00 2001 From: Fabian Bumberger Date: Thu, 22 Aug 2013 17:02:05 +0200 Subject: Refactor QQnxWindow This patch does following things: * Remove the root window: First window which is created will serve as a root window * Allow creation of more than one application window (with every app window having an own window group) on one screen * Fixes a bug when reparanting an EGL window Change-Id: I1afd64a813bc084c0893b958aa191d4a25c32b9d Reviewed-by: Matt Hoosier Reviewed-by: Rafael Roquetto --- src/plugins/platforms/qnx/qnx.pro | 3 - src/plugins/platforms/qnx/qqnxeglwindow.cpp | 17 +- src/plugins/platforms/qnx/qqnxeglwindow.h | 6 +- src/plugins/platforms/qnx/qqnxintegration.cpp | 21 +- src/plugins/platforms/qnx/qqnxintegration.h | 5 +- src/plugins/platforms/qnx/qqnxrasterwindow.cpp | 16 +- src/plugins/platforms/qnx/qqnxrasterwindow.h | 7 +- src/plugins/platforms/qnx/qqnxrootwindow.cpp | 268 ------------------------- src/plugins/platforms/qnx/qqnxrootwindow.h | 85 -------- src/plugins/platforms/qnx/qqnxscreen.cpp | 74 +++---- src/plugins/platforms/qnx/qqnxscreen.h | 9 +- src/plugins/platforms/qnx/qqnxwindow.cpp | 143 +++++++------ src/plugins/platforms/qnx/qqnxwindow.h | 22 +- 13 files changed, 191 insertions(+), 485 deletions(-) delete mode 100644 src/plugins/platforms/qnx/qqnxrootwindow.cpp delete mode 100644 src/plugins/platforms/qnx/qqnxrootwindow.h (limited to 'src') diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro index becf5e287e..aeacbeef69 100644 --- a/src/plugins/platforms/qnx/qnx.pro +++ b/src/plugins/platforms/qnx/qnx.pro @@ -25,7 +25,6 @@ CONFIG += qqnx_pps #DEFINES += QQNXNAVIGATOREVENTNOTIFIER_DEBUG #DEFINES += QQNXNAVIGATOR_DEBUG #DEFINES += QQNXRASTERBACKINGSTORE_DEBUG -#DEFINES += QQNXROOTWINDOW_DEBUG #DEFINES += QQNXSCREENEVENTTHREAD_DEBUG #DEFINES += QQNXSCREENEVENT_DEBUG #DEFINES += QQNXSCREEN_DEBUG @@ -42,7 +41,6 @@ SOURCES = main.cpp \ qqnxscreen.cpp \ qqnxwindow.cpp \ qqnxrasterbackingstore.cpp \ - qqnxrootwindow.cpp \ qqnxscreeneventhandler.cpp \ qqnxnativeinterface.cpp \ qqnxnavigatoreventhandler.cpp \ @@ -59,7 +57,6 @@ HEADERS = main.h \ qqnxscreen.h \ qqnxwindow.h \ qqnxrasterbackingstore.h \ - qqnxrootwindow.h \ qqnxscreeneventhandler.h \ qqnxnativeinterface.h \ qqnxnavigatoreventhandler.h \ diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.cpp b/src/plugins/platforms/qnx/qqnxeglwindow.cpp index e8fcdd692b..6afc3cad21 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 @@ -55,8 +56,8 @@ QT_BEGIN_NAMESPACE -QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context) : - QQnxWindow(window, context), +QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context, bool needRootWindow) : + QQnxWindow(window, context, needRootWindow), m_requestedBufferSize(window->geometry().size()), m_platformOpenGLContext(0), m_newSurfaceRequested(true), @@ -98,8 +99,6 @@ void QQnxEglWindow::createEGLSurface() QQnxGLContext::checkEGLError("eglCreateWindowSurface"); qFatal("QQNX: failed to create EGL surface, err=%d", eglGetError()); } - - screen()->onWindowPost(0); } void QQnxEglWindow::destroyEGLSurface() @@ -166,6 +165,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 +181,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 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/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index 36a2194b56..52f836abbe 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.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. @@ -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; } @@ -323,9 +334,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: @@ -340,12 +352,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/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 -#include - -#if defined(QQNXROOTWINDOW_DEBUG) -#define qRootWindowDebug qDebug -#else -#define qRootWindowDebug QT_NO_QDEBUG_MACRO -#endif - -#include -#include - -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 -#include - -#include - -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 3dab2b3bc9..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. @@ -154,8 +154,8 @@ static QQnxWindow *findMultimediaWindow(const QList windows, 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), @@ -292,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); @@ -312,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 @@ -490,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 { @@ -525,13 +526,15 @@ void QQnxScreen::updateHierarchy() QList::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 @@ -539,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); @@ -564,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) @@ -713,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; @@ -728,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; @@ -755,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 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(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 014f7905f3..61c47e6c72 100644 --- a/src/plugins/platforms/qnx/qqnxscreen.h +++ b/src/plugins/platforms/qnx/qqnxscreen.h @@ -44,7 +44,7 @@ #include -#include "qqnxrootwindow.h" +#include "qqnxwindow.h" #include #include @@ -91,10 +91,10 @@ public: void lowerWindow(QQnxWindow *window); void updateHierarchy(); - void onWindowPost(QQnxWindow *window); void adjustOrientation(); - QSharedPointer rootWindow() const; + QQnxWindow *rootWindow() const; + void setRootWindow(QQnxWindow*); QPlatformCursor *cursor() const; @@ -126,9 +126,8 @@ private: screen_context_t m_screenContext; screen_display_t m_display; - mutable QSharedPointer 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/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 749a336fcc..1e58d482d4 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 + #include #include +#include "private/qguiapplication_p.h" + #include #if defined(Q_OS_BLACKBERRY) @@ -69,12 +70,12 @@ 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), @@ -83,13 +84,22 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context) qWindowDebug() << Q_FUNC_INFO << "window =" << window << ", size =" << window->size(); int result; - // Create child QNX window + QQnxScreen *platformScreen = static_cast(window->screen()->handle()); + + m_isTopLevel = ( needRootWindow && !platformScreen->rootWindow()) + || (!needRootWindow && !parent()) + || window->type() == Qt::CoverWindow; + errno = 0; - if (static_cast(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); @@ -116,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::setSynchronousWindowsSystemEvents(true); //This does not work + 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); } @@ -263,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; @@ -291,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); @@ -304,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); @@ -334,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; } @@ -343,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(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(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. @@ -406,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(); } @@ -541,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 @@ -595,9 +609,24 @@ void QQnxWindow::initWindow() if (window()->parent() && window()->parent()->handle()) setParent(window()->parent()->handle()); setGeometryHelper(window()->geometry()); + if (screen()->rootWindow() == this) { + setGeometry(screen()->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) { updateZorder(m_window, topZorder); diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h index 52d22235a2..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; } @@ -114,7 +109,10 @@ public: screen_window_t mmRendererWindow() const { return m_mmRendererWindow; } - virtual WindowType windowType() const = 0; + void setRotation(int rotation); + + QByteArray groupName() const { return m_windowGroupName; } + protected: virtual int pixelFormat() const = 0; virtual void resetBuffers() = 0; @@ -124,7 +122,10 @@ protected: screen_context_t m_screenContext; QScopedPointer m_cover; + QQnxWindow *m_parentWindow; + private: + void createWindowGroup(); QRect setGeometryHelper(const QRect &rect); void removeFromParent(); void setOffset(const QPoint &setOffset); @@ -138,13 +139,16 @@ private: QQnxScreen *m_screen; QList 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 -- cgit v1.2.3