Basic foreign window support for QNX

Requires a screen with working context permission parsing.  Currently,
all context permission requests fail because the parsing is incorrect.
A context permission is added temporarily to prevent CLOSE/CREATE
events when Qt reparents foreign windows.  Qt does this temporarily
when a foreign window is wrapped in a widget.

Change-Id: I84c18e70d43239286fcd53715332d7015cf1a826
Reviewed-by: Rafael Roquetto <rafael@roquetto.com>
This commit is contained in:
James McDonnell 2018-05-04 14:23:51 -04:00
parent e0d2b50249
commit 9ec564b0bf
13 changed files with 747 additions and 10 deletions

View File

@ -0,0 +1,176 @@
/***************************************************************************
**
** Copyright (C) 2018 QNX Software Systems. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QApplication>
#include <QDebug>
#include <QHBoxLayout>
#include <QWindow>
#include <algorithm>
#include <screen/screen.h>
#include "collector.h"
constexpr int MANAGER_EVENT_NAME_SUGGESTION = 9999;
Collector::Collector(QWidget *parent)
: QWidget(parent)
{
QApplication::instance()->installNativeEventFilter(this);
QLayout *layout = new QHBoxLayout(this);
setLayout(layout);
}
Collector::~Collector()
{
QApplication::instance()->removeNativeEventFilter(this);
}
bool Collector::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
Q_UNUSED(result);
if (eventType == QByteArrayLiteral("screen_event_t"))
return filterQnxScreenEvent(static_cast<screen_event_t>(message));
return false;
}
bool Collector::filterQnxScreenEvent(screen_event_t event)
{
int objectType = SCREEN_OBJECT_TYPE_CONTEXT;
screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType);
if (objectType == SCREEN_OBJECT_TYPE_WINDOW)
return filterQnxScreenWindowEvent(event);
return false;
}
bool Collector::filterQnxScreenWindowEvent(screen_event_t event)
{
int eventType = SCREEN_EVENT_NONE;
screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &eventType);
screen_window_t window = nullptr;
screen_get_event_property_pv(event,
SCREEN_PROPERTY_WINDOW,
reinterpret_cast<void **>(&window));
if (eventType == SCREEN_EVENT_CREATE)
return filterQnxScreenWindowCreateEvent(window, event);
else if (eventType == SCREEN_EVENT_CLOSE)
return filterQnxScreenWindowCloseEvent(window, event);
else if (eventType == SCREEN_EVENT_MANAGER)
return filterQnxScreenWindowManagerEvent(window, event);
return false;
}
bool Collector::filterQnxScreenWindowCreateEvent(screen_window_t window, screen_event_t event)
{
Q_UNUSED(event);
WId winId = reinterpret_cast<WId>(window);
QByteArray parentGroup(256, 0);
screen_get_window_property_cv(window,
SCREEN_PROPERTY_PARENT,
parentGroup.length(),
parentGroup.data());
parentGroup.resize(strlen(parentGroup.constData()));
QByteArray group(256, 0);
screen_get_window_property_cv(reinterpret_cast<screen_window_t>(windowHandle()->winId()),
SCREEN_PROPERTY_GROUP,
group.length(),
group.data());
group.resize(strlen(group.constData()));
if (parentGroup != group)
return false;
Collectible collectible;
collectible.window = QWindow::fromWinId(winId);
collectible.widget = QWidget::createWindowContainer(collectible.window, this);
layout()->addWidget(collectible.widget);
m_collectibles.append(collectible);
return false;
}
bool Collector::filterQnxScreenWindowCloseEvent(screen_window_t window, screen_event_t event)
{
Q_UNUSED(event);
WId winId = reinterpret_cast<WId>(window);
auto it = std::find_if(m_collectibles.begin(), m_collectibles.end(),
[winId] (const Collectible &collectible) {
return collectible.window->winId() == winId;
});
if (it != m_collectibles.end()) {
delete it->widget;
// it->window is deleted by it->widget.
m_collectibles.erase(it);
}
return false;
}
bool Collector::filterQnxScreenWindowManagerEvent(screen_window_t window, screen_event_t event)
{
int managerEventType = 0;
screen_get_event_property_iv(event, SCREEN_PROPERTY_SUBTYPE, &managerEventType);
if (managerEventType == MANAGER_EVENT_NAME_SUGGESTION)
return filterQnxScreenWindowManagerNameEvent(window, event);
return false;
}
bool Collector::filterQnxScreenWindowManagerNameEvent(screen_window_t window, screen_event_t event)
{
Q_UNUSED(window);
int dataSize = 0;
screen_get_event_property_iv(event, SCREEN_PROPERTY_SIZE, &dataSize);
if (dataSize > 0) {
QByteArray data(dataSize, 0);
screen_get_event_property_cv(event, SCREEN_PROPERTY_USER_DATA, data.size(), data.data());
}
return false;
}

View File

@ -0,0 +1,75 @@
/***************************************************************************
**
** Copyright (C) 2018 QNX Software Systems. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef COLLECTOR_H_
#define COLLECTOR_H_
#include <QAbstractNativeEventFilter>
#include <QWidget>
#include <QVector>
#include <screen/screen.h>
class Collector : public QWidget, public QAbstractNativeEventFilter
{
public:
explicit Collector(QWidget *parent = nullptr);
~Collector() override;
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override;
private:
struct Collectible
{
QWindow *window;
QWidget *widget;
};
QVector<Collectible> m_collectibles;
bool filterQnxScreenEvent(screen_event_t event);
bool filterQnxScreenWindowEvent(screen_event_t event);
bool filterQnxScreenWindowCreateEvent(screen_window_t window, screen_event_t event);
bool filterQnxScreenWindowCloseEvent(screen_window_t window, screen_event_t event);
bool filterQnxScreenWindowManagerEvent(screen_window_t window, screen_event_t event);
bool filterQnxScreenWindowManagerNameEvent(screen_window_t window,
screen_event_t event);
};
#endif /* COLLECTOR_H_ */

