Added support for cover windows on BlackBerry platform

On the BlackBerry platform when an application is minimized an
alternate cover window is shown. This patch allows Qt to render
into those windows.
A new window type "Qt::CoverWindow" has been introduced.

Change-Id: If5e321f5cb00f6d3ed7a5dc0af425655d7a9253a
Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com>
Reviewed-by: Fabian Bumberger <fbumberger@rim.com>
Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
This commit is contained in:
Bernd Weimer 2013-09-18 16:14:49 +02:00 committed by The Qt Project
parent 6b95130faa
commit 6a12da7fb3
13 changed files with 274 additions and 29 deletions

View File

@ -296,6 +296,7 @@ public:
Desktop = 0x00000010 | Window,
SubWindow = 0x00000012,
ForeignWindow = 0x00000020 | Window,
CoverWindow = 0x00000040 | Window,
WindowType_Mask = 0x000000ff,
MSWindowsFixedSizeDialogHint = 0x00000100,

View File

@ -1997,6 +1997,10 @@
representing a native platform window created by
another process or by manually using native code.
\value CoverWindow Indicates that the window represents a cover window,
which is shown when the application is minimized
on the BlackBerry platform for instance.
There are also a number of flags which you can use to customize
the appearance of top-level windows. These have no effect on other
windows:

View File

@ -73,6 +73,7 @@ HEADERS = main.h \
qqnxnavigatoreventhandler.h \
qqnxabstractnavigator.h \
qqnxabstractvirtualkeyboard.h \
qqnxabstractcover.h \
qqnxservices.h \
qqnxcursor.h \
qqnxrasterwindow.h
@ -119,9 +120,11 @@ CONFIG(blackberry-playbook) {
} else {
CONFIG(blackberry) {
SOURCES += qqnxfiledialoghelper_bb10.cpp \
qqnxfilepicker.cpp
qqnxfilepicker.cpp \
qqnxnavigatorcover.cpp
HEADERS += qqnxfilepicker.h
HEADERS += qqnxfilepicker.h \
qqnxnavigatorcover.h
}
}

View File

