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 <matt.hoosier@garmin.com>
Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
bb10
Fabian Bumberger 2013-08-22 17:02:05 +02:00 committed by The Qt Project
parent d4ade9d4ef
commit fd619946be
13 changed files with 191 additions and 485 deletions

View File

@ -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 \

View File

@ -42,6 +42,7 @@
#include "qqnxeglwindow.h"
#include "qqnxscreen.h"
#include "qqnxglcontext.h"
#include <QDebug>
@ -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();

View File

@ -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;

View File

@ -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 &paramList
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");

View File

@ -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 &paramList);

View File

@ -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();

View File

@ -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 &region, int dx, int dy, bool flush=false);
void blitHelper(QQnxBuffer &source, QQnxBuffer &target, const QPoint &sourceOffset,
const QPoint &targetOffset, const QRegion &region, bool flush = false);
private:
QRegion m_previousDirty;
QRegion m_scrolled;

View File

@ -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);
}

View File

@ -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

View File

@ -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<QQnxWindow*> 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<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
@ -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<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()) {

View File

@ -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;
@ -126,9 +126,8 @@ private:
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;

View File

@ -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,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<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);
@ -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<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.
@ -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);

View File

@ -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<QQnxAbstractCover> 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<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