View File

@ -0,0 +1,11 @@
TEMPLATE = app
HEADERS += collector.h
SOURCES += main.cpp collector.cpp
LIBS += -lscreen
QT += widgets
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/qnx/foreignwindows
INSTALLS += target

View File

@ -0,0 +1,53 @@
/***************************************************************************
**
** Copyright (C) 2018 QNX Software Systems. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QApplication>
#include "collector.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Collector collector;
collector.resize(640, 480);
collector.show();
return app.exec();
}

View File

@ -33,6 +33,7 @@ QT += \
SOURCES = main.cpp \
qqnxbuffer.cpp \
qqnxforeignwindow.cpp \
qqnxintegration.cpp \
qqnxscreen.cpp \
qqnxwindow.cpp \
@ -50,6 +51,7 @@ SOURCES = main.cpp \
HEADERS = main.h \
qqnxbuffer.h \
qqnxforeignwindow.h \
qqnxkeytranslator.h \
qqnxintegration.h \
qqnxscreen.h \

View File

@ -0,0 +1,65 @@
/***************************************************************************
**
** Copyright (C) 2018 QNX Software Systems. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qqnxforeignwindow.h"
#include "qqnxintegration.h"
QT_BEGIN_NAMESPACE
QQnxForeignWindow::QQnxForeignWindow(QWindow *window,
screen_context_t context,
screen_window_t screenWindow)
: QQnxWindow(window, context, screenWindow)
{
initWindow();
}
bool QQnxForeignWindow::isForeignWindow() const
{
return true;
}
int QQnxForeignWindow::pixelFormat() const
{
int result = SCREEN_FORMAT_RGBA8888;
screen_get_window_property_iv(nativeHandle(), SCREEN_PROPERTY_FORMAT, &result);
return result;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,61 @@
/***************************************************************************
**
** Copyright (C) 2018 QNX Software Systems. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QQNXFOREIGNWINDOW_H
#define QQNXFOREIGNWINDOW_H
#include "qqnxwindow.h"
QT_BEGIN_NAMESPACE
class QQnxForeignWindow : public QQnxWindow
{
public:
QQnxForeignWindow(QWindow *window,
screen_context_t context,
screen_window_t screenWindow);
bool isForeignWindow() const override;
int pixelFormat() const override;
void resetBuffers() override {}
};
QT_END_NAMESPACE
#endif // QQNXFOREIGNWINDOW_H

View File

@ -51,6 +51,7 @@
#include "qqnxabstractvirtualkeyboard.h"
#include "qqnxservices.h"
#include "qqnxforeignwindow.h"
#include "qqnxrasterwindow.h"
#if !defined(QT_NO_OPENGL)
#include "qqnxeglwindow.h"
@ -147,6 +148,7 @@ static inline int getContextCapabilities(const QStringList &paramList)
QQnxIntegration::QQnxIntegration(const QStringList &paramList)
: QPlatformIntegration()
, m_screenContextId(256, 0)
, m_screenEventThread(0)
, m_navigatorEventHandler(new QQnxNavigatorEventHandler())
, m_virtualKeyboard(0)
@ -178,6 +180,11 @@ QQnxIntegration::QQnxIntegration(const QStringList &paramList)
qFatal("%s - Screen: Failed to create screen context - Error: %s (%i)",
Q_FUNC_INFO, strerror(errno), errno);
}
screen_get_context_property_cv(m_screenContext,
SCREEN_PROPERTY_ID,
m_screenContextId.size(),
m_screenContextId.data());
m_screenContextId.resize(strlen(m_screenContextId.constData()));
#if QT_CONFIG(qqnx_pps)
// Create/start navigator event notifier
@ -310,6 +317,7 @@ bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const
qIntegrationDebug();
switch (cap) {
case MultipleWindows:
case ForeignWindows:
case ThreadedPixmaps:
return true;
#if !defined(QT_NO_OPENGL)
@ -323,6 +331,18 @@ bool QQnxIntegration::hasCapability(QPlatformIntegration::Capability cap) const
}
}
QPlatformWindow *QQnxIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
{
screen_window_t screenWindow = reinterpret_cast<screen_window_t>(nativeHandle);
if (this->window(screenWindow)) {
qWarning() << "QWindow already created for foreign window"
<< screenWindow;
return nullptr;
}
return new QQnxForeignWindow(window, m_screenContext, screenWindow);
}
QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const
{
qIntegrationDebug();
@ -478,7 +498,7 @@ QPlatformServices * QQnxIntegration::services() const
return m_services;
}
QWindow *QQnxIntegration::window(screen_window_t qnxWindow)
QWindow *QQnxIntegration::window(screen_window_t qnxWindow) const
{
qIntegrationDebug();
QMutexLocker locker(&m_windowMapperMutex);
@ -706,6 +726,11 @@ screen_context_t QQnxIntegration::screenContext()
return m_screenContext;
}
QByteArray QQnxIntegration::screenContextId()
{
return m_screenContextId;
}
QQnxNavigatorEventHandler *QQnxIntegration::navigatorEventHandler()
{
return m_navigatorEventHandler;

View File

@ -92,6 +92,7 @@ public:
bool hasCapability(QPlatformIntegration::Capability cap) const override;
QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override;
QPlatformWindow *createPlatformWindow(QWindow *window) const override;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
@ -123,7 +124,7 @@ public:
QPlatformServices *services() const override;
QWindow *window(screen_window_t qnxWindow);
QWindow *window(screen_window_t qnxWindow) const;
QQnxScreen *screenForNative(screen_display_t qnxScreen) const;
@ -132,6 +133,7 @@ public:
QQnxScreen *primaryDisplay() const;
Options options() const;
screen_context_t screenContext();
QByteArray screenContextId();
QQnxNavigatorEventHandler *navigatorEventHandler();
@ -145,6 +147,7 @@ private:
int displayCount);
screen_context_t m_screenContext;
QByteArray m_screenContextId;
QQnxScreenEventThread *m_screenEventThread;
QQnxNavigatorEventHandler *m_navigatorEventHandler;
QQnxAbstractVirtualKeyboard *m_virtualKeyboard;
@ -168,7 +171,7 @@ private:
QSimpleDrag *m_drag;
#endif
QQnxWindowMapper m_windowMapper;
QMutex m_windowMapperMutex;
mutable QMutex m_windowMapperMutex;
Options m_options;

View File

@ -45,6 +45,7 @@
#include "qqnxkeytranslator.h"
#include "qqnxscreen.h"
#include "qqnxscreeneventfilter.h"
#include "qqnxscreentraits.h"
#include <QDebug>
#include <QGuiApplication>
@ -89,6 +90,51 @@ static QString capKeyString(int cap, int modifiers, int key)
return QString();
}
template <typename T>
static void finishCloseEvent(screen_event_t event)
{
T t;
screen_get_event_property_pv(event,
screen_traits<T>::propertyName,
reinterpret_cast<void**>(&t));
screen_traits<T>::destroy(t);
}
static void finishCloseEvent(screen_event_t event)
{
// Let libscreen know that we're finished with anything that may have been acquired.
int objectType = SCREEN_OBJECT_TYPE_CONTEXT;
screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType);
switch (objectType) {
case SCREEN_OBJECT_TYPE_CONTEXT:
finishCloseEvent<screen_context_t>(event);
break;
case SCREEN_OBJECT_TYPE_DEVICE:
finishCloseEvent<screen_device_t>(event);
break;
case SCREEN_OBJECT_TYPE_DISPLAY:
// no screen_destroy_display
break;
case SCREEN_OBJECT_TYPE_GROUP:
finishCloseEvent<screen_group_t>(event);
break;
case SCREEN_OBJECT_TYPE_PIXMAP:
finishCloseEvent<screen_pixmap_t>(event);
break;
case SCREEN_OBJECT_TYPE_SESSION:
finishCloseEvent<screen_session_t>(event);
break;
#if _SCREEN_VERSION >= _SCREEN_MAKE_VERSION(2, 0, 0)
case SCREEN_OBJECT_TYPE_STREAM:
finishCloseEvent<screen_stream_t>(event);
break;
#endif
case SCREEN_OBJECT_TYPE_WINDOW:
finishCloseEvent<screen_window_t>(event);
break;
}
}
QT_BEGIN_NAMESPACE
QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration)
@ -251,6 +297,9 @@ void QQnxScreenEventHandler::processEvents()
bool handled = dispatcher && dispatcher->filterNativeEvent(QByteArrayLiteral("screen_event_t"), event, &result);
if (!handled)
handleEvent(event);
if (type == SCREEN_EVENT_CLOSE)
finishCloseEvent(event);
}
m_eventThread->armEventsPending(count);

View File

@ -0,0 +1,127 @@
/***************************************************************************
**
** Copyright (C) 2018 QNX Software Systems. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QQNXSCREENTRAITS_H
#define QQNXSCREENTRAITS_H
#include <screen/screen.h>
QT_BEGIN_NAMESPACE
template <typename T>
class screen_traits
{
};
template <>
class screen_traits<screen_context_t>
{
public:
typedef screen_context_t screen_type;
static const int propertyName = SCREEN_PROPERTY_CONTEXT;
static int destroy(screen_context_t context) { return screen_destroy_context(context); }
};
template <>
class screen_traits<screen_device_t>
{
public:
typedef screen_device_t screen_type;
static const int propertyName = SCREEN_PROPERTY_DEVICE;
static int destroy(screen_device_t device) { return screen_destroy_device(device); }
};
template <>
class screen_traits<screen_display_t>
{
public:
typedef screen_display_t screen_type;
static const int propertyName = SCREEN_PROPERTY_DISPLAY;
};
template <>
class screen_traits<screen_group_t>
{
public:
typedef screen_group_t screen_type;
static const int propertyName = SCREEN_PROPERTY_GROUP;
static int destroy(screen_group_t group) { return screen_destroy_group(group); }
};
template <>
class screen_traits<screen_pixmap_t>
{
public:
typedef screen_pixmap_t screen_type;
static const int propertyName = SCREEN_PROPERTY_PIXMAP;
static int destroy(screen_pixmap_t pixmap) { return screen_destroy_pixmap(pixmap); }
};
template <>
class screen_traits<screen_session_t>
{
public:
typedef screen_session_t screen_type;
static const int propertyName = SCREEN_PROPERTY_SESSION;
static int destroy(screen_session_t session) { return screen_destroy_session(session); }
};
#if _SCREEN_VERSION >= _SCREEN_MAKE_VERSION(2, 0, 0)
template <>
class screen_traits<screen_stream_t>
{
public:
typedef screen_stream_t screen_type;
static const int propertyName = SCREEN_PROPERTY_STREAM;
static int destroy(screen_stream_t stream) { return screen_destroy_stream(stream); }
};
#endif
template <>
class screen_traits<screen_window_t>
{
public:
typedef screen_window_t screen_type;
static const int propertyName = SCREEN_PROPERTY_WINDOW;
static int destroy(screen_window_t window) { return screen_destroy_window(window); }
};
QT_END_NAMESPACE
#endif // QQNXSCREENTRAITS_H

View File

@ -155,6 +155,7 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW
m_parentWindow(0),
m_visible(false),
m_exposed(true),
m_foreign(false),
m_windowState(Qt::WindowNoState),
m_mmRendererWindow(0),
m_firstActivateHandled(false)
@ -254,6 +255,39 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW
}
}
QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, screen_window_t screenWindow)
: QPlatformWindow(window)
, m_screenContext(context)
, m_window(screenWindow)
, m_screen(0)
, m_parentWindow(0)
, m_visible(false)
, m_exposed(true)
, m_foreign(true)
, m_windowState(Qt::WindowNoState)
, m_mmRendererWindow(0)
, m_parentGroupName(256, 0)
, m_isTopLevel(false)
{
qWindowDebug() << "window =" << window << ", size =" << window->size();
collectWindowGroup();
screen_get_window_property_cv(m_window,
SCREEN_PROPERTY_PARENT,
m_parentGroupName.size(),
m_parentGroupName.data());
m_parentGroupName.resize(strlen(m_parentGroupName.constData()));
// If a window group has been provided join it now. If it's an empty string that's OK too,
// it'll cause us not to join a group (the app will presumably join at some future time).
QVariant parentGroup = window->property("qnxInitialWindowGroup");
if (!parentGroup.isValid())
parentGroup = window->property("_q_platform_qnxParentGroup");
if (parentGroup.isValid() && parentGroup.canConvert<QByteArray>())
joinWindowGroup(parentGroup.toByteArray());
}
QQnxWindow::~QQnxWindow()
{
qWindowDebug() << "window =" << window();
@ -270,7 +304,11 @@ QQnxWindow::~QQnxWindow()
m_screen->updateHierarchy();
// Cleanup QNX window and its buffers
screen_destroy_window(m_window);
// Foreign windows are cleaned up externally after the CLOSE event has been handled.
if (m_foreign)
removeContextPermission();
else
screen_destroy_window(m_window);
}
void QQnxWindow::setGeometry(const QRect &rect)
@ -793,14 +831,24 @@ void QQnxWindow::initWindow()
setGeometryHelper(shouldMakeFullScreen() ? screen()->geometry() : window()->geometry());
}
void QQnxWindow::collectWindowGroup()
{
QByteArray groupName(256, 0);
Q_SCREEN_CHECKERROR(screen_get_window_property_cv(m_window,
SCREEN_PROPERTY_GROUP,
groupName.size(),
groupName.data()),
"Failed to retrieve window group");
groupName.resize(strlen(groupName.constData()));
m_windowGroupName = groupName;
}
void QQnxWindow::createWindowGroup()
{
// Generate a random window group name
m_windowGroupName = QUuid::createUuid().toByteArray();
// Create window group so child windows can be parented by container window
Q_SCREEN_CHECKERROR(screen_create_window_group(m_window, m_windowGroupName.constData()),
Q_SCREEN_CHECKERROR(screen_create_window_group(m_window, nullptr),
"Failed to create window group");
collectWindowGroup();
}
void QQnxWindow::joinWindowGroup(const QByteArray &groupName)
@ -809,6 +857,17 @@ void QQnxWindow::joinWindowGroup(const QByteArray &groupName)
qWindowDebug() << "group:" << groupName;
// screen has this annoying habit of generating a CLOSE/CREATE when the owner context of
// the parent group moves a foreign window to another group that it also owns. The
// CLOSE/CREATE changes the identity of the foreign window. Usually, this is undesirable.
// To prevent this CLOSE/CREATE when changing the parent group, we temporarily add a
// context permission for the Qt context. screen won't send a CLOSE/CREATE when the
// context has some permission other than the PARENT permission. If there isn't a new
// group (the window has no parent), this context permission is left in place.
if (m_foreign && !m_parentGroupName.isEmpty())\
addContextPermission();
if (!groupName.isEmpty()) {
if (groupName != m_parentGroupName) {
screen_join_window_group(m_window, groupName);
@ -827,6 +886,9 @@ void QQnxWindow::joinWindowGroup(const QByteArray &groupName)
m_parentGroupName = "";
}
if (m_foreign && !groupName.isEmpty())
removeContextPermission();
if (changed)
screen_flush_context(m_screenContext, 0);
}
@ -899,4 +961,26 @@ bool QQnxWindow::focusable() const
return (window()->flags() & Qt::WindowDoesNotAcceptFocus) != Qt::WindowDoesNotAcceptFocus;
}
void QQnxWindow::addContextPermission()
{
QByteArray grantString("context:");
grantString.append(QQnxIntegration::instance()->screenContextId());
grantString.append(":rw-");
screen_set_window_property_cv(m_window,
SCREEN_PROPERTY_PERMISSIONS,
grantString.length(),
grantString.data());
}
void QQnxWindow::removeContextPermission()
{
QByteArray revokeString("context:");
revokeString.append(QQnxIntegration::instance()->screenContextId());
revokeString.append(":---");
screen_set_window_property_cv(m_window,
SCREEN_PROPERTY_PERMISSIONS,
revokeString.length(),
revokeString.data());
}
QT_END_NAMESPACE

View File

@ -64,7 +64,8 @@ class QQnxWindow : public QPlatformWindow
{
friend class QQnxScreen;
public:
QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow);
explicit QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow);
explicit QQnxWindow(QWindow *window, screen_context_t context, screen_window_t screenWindow);
virtual ~QQnxWindow();
void setGeometry(const QRect &rect) override;
@ -124,6 +125,7 @@ protected:
screen_context_t m_screenContext;
private:
void collectWindowGroup();
void createWindowGroup();
void setGeometryHelper(const QRect &rect);
void removeFromParent();
@ -135,6 +137,9 @@ private:
bool showWithoutActivating() const;
bool focusable() const;
void addContextPermission();
void removeContextPermission();
screen_window_t m_window;
QSize m_bufferSize;
@ -144,6 +149,7 @@ private:
QScopedPointer<QQnxAbstractCover> m_cover;
bool m_visible;
bool m_exposed;
bool m_foreign;
QRect m_unmaximizedGeometry;
Qt::WindowStates m_windowState;
QString m_mmRendererWindowName;