@ -0,0 +1,53 @@
/***************************************************************************
**
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** 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 QQNXABSTRACTCOVER_H
#define QQNXABSTRACTCOVER_H
class QQnxAbstractCover
{
public:
virtual ~QQnxAbstractCover() {}
virtual void updateCover() = 0;
};
#endif // QQNXABSTRACTCOVER_H

View File

@ -126,6 +126,9 @@ void QQnxEglWindow::swapEGLBuffers()
eglResult = eglSwapBuffers(m_platformOpenGLContext->getEglDisplay(), m_eglSurface);
if (eglResult != EGL_TRUE)
qFatal("QQNX: failed to swap EGL buffers, err=%d", eglGetError());
if (m_cover)
m_cover->updateCover();
}
EGLSurface QQnxEglWindow::getSurface()

View File

@ -0,0 +1,65 @@
/***************************************************************************
**
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** 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 "qqnxnavigatorcover.h"
QQnxNavigatorCover::QQnxNavigatorCover()
{
navigator_window_cover_attribute_create(&m_coverAttribute);
}
QQnxNavigatorCover::~QQnxNavigatorCover()
{
if (m_coverAttribute)
navigator_window_cover_attribute_destroy(m_coverAttribute);
navigator_window_cover_reset();
}
void QQnxNavigatorCover::updateCover()
{
if (m_coverAttribute) {
navigator_window_cover_attribute_set_transition(m_coverAttribute,
NAVIGATOR_WINDOW_COVER_TRANSITION_NONE);
navigator_window_cover_attribute_set_alternate_window(m_coverAttribute);
navigator_window_cover_update(m_coverAttribute);
}
}

View File

@ -0,0 +1,60 @@
/***************************************************************************
**
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** 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 QQNXNAVIGATORCOVER_H
#define QQNXNAVIGATORCOVER_H
#include "qqnxabstractcover.h"
#include <bps/navigator.h>
class QQnxNavigatorCover : public QQnxAbstractCover
{
public:
QQnxNavigatorCover();
~QQnxNavigatorCover();
void updateCover();
private:
navigator_window_cover_attribute_t *m_coverAttribute;
};
#endif // QQNXNAVIGATORCOVER_H

View File

@ -118,6 +118,9 @@ void QQnxRasterWindow::post(const QRegion &dirty)
// Notify screen that window posted
if (screen() != 0)
screen()->onWindowPost(this);
if (m_cover)
m_cover->updateCover();
}
}

View File

@ -126,6 +126,7 @@ QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display,
m_posted(false),
m_keyboardHeight(0),
m_nativeOrientation(Qt::PrimaryOrientation),
m_coverWindow(0),
m_cursor(new QQnxCursor())
{
qScreenDebug() << Q_FUNC_INFO;
@ -431,45 +432,59 @@ void QQnxScreen::addWindow(QQnxWindow *window)
if (m_childWindows.contains(window))
return;
// Ensure that the desktop window is at the bottom of the zorder.
// If we do not do this then we may end up activating the desktop
// when the navigator service gets an event that our window group
// has been activated (see QQnxScreen::activateWindowGroup()).
// Such a situation would strangely break focus handling due to the
// invisible desktop widget window being layered on top of normal
// windows
if (window->window()->type() == Qt::Desktop)
m_childWindows.push_front(window);
else
m_childWindows.push_back(window);
updateHierarchy();
if (window->window()->type() != Qt::CoverWindow) {
// Ensure that the desktop window is at the bottom of the zorder.
// If we do not do this then we may end up activating the desktop
// when the navigator service gets an event that our window group
// has been activated (see QQnxScreen::activateWindowGroup()).
// Such a situation would strangely break focus handling due to the
// invisible desktop widget window being layered on top of normal
// windows
if (window->window()->type() == Qt::Desktop)
m_childWindows.push_front(window);
else
m_childWindows.push_back(window);
updateHierarchy();
} else {
#if !defined(Q_OS_BLACKBERRY_TABLET)
m_coverWindow = window;
#endif
}
}
void QQnxScreen::removeWindow(QQnxWindow *window)
{
qScreenDebug() << Q_FUNC_INFO << "window =" << window;
const int numWindowsRemoved = m_childWindows.removeAll(window);
if (numWindowsRemoved > 0)
updateHierarchy();
if (window != m_coverWindow) {
const int numWindowsRemoved = m_childWindows.removeAll(window);
if (numWindowsRemoved > 0)
updateHierarchy();
} else {
m_coverWindow = 0;
}
}
void QQnxScreen::raiseWindow(QQnxWindow *window)
{
qScreenDebug() << Q_FUNC_INFO << "window =" << window;
removeWindow(window);
m_childWindows.push_back(window);
updateHierarchy();
if (window != m_coverWindow) {
removeWindow(window);
m_childWindows.push_back(window);
updateHierarchy();
}
}
void QQnxScreen::lowerWindow(QQnxWindow *window)
{
qScreenDebug() << Q_FUNC_INFO << "window =" << window;
removeWindow(window);
m_childWindows.push_front(window);
updateHierarchy();
if (window != m_coverWindow) {
removeWindow(window);
m_childWindows.push_front(window);
updateHierarchy();
}
}
void QQnxScreen::updateHierarchy()
@ -652,6 +667,9 @@ void QQnxScreen::activateWindowGroup(const QByteArray &id)
Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
childWindow->setExposed(true);
if (m_coverWindow)
m_coverWindow->setExposed(false);
QWindowSystemInterface::handleWindowActivated(window);
}
@ -662,6 +680,9 @@ void QQnxScreen::deactivateWindowGroup(const QByteArray &id)
if (!rootWindow() || id != rootWindow()->groupName())
return;
if (m_coverWindow)
m_coverWindow->setExposed(true);
Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
childWindow->setExposed(false);

View File

@ -139,6 +139,7 @@ private:
QRect m_currentGeometry;
QList<QQnxWindow *> m_childWindows;
QQnxWindow *m_coverWindow;
QList<screen_window_t> m_overlays;
QList<screen_window_t> m_underlays;

View File

@ -51,13 +51,16 @@
#include <QtCore/QDebug>
#include <errno.h>
#if defined(Q_OS_BLACKBERRY)
#if !defined(Q_OS_BLACKBERRY_TABLET)
#include "qqnxnavigatorcover.h"
#endif
#include <sys/pps.h>
#include <bps/navigator.h>
#endif
#include <errno.h>
#if defined(QQNXWINDOW_DEBUG)
#define qWindowDebug qDebug
#else
@ -81,7 +84,8 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context)
// Create child QNX window
errno = 0;
if (static_cast<QQnxScreen *>(window->screen()->handle())->isPrimaryScreen()) {
if (static_cast<QQnxScreen *>(window->screen()->handle())->isPrimaryScreen()
&& window->type() != Qt::CoverWindow) {
result = screen_create_window_type(&m_window, m_screenContext, SCREEN_CHILD_WINDOW);
} else {
result = screen_create_window(&m_window, m_screenContext);
@ -352,7 +356,7 @@ void QQnxWindow::setScreen(QQnxScreen *platformScreen)
qFatal("QQnxWindow: failed to set window display, errno=%d", errno);
if (m_screen->isPrimaryScreen()) {
if (m_screen->isPrimaryScreen() && window()->type() != Qt::CoverWindow) {
// Add window to display's window group
errno = 0;
result = screen_join_window_group(m_window, platformScreen->windowGroupName());
@ -361,8 +365,7 @@ void QQnxWindow::setScreen(QQnxScreen *platformScreen)
Q_FOREACH (QQnxWindow *childWindow, m_childWindows) {
// Only subwindows and tooltips need necessarily be moved to another display with the window.
if ((window()->type() & Qt::WindowType_Mask) == Qt::SubWindow ||
(window()->type() & Qt::WindowType_Mask) == Qt::ToolTip)
if (window()->type() == Qt::SubWindow || window()->type() == Qt::ToolTip)
childWindow->setScreen(platformScreen);
}
}
@ -558,6 +561,17 @@ void QQnxWindow::initWindow()
setScreen(static_cast<QQnxScreen *>(window()->screen()->handle()));
if (window()->type() == Qt::CoverWindow) {
#if !defined(Q_OS_BLACKBERRY_TABLET)
screen_set_window_property_pv(m_screen->rootWindow()->nativeHandle(),
SCREEN_PROPERTY_ALTERNATE_WINDOW, (void**)&m_window);
#if defined(Q_OS_BLACKBERRY)
m_cover.reset(new QQnxNavigatorCover);
#endif
#endif // Q_OS_BLACKBERRY_TABLET
m_exposed = false;
}
// Add window to plugin's window mapper
QQnxIntegration::addWindow(m_window, window());

View File

@ -43,6 +43,9 @@
#define QQNXWINDOW_H
#include <qpa/qplatformwindow.h>
#include "qqnxabstractcover.h"
#include <QtCore/QScopedPointer>
#if !defined(QT_NO_OPENGL)
#include <EGL/egl.h>
@ -112,6 +115,7 @@ protected:
void initWindow();
screen_context_t m_screenContext;
QScopedPointer<QQnxAbstractCover> m_cover;
private:
QRect setGeometryHelper(const QRect &rect);

View File

@ -139,6 +139,19 @@
depends on the result of QWidget::frameGeometry() and the
capability of the window manager to do proper window placement,
neither of which can be guaranteed.
\section2 BlackBerry Peculiarities
On the BlackBerry platform it is possible to set an alternate
cover window that is shown when the application is minimized.
The cover window must be a separate window with the
\l{Qt::CoverWindow} flag set.
The window should have a fixed size depending on the screen
resolution (e.g. for a 768x1280 screen, 334 pixels wide by 396
pixels high). The window can be rendered to as usual, however
updates should occur very infrequently (a few updates per minute
at most) in order save battery.
*/
/*!