qpa: remove mirclient
The Mir display server is now Wayland compatible, so a dedicated Mir client library is no longer necessary. [ChangeLog][Platform Specific Changes][Mir] The Mir platform plugin has been removed: use the Wayland plugin when connecting to a Mir display server. Change-Id: Ibc77698dd45a1afaf29f0d57b5e5cf7bd91735f5 Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io> Reviewed-by: Johan Helsing <johan.helsing@qt.io>
This commit is contained in:
parent
e48b854087
commit
8c73ddd8e3
@ -295,7 +295,6 @@ Gui, printing, widget options:
|
||||
-gbm ............... Enable backends for GBM [auto] (Linux only)
|
||||
-kms ............... Enable backends for KMS [auto] (Linux only)
|
||||
-linuxfb ........... Enable Linux Framebuffer support [auto] (Linux only)
|
||||
-mirclient ......... Enable Mir client support [no] (Linux only)
|
||||
-xcb ............... Enable X11 support. Select used xcb-* libraries [system/qt/no]
|
||||
(-qt-xcb still uses system version of libxcb itself)
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
"libjpeg": { "type": "enum", "values": [ "no", "qt", "system" ] },
|
||||
"libpng": { "type": "enum", "values": [ "no", "qt", "system" ] },
|
||||
"linuxfb": "boolean",
|
||||
"mirclient": "boolean",
|
||||
"mtdev": "boolean",
|
||||
"opengl": { "type": "optionalString", "values": [ "no", "yes", "desktop", "es2", "dynamic" ] },
|
||||
"opengl-es-2": { "type": "void", "name": "opengl", "value": "es2" },
|
||||
@ -394,20 +393,6 @@
|
||||
{ "lib": "zlib", "condition": "features.system-zlib" }
|
||||
]
|
||||
},
|
||||
"mirclient": {
|
||||
"label": "Mir client libraries",
|
||||
"test": {
|
||||
"tail": "static void surfaceCreateCallback(MirSurface*, void*) {}",
|
||||
"main": [
|
||||
"u_application_lifecycle_delegate_new();",
|
||||
"mir_surface_create(0, surfaceCreateCallback, 0);"
|
||||
]
|
||||
},
|
||||
"headers": [ "mir_toolkit/mir_client_library.h", "ubuntu/application/lifecycle_delegate.h", "EGL/egl.h" ],
|
||||
"sources": [
|
||||
{ "type": "pkgConfig", "args": "egl mirclient ubuntu-platform-api libcontent-hub >= 0.2.0" }
|
||||
]
|
||||
},
|
||||
"mtdev": {
|
||||
"label": "mtdev",
|
||||
"test": {
|
||||
@ -1294,13 +1279,6 @@
|
||||
],
|
||||
"output": [ "privateFeature" ]
|
||||
},
|
||||
"mirclient": {
|
||||
"label": "Mir client",
|
||||
"section": "Platform plugins",
|
||||
"autoDetect": false,
|
||||
"condition": "libs.mirclient && features.xkbcommon",
|
||||
"output": [ "privateFeature" ]
|
||||
},
|
||||
"mtdev": {
|
||||
"label": "mtdev",
|
||||
"condition": "libs.mtdev",
|
||||
@ -1827,7 +1805,7 @@ or may depend on your system and XQuartz setup."
|
||||
},
|
||||
{
|
||||
"type": "warning",
|
||||
"condition": "features.gui && config.linux && !config.android && !features.xcb && !features.eglfs && !features.directfb && !features.linuxfb && !features.mirclient",
|
||||
"condition": "features.gui && config.linux && !config.android && !features.xcb && !features.eglfs && !features.directfb && !features.linuxfb",
|
||||
"message": "No QPA platform plugin enabled! This will
|
||||
produce a Qt that cannot run GUI applications.
|
||||
See \"Platform backends\" in the output of --help."
|
||||
@ -1935,7 +1913,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla
|
||||
"eglfs_openwfd", "eglfs_viv", "eglfs_viv_wl", "eglfs_rcar", "eglfs_egldevice", "eglfs_gbm", "eglfs_vsp2", "eglfs_mali", "eglfs_brcm", "eglfs_x11"
|
||||
]
|
||||
},
|
||||
"linuxfb", "vnc", "mirclient",
|
||||
"linuxfb", "vnc",
|
||||
{
|
||||
"type": "feature",
|
||||
"condition": "config.integrity",
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"Keys": [ "mirclient" ]
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
TARGET = qmirclient
|
||||
|
||||
QT += \
|
||||
core-private gui-private dbus \
|
||||
theme_support-private eventdispatcher_support-private \
|
||||
fontdatabase_support-private egl_support-private
|
||||
|
||||
qtHaveModule(linuxaccessibility_support-private): \
|
||||
QT += linuxaccessibility_support-private
|
||||
|
||||
DEFINES += MESA_EGL_NO_X11_HEADERS
|
||||
# CONFIG += c++11 # only enables C++0x
|
||||
QMAKE_CXXFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -Werror -Wall
|
||||
QMAKE_LFLAGS += -std=c++11 -Wl,-no-undefined
|
||||
|
||||
QMAKE_USE_PRIVATE += mirclient
|
||||
|
||||
SOURCES = \
|
||||
qmirclientappstatecontroller.cpp \
|
||||
qmirclientbackingstore.cpp \
|
||||
qmirclientclipboard.cpp \
|
||||
qmirclientcursor.cpp \
|
||||
qmirclientdebugextension.cpp \
|
||||
qmirclientdesktopwindow.cpp \
|
||||
qmirclientglcontext.cpp \
|
||||
qmirclientinput.cpp \
|
||||
qmirclientintegration.cpp \
|
||||
qmirclientnativeinterface.cpp \
|
||||
qmirclientplatformservices.cpp \
|
||||
qmirclientplugin.cpp \
|
||||
qmirclientscreen.cpp \
|
||||
qmirclientscreenobserver.cpp \
|
||||
qmirclienttheme.cpp \
|
||||
qmirclientwindow.cpp
|
||||
|
||||
HEADERS = \
|
||||
qmirclientappstatecontroller.h \
|
||||
qmirclientbackingstore.h \
|
||||
qmirclientclipboard.h \
|
||||
qmirclientcursor.h \
|
||||
qmirclientdebugextension.h \
|
||||
qmirclientdesktopwindow.h \
|
||||
qmirclientglcontext.h \
|
||||
qmirclientinput.h \
|
||||
qmirclientintegration.h \
|
||||
qmirclientlogging.h \
|
||||
qmirclientnativeinterface.h \
|
||||
qmirclientorientationchangeevent_p.h \
|
||||
qmirclientplatformservices.h \
|
||||
qmirclientplugin.h \
|
||||
qmirclientscreen.h \
|
||||
qmirclientscreenobserver.h \
|
||||
qmirclienttheme.h \
|
||||
qmirclientwindow.h
|
||||
|
||||
QMAKE_USE_PRIVATE += xkbcommon
|
||||
|
||||
PLUGIN_TYPE = platforms
|
||||
PLUGIN_CLASS_NAME = MirServerIntegrationPlugin
|
||||
!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
|
||||
load(qt_plugin)
|
@ -1,102 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 "qmirclientappstatecontroller.h"
|
||||
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
/*
|
||||
* QMirClientAppStateController - updates Qt's QApplication::applicationState property.
|
||||
*
|
||||
* Tries to avoid active-inactive-active invocations using a timer. The rapid state
|
||||
* change can confuse some applications.
|
||||
*/
|
||||
|
||||
QMirClientAppStateController::QMirClientAppStateController()
|
||||
: m_suspended(false)
|
||||
, m_lastActive(true)
|
||||
{
|
||||
m_inactiveTimer.setSingleShot(true);
|
||||
m_inactiveTimer.setInterval(10);
|
||||
QObject::connect(&m_inactiveTimer, &QTimer::timeout, []()
|
||||
{
|
||||
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
|
||||
});
|
||||
}
|
||||
|
||||
void QMirClientAppStateController::setSuspended()
|
||||
{
|
||||
m_inactiveTimer.stop();
|
||||
if (!m_suspended) {
|
||||
m_suspended = true;
|
||||
|
||||
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended);
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientAppStateController::setResumed()
|
||||
{
|
||||
m_inactiveTimer.stop();
|
||||
if (m_suspended) {
|
||||
m_suspended = false;
|
||||
|
||||
if (m_lastActive) {
|
||||
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
|
||||
} else {
|
||||
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientAppStateController::setWindowFocused(bool focused)
|
||||
{
|
||||
if (m_suspended) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (focused) {
|
||||
m_inactiveTimer.stop();
|
||||
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
|
||||
} else {
|
||||
m_inactiveTimer.start();
|
||||
}
|
||||
|
||||
m_lastActive = focused;
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTAPPSTATECONTROLLER_H
|
||||
#define QMIRCLIENTAPPSTATECONTROLLER_H
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
class QMirClientAppStateController
|
||||
{
|
||||
public:
|
||||
QMirClientAppStateController();
|
||||
|
||||
void setSuspended();
|
||||
void setResumed();
|
||||
|
||||
void setWindowFocused(bool focused);
|
||||
|
||||
private:
|
||||
bool m_suspended;
|
||||
bool m_lastActive;
|
||||
QTimer m_inactiveTimer;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTAPPSTATECONTROLLER_H
|
@ -1,157 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 "qmirclientbackingstore.h"
|
||||
#include "qmirclientlogging.h"
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QOpenGLTexture>
|
||||
#include <QtGui/QMatrix4x4>
|
||||
#include <QtGui/qopengltextureblitter.h>
|
||||
#include <QtGui/qopenglfunctions.h>
|
||||
|
||||
QMirClientBackingStore::QMirClientBackingStore(QWindow* window)
|
||||
: QPlatformBackingStore(window)
|
||||
, mContext(new QOpenGLContext)
|
||||
, mTexture(new QOpenGLTexture(QOpenGLTexture::Target2D))
|
||||
, mBlitter(new QOpenGLTextureBlitter)
|
||||
{
|
||||
mContext->setFormat(window->requestedFormat());
|
||||
mContext->setScreen(window->screen());
|
||||
mContext->create();
|
||||
|
||||
window->setSurfaceType(QSurface::OpenGLSurface);
|
||||
}
|
||||
|
||||
QMirClientBackingStore::~QMirClientBackingStore()
|
||||
{
|
||||
mContext->makeCurrent(window()); // needed as QOpenGLTexture destructor assumes current context
|
||||
}
|
||||
|
||||
void QMirClientBackingStore::flush(QWindow* window, const QRegion& region, const QPoint& offset)
|
||||
{
|
||||
Q_UNUSED(region);
|
||||
Q_UNUSED(offset);
|
||||
mContext->makeCurrent(window);
|
||||
glViewport(0, 0, window->width(), window->height());
|
||||
|
||||
updateTexture();
|
||||
|
||||
if (!mBlitter->isCreated())
|
||||
mBlitter->create();
|
||||
|
||||
mBlitter->bind();
|
||||
mBlitter->blit(mTexture->textureId(), QMatrix4x4(), QOpenGLTextureBlitter::OriginTopLeft);
|
||||
mBlitter->release();
|
||||
|
||||
mContext->swapBuffers(window);
|
||||
}
|
||||
|
||||
void QMirClientBackingStore::updateTexture()
|
||||
{
|
||||
if (mDirty.isNull())
|
||||
return;
|
||||
|
||||
if (!mTexture->isCreated()) {
|
||||
mTexture->setMinificationFilter(QOpenGLTexture::Nearest);
|
||||
mTexture->setMagnificationFilter(QOpenGLTexture::Nearest);
|
||||
mTexture->setWrapMode(QOpenGLTexture::ClampToEdge);
|
||||
mTexture->setData(mImage, QOpenGLTexture::DontGenerateMipMaps);
|
||||
mTexture->create();
|
||||
}
|
||||
mTexture->bind();
|
||||
|
||||
QRegion fixed;
|
||||
QRect imageRect = mImage.rect();
|
||||
|
||||
for (const QRect &rect : mDirty) {
|
||||
// intersect with image rect to be sure
|
||||
QRect r = imageRect & rect;
|
||||
|
||||
// if the rect is wide enough it is cheaper to just extend it instead of doing an image copy
|
||||
if (r.width() >= imageRect.width() / 2) {
|
||||
r.setX(0);
|
||||
r.setWidth(imageRect.width());
|
||||
}
|
||||
|
||||
fixed |= r;
|
||||
}
|
||||
|
||||
for (const QRect &rect : fixed) {
|
||||
// if the sub-rect is full-width we can pass the image data directly to
|
||||
// OpenGL instead of copying, since there is no gap between scanlines
|
||||
if (rect.width() == imageRect.width()) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
mImage.constScanLine(rect.y()));
|
||||
} else {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
mImage.copy(rect).constBits());
|
||||
}
|
||||
}
|
||||
/* End of code taken from QEGLPlatformBackingStore */
|
||||
|
||||
mDirty = QRegion();
|
||||
}
|
||||
|
||||
|
||||
void QMirClientBackingStore::beginPaint(const QRegion& region)
|
||||
{
|
||||
mDirty |= region;
|
||||
}
|
||||
|
||||
void QMirClientBackingStore::resize(const QSize& size, const QRegion& /*staticContents*/)
|
||||
{
|
||||
mImage = QImage(size, QImage::Format_RGBA8888);
|
||||
|
||||
mContext->makeCurrent(window());
|
||||
|
||||
if (mTexture->isCreated())
|
||||
mTexture->destroy();
|
||||
}
|
||||
|
||||
QPaintDevice* QMirClientBackingStore::paintDevice()
|
||||
{
|
||||
return &mImage;
|
||||
}
|
||||
|
||||
QImage QMirClientBackingStore::toImage() const
|
||||
{
|
||||
// used by QPlatformBackingStore::composeAndFlush
|
||||
return mImage;
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTBACKINGSTORE_H
|
||||
#define QMIRCLIENTBACKINGSTORE_H
|
||||
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
|
||||
class QOpenGLContext;
|
||||
class QOpenGLTexture;
|
||||
class QOpenGLTextureBlitter;
|
||||
|
||||
class QMirClientBackingStore : public QPlatformBackingStore
|
||||
{
|
||||
public:
|
||||
QMirClientBackingStore(QWindow* window);
|
||||
virtual ~QMirClientBackingStore();
|
||||
|
||||
// QPlatformBackingStore methods.
|
||||
void beginPaint(const QRegion&) override;
|
||||
void flush(QWindow* window, const QRegion& region, const QPoint& offset) override;
|
||||
void resize(const QSize& size, const QRegion& staticContents) override;
|
||||
QPaintDevice* paintDevice() override;
|
||||
QImage toImage() const override;
|
||||
|
||||
protected:
|
||||
void updateTexture();
|
||||
|
||||
private:
|
||||
QScopedPointer<QOpenGLContext> mContext;
|
||||
QScopedPointer<QOpenGLTexture> mTexture;
|
||||
QScopedPointer<QOpenGLTextureBlitter> mBlitter;
|
||||
QImage mImage;
|
||||
QRegion mDirty;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTBACKINGSTORE_H
|
@ -1,181 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 "qmirclientclipboard.h"
|
||||
#include "qmirclientlogging.h"
|
||||
#include "qmirclientwindow.h"
|
||||
|
||||
#include <QDBusPendingCallWatcher>
|
||||
#include <QGuiApplication>
|
||||
#include <QSignalBlocker>
|
||||
#include <QtCore/QMimeData>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
// content-hub
|
||||
#include <com/ubuntu/content/hub.h>
|
||||
|
||||
// get this cumbersome nested namespace out of the way
|
||||
using namespace com::ubuntu::content;
|
||||
|
||||
QMirClientClipboard::QMirClientClipboard()
|
||||
: mMimeData(new QMimeData)
|
||||
, mContentHub(Hub::Client::instance())
|
||||
{
|
||||
connect(mContentHub, &Hub::pasteboardChanged, this, [this]() {
|
||||
if (mClipboardState == QMirClientClipboard::SyncedClipboard) {
|
||||
mClipboardState = QMirClientClipboard::OutdatedClipboard;
|
||||
emitChanged(QClipboard::Clipboard);
|
||||
}
|
||||
});
|
||||
|
||||
connect(qGuiApp, &QGuiApplication::applicationStateChanged,
|
||||
this, &QMirClientClipboard::onApplicationStateChanged);
|
||||
|
||||
requestMimeData();
|
||||
}
|
||||
|
||||
QMirClientClipboard::~QMirClientClipboard()
|
||||
{
|
||||
delete mMimeData;
|
||||
}
|
||||
|
||||
QMimeData* QMirClientClipboard::mimeData(QClipboard::Mode mode)
|
||||
{
|
||||
if (mode != QClipboard::Clipboard)
|
||||
return nullptr;
|
||||
|
||||
// Blocks dataChanged() signal from being emitted. Makes no sense to emit it from
|
||||
// inside the data getter.
|
||||
const QSignalBlocker blocker(this);
|
||||
|
||||
if (mClipboardState == OutdatedClipboard) {
|
||||
updateMimeData();
|
||||
} else if (mClipboardState == SyncingClipboard) {
|
||||
mPasteReply->waitForFinished();
|
||||
}
|
||||
|
||||
return mMimeData;
|
||||
}
|
||||
|
||||
void QMirClientClipboard::setMimeData(QMimeData* mimeData, QClipboard::Mode mode)
|
||||
{
|
||||
QWindow *focusWindow = QGuiApplication::focusWindow();
|
||||
if (focusWindow && mode == QClipboard::Clipboard && mimeData != nullptr) {
|
||||
QString surfaceId = static_cast<QMirClientWindow*>(focusWindow->handle())->persistentSurfaceId();
|
||||
|
||||
QDBusPendingCall reply = mContentHub->createPaste(surfaceId, *mimeData);
|
||||
|
||||
// Don't care whether it succeeded
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished,
|
||||
watcher, &QObject::deleteLater);
|
||||
|
||||
mMimeData = mimeData;
|
||||
mClipboardState = SyncedClipboard;
|
||||
emitChanged(QClipboard::Clipboard);
|
||||
}
|
||||
}
|
||||
|
||||
bool QMirClientClipboard::supportsMode(QClipboard::Mode mode) const
|
||||
{
|
||||
return mode == QClipboard::Clipboard;
|
||||
}
|
||||
|
||||
bool QMirClientClipboard::ownsMode(QClipboard::Mode mode) const
|
||||
{
|
||||
Q_UNUSED(mode);
|
||||
return false;
|
||||
}
|
||||
|
||||
void QMirClientClipboard::onApplicationStateChanged(Qt::ApplicationState state)
|
||||
{
|
||||
if (state == Qt::ApplicationActive) {
|
||||
// Only focused or active applications might be allowed to paste, so we probably
|
||||
// missed changes in the clipboard while we were hidden, inactive or, more importantly,
|
||||
// suspended.
|
||||
requestMimeData();
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientClipboard::updateMimeData()
|
||||
{
|
||||
if (qGuiApp->applicationState() != Qt::ApplicationActive) {
|
||||
// Don't even bother asking as content-hub would probably ignore our request (and should).
|
||||
return;
|
||||
}
|
||||
|
||||
delete mMimeData;
|
||||
|
||||
QWindow *focusWindow = QGuiApplication::focusWindow();
|
||||
if (focusWindow) {
|
||||
QString surfaceId = static_cast<QMirClientWindow*>(focusWindow->handle())->persistentSurfaceId();
|
||||
mMimeData = mContentHub->latestPaste(surfaceId);
|
||||
mClipboardState = SyncedClipboard;
|
||||
emitChanged(QClipboard::Clipboard);
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientClipboard::requestMimeData()
|
||||
{
|
||||
if (qGuiApp->applicationState() != Qt::ApplicationActive) {
|
||||
// Don't even bother asking as content-hub would probably ignore our request (and should).
|
||||
return;
|
||||
}
|
||||
|
||||
QWindow *focusWindow = QGuiApplication::focusWindow();
|
||||
if (!focusWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString surfaceId = static_cast<QMirClientWindow*>(focusWindow->handle())->persistentSurfaceId();
|
||||
QDBusPendingCall reply = mContentHub->requestLatestPaste(surfaceId);
|
||||
mClipboardState = SyncingClipboard;
|
||||
|
||||
mPasteReply = new QDBusPendingCallWatcher(reply, this);
|
||||
connect(mPasteReply, &QDBusPendingCallWatcher::finished,
|
||||
this, [this]() {
|
||||
delete mMimeData;
|
||||
mMimeData = mContentHub->paste(*mPasteReply);
|
||||
mClipboardState = SyncedClipboard;
|
||||
mPasteReply->deleteLater();
|
||||
mPasteReply = nullptr;
|
||||
emitChanged(QClipboard::Clipboard);
|
||||
});
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTCLIPBOARD_H
|
||||
#define QMIRCLIENTCLIPBOARD_H
|
||||
|
||||
#include <qpa/qplatformclipboard.h>
|
||||
|
||||
#include <QMimeData>
|
||||
#include <QPointer>
|
||||
|
||||
namespace com {
|
||||
namespace ubuntu {
|
||||
namespace content {
|
||||
class Hub;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class QDBusPendingCallWatcher;
|
||||
|
||||
class QMirClientClipboard : public QObject, public QPlatformClipboard
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QMirClientClipboard();
|
||||
virtual ~QMirClientClipboard();
|
||||
|
||||
// QPlatformClipboard methods.
|
||||
QMimeData* mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override;
|
||||
void setMimeData(QMimeData* data, QClipboard::Mode mode = QClipboard::Clipboard) override;
|
||||
bool supportsMode(QClipboard::Mode mode) const override;
|
||||
bool ownsMode(QClipboard::Mode mode) const override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onApplicationStateChanged(Qt::ApplicationState state);
|
||||
|
||||
private:
|
||||
void updateMimeData();
|
||||
void requestMimeData();
|
||||
|
||||
QMimeData *mMimeData;
|
||||
|
||||
enum {
|
||||
OutdatedClipboard, // Our mimeData is outdated, need to fetch latest from ContentHub
|
||||
SyncingClipboard, // Our mimeData is outdated and we are waiting for ContentHub to reply with the latest paste
|
||||
SyncedClipboard // Our mimeData is in sync with what ContentHub has
|
||||
} mClipboardState{OutdatedClipboard};
|
||||
|
||||
com::ubuntu::content::Hub *mContentHub;
|
||||
|
||||
QDBusPendingCallWatcher *mPasteReply{nullptr};
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTCLIPBOARD_H
|
@ -1,209 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015-2016 Canonical, Ltd.
|
||||
** 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 "qmirclientcursor.h"
|
||||
|
||||
#include "qmirclientlogging.h"
|
||||
#include "qmirclientwindow.h"
|
||||
|
||||
#include <mir_toolkit/mir_client_library.h>
|
||||
|
||||
Q_LOGGING_CATEGORY(mirclientCursor, "qt.qpa.mirclient.cursor", QtWarningMsg)
|
||||
|
||||
QMirClientCursor::QMirClientCursor(MirConnection *connection)
|
||||
: mConnection(connection)
|
||||
{
|
||||
/*
|
||||
* TODO: Add the missing cursors to Mir (LP: #1388987)
|
||||
* Those are the ones without a mir_ prefix, which are X11 cursors
|
||||
* and won't be understood by any shell other than Unity8.
|
||||
*/
|
||||
mShapeToCursorName[Qt::ArrowCursor] = mir_arrow_cursor_name;
|
||||
mShapeToCursorName[Qt::UpArrowCursor] = "up_arrow";
|
||||
mShapeToCursorName[Qt::CrossCursor] = mir_crosshair_cursor_name;
|
||||
mShapeToCursorName[Qt::WaitCursor] = mir_busy_cursor_name;
|
||||
mShapeToCursorName[Qt::IBeamCursor] = mir_caret_cursor_name;
|
||||
mShapeToCursorName[Qt::SizeVerCursor] = mir_vertical_resize_cursor_name;
|
||||
mShapeToCursorName[Qt::SizeHorCursor] = mir_horizontal_resize_cursor_name;
|
||||
mShapeToCursorName[Qt::SizeBDiagCursor] = mir_diagonal_resize_bottom_to_top_cursor_name;
|
||||
mShapeToCursorName[Qt::SizeFDiagCursor] = mir_diagonal_resize_top_to_bottom_cursor_name;
|
||||
mShapeToCursorName[Qt::SizeAllCursor] = mir_omnidirectional_resize_cursor_name;
|
||||
mShapeToCursorName[Qt::BlankCursor] = mir_disabled_cursor_name;
|
||||
mShapeToCursorName[Qt::SplitVCursor] = mir_vsplit_resize_cursor_name;
|
||||
mShapeToCursorName[Qt::SplitHCursor] = mir_hsplit_resize_cursor_name;
|
||||
mShapeToCursorName[Qt::PointingHandCursor] = mir_pointing_hand_cursor_name;
|
||||
mShapeToCursorName[Qt::ForbiddenCursor] = "forbidden";
|
||||
mShapeToCursorName[Qt::WhatsThisCursor] = "whats_this";
|
||||
mShapeToCursorName[Qt::BusyCursor] = "left_ptr_watch";
|
||||
mShapeToCursorName[Qt::OpenHandCursor] = mir_open_hand_cursor_name;
|
||||
mShapeToCursorName[Qt::ClosedHandCursor] = mir_closed_hand_cursor_name;
|
||||
mShapeToCursorName[Qt::DragCopyCursor] = "dnd-copy";
|
||||
mShapeToCursorName[Qt::DragMoveCursor] = "dnd-move";
|
||||
mShapeToCursorName[Qt::DragLinkCursor] = "dnd-link";
|
||||
}
|
||||
|
||||
namespace {
|
||||
const char *qtCursorShapeToStr(Qt::CursorShape shape)
|
||||
{
|
||||
switch (shape) {
|
||||
case Qt::ArrowCursor:
|
||||
return "Arrow";
|
||||
case Qt::UpArrowCursor:
|
||||
return "UpArrow";
|
||||
case Qt::CrossCursor:
|
||||
return "Cross";
|
||||
case Qt::WaitCursor:
|
||||
return "Wait";
|
||||
case Qt::IBeamCursor:
|
||||
return "IBeam";
|
||||
case Qt::SizeVerCursor:
|
||||
return "SizeVer";
|
||||
case Qt::SizeHorCursor:
|
||||
return "SizeHor";
|
||||
case Qt::SizeBDiagCursor:
|
||||
return "SizeBDiag";
|
||||
case Qt::SizeFDiagCursor:
|
||||
return "SizeFDiag";
|
||||
case Qt::SizeAllCursor:
|
||||
return "SizeAll";
|
||||
case Qt::BlankCursor:
|
||||
return "Blank";
|
||||
case Qt::SplitVCursor:
|
||||
return "SplitV";
|
||||
case Qt::SplitHCursor:
|
||||
return "SplitH";
|
||||
case Qt::PointingHandCursor:
|
||||
return "PointingHand";
|
||||
case Qt::ForbiddenCursor:
|
||||
return "Forbidden";
|
||||
case Qt::WhatsThisCursor:
|
||||
return "WhatsThis";
|
||||
case Qt::BusyCursor:
|
||||
return "Busy";
|
||||
case Qt::OpenHandCursor:
|
||||
return "OpenHand";
|
||||
case Qt::ClosedHandCursor:
|
||||
return "ClosedHand";
|
||||
case Qt::DragCopyCursor:
|
||||
return "DragCopy";
|
||||
case Qt::DragMoveCursor:
|
||||
return "DragMove";
|
||||
case Qt::DragLinkCursor:
|
||||
return "DragLink";
|
||||
case Qt::BitmapCursor:
|
||||
return "Bitmap";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
void QMirClientCursor::changeCursor(QCursor *windowCursor, QWindow *window)
|
||||
{
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
MirSurface *surface = static_cast<QMirClientWindow*>(window->handle())->mirSurface();
|
||||
|
||||
if (!surface) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (windowCursor) {
|
||||
qCDebug(mirclientCursor, "changeCursor shape=%s, window=%p", qtCursorShapeToStr(windowCursor->shape()), window);
|
||||
if (!windowCursor->pixmap().isNull()) {
|
||||
configureMirCursorWithPixmapQCursor(surface, *windowCursor);
|
||||
} else if (windowCursor->shape() == Qt::BitmapCursor) {
|
||||
// TODO: Implement bitmap cursor support
|
||||
applyDefaultCursorConfiguration(surface);
|
||||
} else {
|
||||
const auto &cursorName = mShapeToCursorName.value(windowCursor->shape(), QByteArray("left_ptr"));
|
||||
auto cursorConfiguration = mir_cursor_configuration_from_name(cursorName.data());
|
||||
mir_surface_configure_cursor(surface, cursorConfiguration);
|
||||
mir_cursor_configuration_destroy(cursorConfiguration);
|
||||
}
|
||||
} else {
|
||||
applyDefaultCursorConfiguration(surface);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QMirClientCursor::configureMirCursorWithPixmapQCursor(MirSurface *surface, QCursor &cursor)
|
||||
{
|
||||
QImage image = cursor.pixmap().toImage();
|
||||
|
||||
if (image.format() != QImage::Format_ARGB32) {
|
||||
image = image.convertToFormat(QImage::Format_ARGB32);
|
||||
}
|
||||
|
||||
MirBufferStream *bufferStream = mir_connection_create_buffer_stream_sync(mConnection,
|
||||
image.width(), image.height(), mir_pixel_format_argb_8888, mir_buffer_usage_software);
|
||||
|
||||
{
|
||||
MirGraphicsRegion region;
|
||||
mir_buffer_stream_get_graphics_region(bufferStream, ®ion);
|
||||
|
||||
char *regionLine = region.vaddr;
|
||||
Q_ASSERT(image.bytesPerLine() <= region.stride);
|
||||
for (int i = 0; i < image.height(); ++i) {
|
||||
memcpy(regionLine, image.scanLine(i), image.bytesPerLine());
|
||||
regionLine += region.stride;
|
||||
}
|
||||
}
|
||||
|
||||
mir_buffer_stream_swap_buffers_sync(bufferStream);
|
||||
|
||||
{
|
||||
auto configuration = mir_cursor_configuration_from_buffer_stream(bufferStream, cursor.hotSpot().x(), cursor.hotSpot().y());
|
||||
mir_surface_configure_cursor(surface, configuration);
|
||||
mir_cursor_configuration_destroy(configuration);
|
||||
}
|
||||
|
||||
mir_buffer_stream_release_sync(bufferStream);
|
||||
}
|
||||
|
||||
void QMirClientCursor::applyDefaultCursorConfiguration(MirSurface *surface)
|
||||
{
|
||||
auto cursorConfiguration = mir_cursor_configuration_from_name("left_ptr");
|
||||
mir_surface_configure_cursor(surface, cursorConfiguration);
|
||||
mir_cursor_configuration_destroy(cursorConfiguration);
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015-2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTCURSOR_H
|
||||
#define QMIRCLIENTCURSOR_H
|
||||
|
||||
#include <qpa/qplatformcursor.h>
|
||||
|
||||
#include <QMap>
|
||||
#include <QByteArray>
|
||||
|
||||
struct MirConnection;
|
||||
struct MirSurface;
|
||||
|
||||
class QMirClientCursor : public QPlatformCursor
|
||||
{
|
||||
public:
|
||||
QMirClientCursor(MirConnection *connection);
|
||||
void changeCursor(QCursor *windowCursor, QWindow *window) override;
|
||||
private:
|
||||
void configureMirCursorWithPixmapQCursor(MirSurface *surface, QCursor &cursor);
|
||||
void applyDefaultCursorConfiguration(MirSurface *surface);
|
||||
QMap<int, QByteArray> mShapeToCursorName;
|
||||
MirConnection *mConnection;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTCURSOR_H
|
@ -1,79 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 "qmirclientdebugextension.h"
|
||||
|
||||
#include "qmirclientlogging.h"
|
||||
|
||||
// mir client debug
|
||||
#include <mir_toolkit/debug/surface.h>
|
||||
|
||||
Q_LOGGING_CATEGORY(mirclientDebug, "qt.qpa.mirclient.debug")
|
||||
|
||||
QMirClientDebugExtension::QMirClientDebugExtension()
|
||||
: m_mirclientDebug(QStringLiteral("mirclient-debug-extension"), 1)
|
||||
, m_mapper(nullptr)
|
||||
{
|
||||
qCDebug(mirclientDebug) << "NOTICE: Loading mirclient-debug-extension";
|
||||
m_mapper = (MapperPrototype) m_mirclientDebug.resolve("mir_debug_surface_coords_to_screen");
|
||||
|
||||
if (!m_mirclientDebug.isLoaded()) {
|
||||
qCWarning(mirclientDebug) << "ERROR: mirclient-debug-extension failed to load:"
|
||||
<< m_mirclientDebug.errorString();
|
||||
} else if (!m_mapper) {
|
||||
qCWarning(mirclientDebug) << "ERROR: unable to find required symbols in mirclient-debug-extension:"
|
||||
<< m_mirclientDebug.errorString();
|
||||
}
|
||||
}
|
||||
|
||||
QPoint QMirClientDebugExtension::mapSurfacePointToScreen(MirSurface *surface, const QPoint &point)
|
||||
{
|
||||
if (!m_mapper) {
|
||||
return point;
|
||||
}
|
||||
|
||||
QPoint mappedPoint;
|
||||
bool status = m_mapper(surface, point.x(), point.y(), &mappedPoint.rx(), &mappedPoint.ry());
|
||||
if (status) {
|
||||
return mappedPoint;
|
||||
} else {
|
||||
return point;
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTDEBUGEXTENSION_H
|
||||
#define QMIRCLIENTDEBUGEXTENSION_H
|
||||
|
||||
#include <QPoint>
|
||||
#include <QLibrary>
|
||||
struct MirSurface;
|
||||
|
||||
typedef bool (*MapperPrototype)(MirSurface* surface, int x, int y, int* screenX, int* screenY);
|
||||
|
||||
|
||||
class QMirClientDebugExtension
|
||||
{
|
||||
public:
|
||||
QMirClientDebugExtension();
|
||||
|
||||
QPoint mapSurfacePointToScreen(MirSurface *, const QPoint &point);
|
||||
|
||||
private:
|
||||
QLibrary m_mirclientDebug;
|
||||
MapperPrototype m_mapper;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTDEBUGEXTENSION_H
|
@ -1,50 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 "qmirclientdesktopwindow.h"
|
||||
|
||||
// local
|
||||
#include "qmirclientlogging.h"
|
||||
|
||||
QMirClientDesktopWindow::QMirClientDesktopWindow(QWindow *window)
|
||||
: QPlatformWindow(window)
|
||||
{
|
||||
qCDebug(mirclient, "QMirClientDesktopWindow(window=%p)", window);
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTDESKTOPWINDOW_H
|
||||
#define QMIRCLIENTDESKTOPWINDOW_H
|
||||
|
||||
#include <qpa/qplatformwindow.h>
|
||||
|
||||
// TODO Implement it. For now it's just an empty, dummy class.
|
||||
class QMirClientDesktopWindow : public QPlatformWindow
|
||||
{
|
||||
public:
|
||||
QMirClientDesktopWindow(QWindow*);
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTDESKTOPWINDOW_H
|
@ -1,132 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 "qmirclientglcontext.h"
|
||||
#include "qmirclientlogging.h"
|
||||
#include "qmirclientwindow.h"
|
||||
|
||||
#include <QOpenGLFramebufferObject>
|
||||
#include <QtEglSupport/private/qeglconvenience_p.h>
|
||||
#include <QtEglSupport/private/qeglpbuffer_p.h>
|
||||
#include <QtGui/private/qopenglcontext_p.h>
|
||||
|
||||
Q_LOGGING_CATEGORY(mirclientGraphics, "qt.qpa.mirclient.graphics", QtWarningMsg)
|
||||
|
||||
namespace {
|
||||
|
||||
void printEglConfig(EGLDisplay display, EGLConfig config)
|
||||
{
|
||||
Q_ASSERT(display != EGL_NO_DISPLAY);
|
||||
Q_ASSERT(config != nullptr);
|
||||
|
||||
const char *string = eglQueryString(display, EGL_VENDOR);
|
||||
qCDebug(mirclientGraphics, "EGL vendor: %s", string);
|
||||
|
||||
string = eglQueryString(display, EGL_VERSION);
|
||||
qCDebug(mirclientGraphics, "EGL version: %s", string);
|
||||
|
||||
string = eglQueryString(display, EGL_EXTENSIONS);
|
||||
qCDebug(mirclientGraphics, "EGL extensions: %s", string);
|
||||
|
||||
qCDebug(mirclientGraphics, "EGL configuration attributes:");
|
||||
q_printEglConfig(display, config);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
QMirClientOpenGLContext::QMirClientOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
|
||||
EGLDisplay display)
|
||||
: QEGLPlatformContext(format, share, display, 0)
|
||||
{
|
||||
if (mirclientGraphics().isDebugEnabled()) {
|
||||
printEglConfig(display, eglConfig());
|
||||
}
|
||||
}
|
||||
|
||||
static bool needsFBOReadBackWorkaround()
|
||||
{
|
||||
static bool set = false;
|
||||
static bool needsWorkaround = false;
|
||||
|
||||
if (Q_UNLIKELY(!set)) {
|
||||
const char *rendererString = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
|
||||
needsWorkaround = qstrncmp(rendererString, "Mali-400", 8) == 0
|
||||
|| qstrncmp(rendererString, "Mali-T7", 7) == 0
|
||||
|| qstrncmp(rendererString, "PowerVR Rogue G6200", 19) == 0;
|
||||
set = true;
|
||||
}
|
||||
|
||||
return needsWorkaround;
|
||||
}
|
||||
|
||||
bool QMirClientOpenGLContext::makeCurrent(QPlatformSurface* surface)
|
||||
{
|
||||
const bool ret = QEGLPlatformContext::makeCurrent(surface);
|
||||
|
||||
if (Q_LIKELY(ret)) {
|
||||
QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context());
|
||||
if (!ctx_d->workaround_brokenFBOReadBack && needsFBOReadBackWorkaround()) {
|
||||
ctx_d->workaround_brokenFBOReadBack = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Following method used internally in the base class QEGLPlatformContext to access
|
||||
// the egl surface of a QPlatformSurface/QMirClientWindow
|
||||
EGLSurface QMirClientOpenGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
|
||||
{
|
||||
if (surface->surface()->surfaceClass() == QSurface::Window) {
|
||||
return static_cast<QMirClientWindow *>(surface)->eglSurface();
|
||||
} else {
|
||||
return static_cast<QEGLPbuffer *>(surface)->pbuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientOpenGLContext::swapBuffers(QPlatformSurface* surface)
|
||||
{
|
||||
QEGLPlatformContext::swapBuffers(surface);
|
||||
|
||||
if (surface->surface()->surfaceClass() == QSurface::Window) {
|
||||
// notify window on swap completion
|
||||
auto platformWindow = static_cast<QMirClientWindow *>(surface);
|
||||
platformWindow->onSwapBuffersDone();
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTGLCONTEXT_H
|
||||
#define QMIRCLIENTGLCONTEXT_H
|
||||
|
||||
#include <qpa/qplatformopenglcontext.h>
|
||||
#include <QtEglSupport/private/qeglplatformcontext_p.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
class QMirClientOpenGLContext : public QEGLPlatformContext
|
||||
{
|
||||
public:
|
||||
QMirClientOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
|
||||
EGLDisplay display);
|
||||
|
||||
// QEGLPlatformContext methods.
|
||||
void swapBuffers(QPlatformSurface *surface) final;
|
||||
bool makeCurrent(QPlatformSurface *surface) final;
|
||||
|
||||
protected:
|
||||
EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) final;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTGLCONTEXT_H
|
@ -1,708 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014-2016 Canonical, Ltd.
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
// Local
|
||||
#include "qmirclientinput.h"
|
||||
#include "qmirclientintegration.h"
|
||||
#include "qmirclientnativeinterface.h"
|
||||
#include "qmirclientscreen.h"
|
||||
#include "qmirclientwindow.h"
|
||||
#include "qmirclientlogging.h"
|
||||
#include "qmirclientorientationchangeevent_p.h"
|
||||
|
||||
// Qt
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
#include <qpa/qplatforminputcontext.h>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <QTextCodec>
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-keysyms.h>
|
||||
|
||||
#include <mir_toolkit/mir_client_library.h>
|
||||
|
||||
Q_LOGGING_CATEGORY(mirclientInput, "qt.qpa.mirclient.input", QtWarningMsg)
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// XKB Keysyms which do not map directly to Qt types (i.e. Unicode points)
|
||||
static const uint32_t KeyTable[] = {
|
||||
XKB_KEY_Escape, Qt::Key_Escape,
|
||||
XKB_KEY_Tab, Qt::Key_Tab,
|
||||
XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab,
|
||||
XKB_KEY_BackSpace, Qt::Key_Backspace,
|
||||
XKB_KEY_Return, Qt::Key_Return,
|
||||
XKB_KEY_Insert, Qt::Key_Insert,
|
||||
XKB_KEY_Delete, Qt::Key_Delete,
|
||||
XKB_KEY_Clear, Qt::Key_Delete,
|
||||
XKB_KEY_Pause, Qt::Key_Pause,
|
||||
XKB_KEY_Print, Qt::Key_Print,
|
||||
|
||||
XKB_KEY_Home, Qt::Key_Home,
|
||||
XKB_KEY_End, Qt::Key_End,
|
||||
XKB_KEY_Left, Qt::Key_Left,
|
||||
XKB_KEY_Up, Qt::Key_Up,
|
||||
XKB_KEY_Right, Qt::Key_Right,
|
||||
XKB_KEY_Down, Qt::Key_Down,
|
||||
XKB_KEY_Prior, Qt::Key_PageUp,
|
||||
XKB_KEY_Next, Qt::Key_PageDown,
|
||||
|
||||
XKB_KEY_Shift_L, Qt::Key_Shift,
|
||||
XKB_KEY_Shift_R, Qt::Key_Shift,
|
||||
XKB_KEY_Shift_Lock, Qt::Key_Shift,
|
||||
XKB_KEY_Control_L, Qt::Key_Control,
|
||||
XKB_KEY_Control_R, Qt::Key_Control,
|
||||
XKB_KEY_Meta_L, Qt::Key_Meta,
|
||||
XKB_KEY_Meta_R, Qt::Key_Meta,
|
||||
XKB_KEY_Alt_L, Qt::Key_Alt,
|
||||
XKB_KEY_Alt_R, Qt::Key_Alt,
|
||||
XKB_KEY_Caps_Lock, Qt::Key_CapsLock,
|
||||
XKB_KEY_Num_Lock, Qt::Key_NumLock,
|
||||
XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock,
|
||||
XKB_KEY_Super_L, Qt::Key_Super_L,
|
||||
XKB_KEY_Super_R, Qt::Key_Super_R,
|
||||
XKB_KEY_Menu, Qt::Key_Menu,
|
||||
XKB_KEY_Hyper_L, Qt::Key_Hyper_L,
|
||||
XKB_KEY_Hyper_R, Qt::Key_Hyper_R,
|
||||
XKB_KEY_Help, Qt::Key_Help,
|
||||
|
||||
XKB_KEY_KP_Space, Qt::Key_Space,
|
||||
XKB_KEY_KP_Tab, Qt::Key_Tab,
|
||||
XKB_KEY_KP_Enter, Qt::Key_Enter,
|
||||
XKB_KEY_KP_Home, Qt::Key_Home,
|
||||
XKB_KEY_KP_Left, Qt::Key_Left,
|
||||
XKB_KEY_KP_Up, Qt::Key_Up,
|
||||
XKB_KEY_KP_Right, Qt::Key_Right,
|
||||
XKB_KEY_KP_Down, Qt::Key_Down,
|
||||
XKB_KEY_KP_Prior, Qt::Key_PageUp,
|
||||
XKB_KEY_KP_Next, Qt::Key_PageDown,
|
||||
XKB_KEY_KP_End, Qt::Key_End,
|
||||
XKB_KEY_KP_Begin, Qt::Key_Clear,
|
||||
XKB_KEY_KP_Insert, Qt::Key_Insert,
|
||||
XKB_KEY_KP_Delete, Qt::Key_Delete,
|
||||
XKB_KEY_KP_Equal, Qt::Key_Equal,
|
||||
XKB_KEY_KP_Multiply, Qt::Key_Asterisk,
|
||||
XKB_KEY_KP_Add, Qt::Key_Plus,
|
||||
XKB_KEY_KP_Separator, Qt::Key_Comma,
|
||||
XKB_KEY_KP_Subtract, Qt::Key_Minus,
|
||||
XKB_KEY_KP_Decimal, Qt::Key_Period,
|
||||
XKB_KEY_KP_Divide, Qt::Key_Slash,
|
||||
|
||||
XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr,
|
||||
XKB_KEY_Multi_key, Qt::Key_Multi_key,
|
||||
XKB_KEY_Codeinput, Qt::Key_Codeinput,
|
||||
XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate,
|
||||
XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate,
|
||||
XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate,
|
||||
|
||||
// dead keys
|
||||
XKB_KEY_dead_grave, Qt::Key_Dead_Grave,
|
||||
XKB_KEY_dead_acute, Qt::Key_Dead_Acute,
|
||||
XKB_KEY_dead_circumflex, Qt::Key_Dead_Circumflex,
|
||||
XKB_KEY_dead_tilde, Qt::Key_Dead_Tilde,
|
||||
XKB_KEY_dead_macron, Qt::Key_Dead_Macron,
|
||||
XKB_KEY_dead_breve, Qt::Key_Dead_Breve,
|
||||
XKB_KEY_dead_abovedot, Qt::Key_Dead_Abovedot,
|
||||
XKB_KEY_dead_diaeresis, Qt::Key_Dead_Diaeresis,
|
||||
XKB_KEY_dead_abovering, Qt::Key_Dead_Abovering,
|
||||
XKB_KEY_dead_doubleacute, Qt::Key_Dead_Doubleacute,
|
||||
XKB_KEY_dead_caron, Qt::Key_Dead_Caron,
|
||||
XKB_KEY_dead_cedilla, Qt::Key_Dead_Cedilla,
|
||||
XKB_KEY_dead_ogonek, Qt::Key_Dead_Ogonek,
|
||||
XKB_KEY_dead_iota, Qt::Key_Dead_Iota,
|
||||
XKB_KEY_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound,
|
||||
XKB_KEY_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound,
|
||||
XKB_KEY_dead_belowdot, Qt::Key_Dead_Belowdot,
|
||||
XKB_KEY_dead_hook, Qt::Key_Dead_Hook,
|
||||
XKB_KEY_dead_horn, Qt::Key_Dead_Horn,
|
||||
XKB_KEY_dead_stroke, Qt::Key_Dead_Stroke,
|
||||
XKB_KEY_dead_abovecomma, Qt::Key_Dead_Abovecomma,
|
||||
XKB_KEY_dead_abovereversedcomma, Qt::Key_Dead_Abovereversedcomma,
|
||||
XKB_KEY_dead_doublegrave, Qt::Key_Dead_Doublegrave,
|
||||
XKB_KEY_dead_belowring, Qt::Key_Dead_Belowring,
|
||||
XKB_KEY_dead_belowmacron, Qt::Key_Dead_Belowmacron,
|
||||
XKB_KEY_dead_belowcircumflex, Qt::Key_Dead_Belowcircumflex,
|
||||
XKB_KEY_dead_belowtilde, Qt::Key_Dead_Belowtilde,
|
||||
XKB_KEY_dead_belowbreve, Qt::Key_Dead_Belowbreve,
|
||||
XKB_KEY_dead_belowdiaeresis, Qt::Key_Dead_Belowdiaeresis,
|
||||
XKB_KEY_dead_invertedbreve, Qt::Key_Dead_Invertedbreve,
|
||||
XKB_KEY_dead_belowcomma, Qt::Key_Dead_Belowcomma,
|
||||
XKB_KEY_dead_currency, Qt::Key_Dead_Currency,
|
||||
XKB_KEY_dead_a, Qt::Key_Dead_a,
|
||||
XKB_KEY_dead_A, Qt::Key_Dead_A,
|
||||
XKB_KEY_dead_e, Qt::Key_Dead_e,
|
||||
XKB_KEY_dead_E, Qt::Key_Dead_E,
|
||||
XKB_KEY_dead_i, Qt::Key_Dead_i,
|
||||
XKB_KEY_dead_I, Qt::Key_Dead_I,
|
||||
XKB_KEY_dead_o, Qt::Key_Dead_o,
|
||||
XKB_KEY_dead_O, Qt::Key_Dead_O,
|
||||
XKB_KEY_dead_u, Qt::Key_Dead_u,
|
||||
XKB_KEY_dead_U, Qt::Key_Dead_U,
|
||||
XKB_KEY_dead_small_schwa, Qt::Key_Dead_Small_Schwa,
|
||||
XKB_KEY_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa,
|
||||
XKB_KEY_dead_greek, Qt::Key_Dead_Greek,
|
||||
XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline,
|
||||
XKB_KEY_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline,
|
||||
XKB_KEY_dead_belowverticalline, Qt::Key_Dead_Belowverticalline,
|
||||
XKB_KEY_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay,
|
||||
|
||||
XKB_KEY_Mode_switch, Qt::Key_Mode_switch,
|
||||
XKB_KEY_script_switch, Qt::Key_Mode_switch,
|
||||
XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp,
|
||||
XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown,
|
||||
XKB_KEY_XF86PowerOff, Qt::Key_PowerOff,
|
||||
XKB_KEY_XF86PowerDown, Qt::Key_PowerDown,
|
||||
|
||||
0, 0
|
||||
};
|
||||
|
||||
Qt::WindowState mirSurfaceStateToWindowState(MirSurfaceState state)
|
||||
{
|
||||
switch (state) {
|
||||
case mir_surface_state_fullscreen:
|
||||
return Qt::WindowFullScreen;
|
||||
case mir_surface_state_maximized:
|
||||
case mir_surface_state_vertmaximized:
|
||||
case mir_surface_state_horizmaximized:
|
||||
return Qt::WindowMaximized;
|
||||
case mir_surface_state_minimized:
|
||||
return Qt::WindowMinimized;
|
||||
case mir_surface_state_hidden:
|
||||
// We should be handling this state separately.
|
||||
Q_ASSERT(false);
|
||||
case mir_surface_state_restored:
|
||||
case mir_surface_state_unknown:
|
||||
default:
|
||||
return Qt::WindowNoState;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class UbuntuEvent : public QEvent
|
||||
{
|
||||
public:
|
||||
UbuntuEvent(QMirClientWindow* window, const MirEvent *event, QEvent::Type type)
|
||||
: QEvent(type), window(window) {
|
||||
nativeEvent = mir_event_ref(event);
|
||||
}
|
||||
~UbuntuEvent()
|
||||
{
|
||||
mir_event_unref(nativeEvent);
|
||||
}
|
||||
|
||||
QPointer<QMirClientWindow> window;
|
||||
const MirEvent *nativeEvent;
|
||||
};
|
||||
|
||||
QMirClientInput::QMirClientInput(QMirClientClientIntegration* integration)
|
||||
: QObject(nullptr)
|
||||
, mIntegration(integration)
|
||||
, mEventFilterType(static_cast<QMirClientNativeInterface*>(
|
||||
integration->nativeInterface())->genericEventFilterType())
|
||||
, mEventType(static_cast<QEvent::Type>(QEvent::registerEventType()))
|
||||
, mLastInputWindow(nullptr)
|
||||
{
|
||||
// Initialize touch device.
|
||||
mTouchDevice = new QTouchDevice;
|
||||
mTouchDevice->setType(QTouchDevice::TouchScreen);
|
||||
mTouchDevice->setCapabilities(
|
||||
QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure |
|
||||
QTouchDevice::NormalizedPosition);
|
||||
QWindowSystemInterface::registerTouchDevice(mTouchDevice);
|
||||
}
|
||||
|
||||
QMirClientInput::~QMirClientInput()
|
||||
{
|
||||
// Qt will take care of deleting mTouchDevice.
|
||||
}
|
||||
|
||||
static const char* nativeEventTypeToStr(MirEventType t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case mir_event_type_key:
|
||||
return "key";
|
||||
case mir_event_type_motion:
|
||||
return "motion";
|
||||
case mir_event_type_surface:
|
||||
return "surface";
|
||||
case mir_event_type_resize:
|
||||
return "resize";
|
||||
case mir_event_type_prompt_session_state_change:
|
||||
return "prompt_session_state_change";
|
||||
case mir_event_type_orientation:
|
||||
return "orientation";
|
||||
case mir_event_type_close_surface:
|
||||
return "close_surface";
|
||||
case mir_event_type_input:
|
||||
return "input";
|
||||
case mir_event_type_keymap:
|
||||
return "keymap";
|
||||
case mir_event_type_input_configuration:
|
||||
return "input_configuration";
|
||||
case mir_event_type_surface_output:
|
||||
return "surface_output";
|
||||
case mir_event_type_input_device_state:
|
||||
return "input_device_state";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientInput::customEvent(QEvent* event)
|
||||
{
|
||||
Q_ASSERT(QThread::currentThread() == thread());
|
||||
UbuntuEvent* ubuntuEvent = static_cast<UbuntuEvent*>(event);
|
||||
const MirEvent *nativeEvent = ubuntuEvent->nativeEvent;
|
||||
|
||||
if ((ubuntuEvent->window == nullptr) || (ubuntuEvent->window->window() == nullptr)) {
|
||||
qCWarning(mirclient) << "Attempted to deliver an event to a non-existent window, ignoring.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Event filtering.
|
||||
long result;
|
||||
if (QWindowSystemInterface::handleNativeEvent(
|
||||
ubuntuEvent->window->window(), mEventFilterType,
|
||||
const_cast<void *>(static_cast<const void *>(nativeEvent)), &result) == true) {
|
||||
qCDebug(mirclient, "event filtered out by native interface");
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(mirclientInput, "customEvent(type=%s)", nativeEventTypeToStr(mir_event_get_type(nativeEvent)));
|
||||
|
||||
// Event dispatching.
|
||||
switch (mir_event_get_type(nativeEvent))
|
||||
{
|
||||
case mir_event_type_input:
|
||||
dispatchInputEvent(ubuntuEvent->window, mir_event_get_input_event(nativeEvent));
|
||||
break;
|
||||
case mir_event_type_resize:
|
||||
{
|
||||
auto resizeEvent = mir_event_get_resize_event(nativeEvent);
|
||||
|
||||
// Enable workaround for Screen rotation
|
||||
auto const targetWindow = ubuntuEvent->window;
|
||||
if (targetWindow) {
|
||||
auto const screen = static_cast<QMirClientScreen*>(targetWindow->screen());
|
||||
if (screen) {
|
||||
screen->handleWindowSurfaceResize(
|
||||
mir_resize_event_get_width(resizeEvent),
|
||||
mir_resize_event_get_height(resizeEvent));
|
||||
}
|
||||
|
||||
targetWindow->handleSurfaceResized(
|
||||
mir_resize_event_get_width(resizeEvent),
|
||||
mir_resize_event_get_height(resizeEvent));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case mir_event_type_surface:
|
||||
handleSurfaceEvent(ubuntuEvent->window, mir_event_get_surface_event(nativeEvent));
|
||||
break;
|
||||
case mir_event_type_surface_output:
|
||||
handleSurfaceOutputEvent(ubuntuEvent->window, mir_event_get_surface_output_event(nativeEvent));
|
||||
break;
|
||||
case mir_event_type_orientation:
|
||||
dispatchOrientationEvent(ubuntuEvent->window->window(), mir_event_get_orientation_event(nativeEvent));
|
||||
break;
|
||||
case mir_event_type_close_surface:
|
||||
QWindowSystemInterface::handleCloseEvent(ubuntuEvent->window->window());
|
||||
break;
|
||||
default:
|
||||
qCDebug(mirclient, "unhandled event type: %d", static_cast<int>(mir_event_get_type(nativeEvent)));
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientInput::postEvent(QMirClientWindow *platformWindow, const MirEvent *event)
|
||||
{
|
||||
QWindow *window = platformWindow->window();
|
||||
|
||||
QCoreApplication::postEvent(this, new UbuntuEvent(
|
||||
platformWindow, event, mEventType));
|
||||
|
||||
if ((window->flags().testFlag(Qt::WindowTransparentForInput)) && window->parent()) {
|
||||
QCoreApplication::postEvent(this, new UbuntuEvent(
|
||||
static_cast<QMirClientWindow*>(platformWindow->QPlatformWindow::parent()),
|
||||
event, mEventType));
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientInput::dispatchInputEvent(QMirClientWindow *window, const MirInputEvent *ev)
|
||||
{
|
||||
switch (mir_input_event_get_type(ev))
|
||||
{
|
||||
case mir_input_event_type_key:
|
||||
dispatchKeyEvent(window, ev);
|
||||
break;
|
||||
case mir_input_event_type_touch:
|
||||
dispatchTouchEvent(window, ev);
|
||||
break;
|
||||
case mir_input_event_type_pointer:
|
||||
dispatchPointerEvent(window, ev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientInput::dispatchTouchEvent(QMirClientWindow *window, const MirInputEvent *ev)
|
||||
{
|
||||
const MirTouchEvent *tev = mir_input_event_get_touch_event(ev);
|
||||
|
||||
// FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That
|
||||
// needs to be fixed as soon as the compat input lib adds query support.
|
||||
const float kMaxPressure = 1.28;
|
||||
const QRect kWindowGeometry = window->geometry();
|
||||
QList<QWindowSystemInterface::TouchPoint> touchPoints;
|
||||
|
||||
|
||||
// TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left
|
||||
// as Qt::TouchPointMoved
|
||||
const unsigned int kPointerCount = mir_touch_event_point_count(tev);
|
||||
touchPoints.reserve(int(kPointerCount));
|
||||
for (unsigned int i = 0; i < kPointerCount; ++i) {
|
||||
QWindowSystemInterface::TouchPoint touchPoint;
|
||||
|
||||
const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x) + kWindowGeometry.x();
|
||||
const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y) + kWindowGeometry.y(); // see bug lp:1346633 workaround comments elsewhere
|
||||
const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major);
|
||||
const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor);
|
||||
const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure);
|
||||
touchPoint.id = mir_touch_event_id(tev, i);
|
||||
touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height());
|
||||
touchPoint.area = QRectF(kX - (kW / 2.0), kY - (kH / 2.0), kW, kH);
|
||||
touchPoint.pressure = kP / kMaxPressure;
|
||||
|
||||
MirTouchAction touch_action = mir_touch_event_action(tev, i);
|
||||
switch (touch_action)
|
||||
{
|
||||
case mir_touch_action_down:
|
||||
mLastInputWindow = window;
|
||||
touchPoint.state = Qt::TouchPointPressed;
|
||||
break;
|
||||
case mir_touch_action_up:
|
||||
touchPoint.state = Qt::TouchPointReleased;
|
||||
break;
|
||||
case mir_touch_action_change:
|
||||
touchPoint.state = Qt::TouchPointMoved;
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
touchPoints.append(touchPoint);
|
||||
}
|
||||
|
||||
ulong timestamp = mir_input_event_get_event_time(ev) / 1000000;
|
||||
QWindowSystemInterface::handleTouchEvent(window->window(), timestamp,
|
||||
mTouchDevice, touchPoints);
|
||||
}
|
||||
|
||||
static uint32_t translateKeysym(uint32_t sym, const QString &text) {
|
||||
int code = 0;
|
||||
|
||||
QTextCodec *systemCodec = QTextCodec::codecForLocale();
|
||||
if (sym < 128 || (sym < 256 && systemCodec->mibEnum() == 4)) {
|
||||
// upper-case key, if known
|
||||
code = isprint((int)sym) ? toupper((int)sym) : 0;
|
||||
} else if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F35) {
|
||||
return Qt::Key_F1 + (int(sym) - XKB_KEY_F1);
|
||||
} else if (text.length() == 1 && text.unicode()->unicode() > 0x1f
|
||||
&& text.unicode()->unicode() != 0x7f
|
||||
&& !(sym >= XKB_KEY_dead_grave && sym <= XKB_KEY_dead_currency)) {
|
||||
code = text.unicode()->toUpper().unicode();
|
||||
} else {
|
||||
for (int i = 0; KeyTable[i]; i += 2)
|
||||
if (sym == KeyTable[i])
|
||||
code = KeyTable[i + 1];
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
Qt::KeyboardModifiers qt_modifiers_from_mir(MirInputEventModifiers modifiers)
|
||||
{
|
||||
Qt::KeyboardModifiers q_modifiers = Qt::NoModifier;
|
||||
if (modifiers & mir_input_event_modifier_shift) {
|
||||
q_modifiers |= Qt::ShiftModifier;
|
||||
}
|
||||
if (modifiers & mir_input_event_modifier_ctrl) {
|
||||
q_modifiers |= Qt::ControlModifier;
|
||||
}
|
||||
if (modifiers & mir_input_event_modifier_alt_left) {
|
||||
q_modifiers |= Qt::AltModifier;
|
||||
}
|
||||
if (modifiers & mir_input_event_modifier_meta) {
|
||||
q_modifiers |= Qt::MetaModifier;
|
||||
}
|
||||
if (modifiers & mir_input_event_modifier_alt_right) {
|
||||
q_modifiers |= Qt::GroupSwitchModifier;
|
||||
}
|
||||
return q_modifiers;
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientInput::dispatchKeyEvent(QMirClientWindow *window, const MirInputEvent *event)
|
||||
{
|
||||
const MirKeyboardEvent *key_event = mir_input_event_get_keyboard_event(event);
|
||||
|
||||
ulong timestamp = mir_input_event_get_event_time(event) / 1000000;
|
||||
xkb_keysym_t xk_sym = mir_keyboard_event_key_code(key_event);
|
||||
quint32 scan_code = mir_keyboard_event_scan_code(key_event);
|
||||
quint32 native_modifiers = mir_keyboard_event_modifiers(key_event);
|
||||
|
||||
// Key modifier and unicode index mapping.
|
||||
auto modifiers = qt_modifiers_from_mir(native_modifiers);
|
||||
|
||||
MirKeyboardAction action = mir_keyboard_event_action(key_event);
|
||||
QEvent::Type keyType = action == mir_keyboard_action_up
|
||||
? QEvent::KeyRelease : QEvent::KeyPress;
|
||||
|
||||
if (action == mir_keyboard_action_down)
|
||||
mLastInputWindow = window;
|
||||
|
||||
QString text;
|
||||
QVarLengthArray<char, 32> chars(32);
|
||||
{
|
||||
int result = xkb_keysym_to_utf8(xk_sym, chars.data(), chars.size());
|
||||
|
||||
if (result > 0) {
|
||||
text = QString::fromUtf8(chars.constData());
|
||||
}
|
||||
}
|
||||
int sym = translateKeysym(xk_sym, text);
|
||||
|
||||
bool is_auto_rep = action == mir_keyboard_action_repeat;
|
||||
|
||||
QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();
|
||||
if (context) {
|
||||
QKeyEvent qKeyEvent(keyType, sym, modifiers, scan_code, xk_sym, native_modifiers, text, is_auto_rep);
|
||||
qKeyEvent.setTimestamp(timestamp);
|
||||
if (context->filterEvent(&qKeyEvent)) {
|
||||
qCDebug(mirclient, "key event filtered out by input context");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QWindowSystemInterface::handleExtendedKeyEvent(window->window(), timestamp, keyType, sym, modifiers, scan_code, xk_sym, native_modifiers, text, is_auto_rep);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
Qt::MouseButtons extract_buttons(const MirPointerEvent *pev)
|
||||
{
|
||||
Qt::MouseButtons buttons = Qt::NoButton;
|
||||
if (mir_pointer_event_button_state(pev, mir_pointer_button_primary))
|
||||
buttons |= Qt::LeftButton;
|
||||
if (mir_pointer_event_button_state(pev, mir_pointer_button_secondary))
|
||||
buttons |= Qt::RightButton;
|
||||
if (mir_pointer_event_button_state(pev, mir_pointer_button_tertiary))
|
||||
buttons |= Qt::MiddleButton;
|
||||
if (mir_pointer_event_button_state(pev, mir_pointer_button_back))
|
||||
buttons |= Qt::BackButton;
|
||||
if (mir_pointer_event_button_state(pev, mir_pointer_button_forward))
|
||||
buttons |= Qt::ForwardButton;
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientInput::dispatchPointerEvent(QMirClientWindow *platformWindow, const MirInputEvent *ev)
|
||||
{
|
||||
const auto window = platformWindow->window();
|
||||
const auto timestamp = mir_input_event_get_event_time(ev) / 1000000;
|
||||
|
||||
const auto pev = mir_input_event_get_pointer_event(ev);
|
||||
const auto action = mir_pointer_event_action(pev);
|
||||
|
||||
const auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev));
|
||||
const auto localPoint = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x),
|
||||
mir_pointer_event_axis_value(pev, mir_pointer_axis_y));
|
||||
|
||||
mLastInputWindow = platformWindow;
|
||||
|
||||
switch (action) {
|
||||
case mir_pointer_action_button_up:
|
||||
case mir_pointer_action_button_down:
|
||||
case mir_pointer_action_motion:
|
||||
{
|
||||
const float hDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_hscroll);
|
||||
const float vDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_vscroll);
|
||||
|
||||
if (hDelta != 0 || vDelta != 0) {
|
||||
// QWheelEvent::DefaultDeltasPerStep = 120 but doesn't exist on vivid
|
||||
const QPoint angleDelta(120 * hDelta, 120 * vDelta);
|
||||
QWindowSystemInterface::handleWheelEvent(window, timestamp, localPoint, window->position() + localPoint,
|
||||
QPoint(), angleDelta, modifiers, Qt::ScrollUpdate);
|
||||
}
|
||||
auto buttons = extract_buttons(pev);
|
||||
QWindowSystemInterface::handleMouseEvent(window, timestamp, localPoint, window->position() + localPoint /* Should we omit global point instead? */,
|
||||
buttons, modifiers);
|
||||
break;
|
||||
}
|
||||
case mir_pointer_action_enter:
|
||||
QWindowSystemInterface::handleEnterEvent(window, localPoint, window->position() + localPoint);
|
||||
break;
|
||||
case mir_pointer_action_leave:
|
||||
QWindowSystemInterface::handleLeaveEvent(window);
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
static const char* nativeOrientationDirectionToStr(MirOrientation orientation)
|
||||
{
|
||||
switch (orientation) {
|
||||
case mir_orientation_normal:
|
||||
return "Normal";
|
||||
case mir_orientation_left:
|
||||
return "Left";
|
||||
case mir_orientation_inverted:
|
||||
return "Inverted";
|
||||
case mir_orientation_right:
|
||||
return "Right";
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
void QMirClientInput::dispatchOrientationEvent(QWindow *window, const MirOrientationEvent *event)
|
||||
{
|
||||
MirOrientation mir_orientation = mir_orientation_event_get_direction(event);
|
||||
qCDebug(mirclientInput, "orientation direction: %s", nativeOrientationDirectionToStr(mir_orientation));
|
||||
|
||||
if (!window->screen()) {
|
||||
qCDebug(mirclient, "Window has no associated screen, dropping orientation event");
|
||||
return;
|
||||
}
|
||||
|
||||
OrientationChangeEvent::Orientation orientation;
|
||||
switch (mir_orientation) {
|
||||
case mir_orientation_normal:
|
||||
orientation = OrientationChangeEvent::TopUp;
|
||||
break;
|
||||
case mir_orientation_left:
|
||||
orientation = OrientationChangeEvent::LeftUp;
|
||||
break;
|
||||
case mir_orientation_inverted:
|
||||
orientation = OrientationChangeEvent::TopDown;
|
||||
break;
|
||||
case mir_orientation_right:
|
||||
orientation = OrientationChangeEvent::RightUp;
|
||||
break;
|
||||
default:
|
||||
qCDebug(mirclient, "No such orientation %d", mir_orientation);
|
||||
return;
|
||||
}
|
||||
|
||||
// Dispatch orientation event to [Platform]Screen, as that is where Qt reads it. Screen will handle
|
||||
// notifying Qt of the actual orientation change - done to prevent multiple Windows each creating
|
||||
// an identical orientation change event and passing it directly to Qt.
|
||||
// [Platform]Screen can also factor in the native orientation.
|
||||
QCoreApplication::postEvent(static_cast<QMirClientScreen*>(window->screen()->handle()),
|
||||
new OrientationChangeEvent(OrientationChangeEvent::mType, orientation));
|
||||
}
|
||||
|
||||
void QMirClientInput::handleSurfaceEvent(const QPointer<QMirClientWindow> &window, const MirSurfaceEvent *event)
|
||||
{
|
||||
auto surfaceEventAttribute = mir_surface_event_get_attribute(event);
|
||||
|
||||
switch (surfaceEventAttribute) {
|
||||
case mir_surface_attrib_focus: {
|
||||
window->handleSurfaceFocusChanged(
|
||||
mir_surface_event_get_attribute_value(event) == mir_surface_focused);
|
||||
break;
|
||||
}
|
||||
case mir_surface_attrib_visibility: {
|
||||
window->handleSurfaceExposeChange(
|
||||
mir_surface_event_get_attribute_value(event) == mir_surface_visibility_exposed);
|
||||
break;
|
||||
}
|
||||
// Remaining attributes are ones client sets for server, and server should not override them
|
||||
case mir_surface_attrib_state: {
|
||||
MirSurfaceState state = static_cast<MirSurfaceState>(mir_surface_event_get_attribute_value(event));
|
||||
|
||||
if (state == mir_surface_state_hidden) {
|
||||
window->handleSurfaceVisibilityChanged(false);
|
||||
} else {
|
||||
// it's visible!
|
||||
window->handleSurfaceVisibilityChanged(true);
|
||||
window->handleSurfaceStateChanged(mirSurfaceStateToWindowState(state));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case mir_surface_attrib_type:
|
||||
case mir_surface_attrib_swapinterval:
|
||||
case mir_surface_attrib_dpi:
|
||||
case mir_surface_attrib_preferred_orientation:
|
||||
case mir_surface_attribs:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientInput::handleSurfaceOutputEvent(const QPointer<QMirClientWindow> &window, const MirSurfaceOutputEvent *event)
|
||||
{
|
||||
const uint32_t outputId = mir_surface_output_event_get_output_id(event);
|
||||
const int dpi = mir_surface_output_event_get_dpi(event);
|
||||
const MirFormFactor formFactor = mir_surface_output_event_get_form_factor(event);
|
||||
const float scale = mir_surface_output_event_get_scale(event);
|
||||
|
||||
const auto screenObserver = mIntegration->screenObserver();
|
||||
QMirClientScreen *screen = screenObserver->findScreenWithId(outputId);
|
||||
if (!screen) {
|
||||
qCWarning(mirclient) << "Mir notified window" << window->window() << "on an unknown screen with id" << outputId;
|
||||
return;
|
||||
}
|
||||
|
||||
screenObserver->handleScreenPropertiesChange(screen, dpi, formFactor, scale);
|
||||
window->handleScreenPropertiesChange(formFactor, scale);
|
||||
|
||||
if (window->screen() != screen) {
|
||||
QWindowSystemInterface::handleWindowScreenChanged(window->window(), screen->screen());
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014-2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTINPUT_H
|
||||
#define QMIRCLIENTINPUT_H
|
||||
|
||||
// Qt
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
|
||||
#include <mir_toolkit/mir_client_library.h>
|
||||
|
||||
class QMirClientClientIntegration;
|
||||
class QMirClientWindow;
|
||||
|
||||
class QMirClientInput : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QMirClientInput(QMirClientClientIntegration* integration);
|
||||
virtual ~QMirClientInput();
|
||||
|
||||
// QObject methods.
|
||||
void customEvent(QEvent* event) override;
|
||||
|
||||
void postEvent(QMirClientWindow* window, const MirEvent *event);
|
||||
QMirClientClientIntegration* integration() const { return mIntegration; }
|
||||
QMirClientWindow *lastInputWindow() const {return mLastInputWindow; }
|
||||
|
||||
protected:
|
||||
void dispatchKeyEvent(QMirClientWindow *window, const MirInputEvent *event);
|
||||
void dispatchPointerEvent(QMirClientWindow *window, const MirInputEvent *event);
|
||||
void dispatchTouchEvent(QMirClientWindow *window, const MirInputEvent *event);
|
||||
void dispatchInputEvent(QMirClientWindow *window, const MirInputEvent *event);
|
||||
|
||||
void dispatchOrientationEvent(QWindow* window, const MirOrientationEvent *event);
|
||||
void handleSurfaceEvent(const QPointer<QMirClientWindow> &window, const MirSurfaceEvent *event);
|
||||
void handleSurfaceOutputEvent(const QPointer<QMirClientWindow> &window, const MirSurfaceOutputEvent *event);
|
||||
|
||||
private:
|
||||
QMirClientClientIntegration* mIntegration;
|
||||
QTouchDevice* mTouchDevice;
|
||||
const QByteArray mEventFilterType;
|
||||
const QEvent::Type mEventType;
|
||||
|
||||
QMirClientWindow *mLastInputWindow;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTINPUT_H
|
@ -1,411 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014-2016 Canonical, Ltd.
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
// Local
|
||||
#include "qmirclientintegration.h"
|
||||
#include "qmirclientbackingstore.h"
|
||||
#include "qmirclientclipboard.h"
|
||||
#include "qmirclientdebugextension.h"
|
||||
#include "qmirclientdesktopwindow.h"
|
||||
#include "qmirclientglcontext.h"
|
||||
#include "qmirclientinput.h"
|
||||
#include "qmirclientlogging.h"
|
||||
#include "qmirclientnativeinterface.h"
|
||||
#include "qmirclientscreen.h"
|
||||
#include "qmirclienttheme.h"
|
||||
#include "qmirclientwindow.h"
|
||||
|
||||
// Qt
|
||||
#include <QFileInfo>
|
||||
#include <QGuiApplication>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#include <qpa/qplatforminputcontextfactory_p.h>
|
||||
#include <qpa/qplatforminputcontext.h>
|
||||
#include <QtEglSupport/private/qeglconvenience_p.h>
|
||||
#include <QtEglSupport/private/qeglpbuffer_p.h>
|
||||
#include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
|
||||
#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
#include <qpa/qplatformaccessibility.h>
|
||||
#ifndef QT_NO_ACCESSIBILITY_ATSPI_BRIDGE
|
||||
#include <QtLinuxAccessibilitySupport/private/bridge_p.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <QOpenGLContext>
|
||||
#include <QOffscreenSurface>
|
||||
|
||||
// platform-api
|
||||
#include <ubuntu/application/lifecycle_delegate.h>
|
||||
#include <ubuntu/application/id.h>
|
||||
#include <ubuntu/application/options.h>
|
||||
|
||||
static void resumedCallback(const UApplicationOptions */*options*/, void* context)
|
||||
{
|
||||
auto integration = static_cast<QMirClientClientIntegration*>(context);
|
||||
integration->appStateController()->setResumed();
|
||||
}
|
||||
|
||||
static void aboutToStopCallback(UApplicationArchive */*archive*/, void* context)
|
||||
{
|
||||
auto integration = static_cast<QMirClientClientIntegration*>(context);
|
||||
auto inputContext = integration->inputContext();
|
||||
if (inputContext) {
|
||||
inputContext->hideInputPanel();
|
||||
} else {
|
||||
qCWarning(mirclient) << "aboutToStopCallback(): no input context";
|
||||
}
|
||||
integration->appStateController()->setSuspended();
|
||||
}
|
||||
|
||||
QMirClientClientIntegration::QMirClientClientIntegration(int argc, char **argv)
|
||||
: QPlatformIntegration()
|
||||
, mNativeInterface(new QMirClientNativeInterface(this))
|
||||
, mFontDb(new QGenericUnixFontDatabase)
|
||||
, mServices(new QMirClientPlatformServices)
|
||||
, mAppStateController(new QMirClientAppStateController)
|
||||
, mScaleFactor(1.0)
|
||||
{
|
||||
{
|
||||
QStringList args = QCoreApplication::arguments();
|
||||
setupOptions(args);
|
||||
QByteArray sessionName = generateSessionName(args);
|
||||
setupDescription(sessionName);
|
||||
}
|
||||
|
||||
// Create new application instance
|
||||
mInstance = u_application_instance_new_from_description_with_options(mDesc, mOptions);
|
||||
|
||||
if (Q_UNLIKELY(!mInstance))
|
||||
qFatal("QMirClientClientIntegration: connection to Mir server failed. Check that a Mir server is\n"
|
||||
"running, and the correct socket is being used and is accessible. The shell may have\n"
|
||||
"rejected the incoming connection, so check its log file");
|
||||
|
||||
mMirConnection = u_application_instance_get_mir_connection(mInstance);
|
||||
|
||||
// Choose the default surface format suited to the Mir platform
|
||||
QSurfaceFormat defaultFormat;
|
||||
defaultFormat.setRedBufferSize(8);
|
||||
defaultFormat.setGreenBufferSize(8);
|
||||
defaultFormat.setBlueBufferSize(8);
|
||||
QSurfaceFormat::setDefaultFormat(defaultFormat);
|
||||
|
||||
// Initialize EGL.
|
||||
mEglNativeDisplay = mir_connection_get_egl_native_display(mMirConnection);
|
||||
ASSERT((mEglDisplay = eglGetDisplay(mEglNativeDisplay)) != EGL_NO_DISPLAY);
|
||||
ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE);
|
||||
|
||||
// Has debug mode been requsted, either with "-testability" switch or QT_LOAD_TESTABILITY env var
|
||||
bool testability = qEnvironmentVariableIsSet("QT_LOAD_TESTABILITY");
|
||||
for (int i=1; !testability && i<argc; i++) {
|
||||
if (strcmp(argv[i], "-testability") == 0) {
|
||||
testability = true;
|
||||
}
|
||||
}
|
||||
if (testability) {
|
||||
mDebugExtension.reset(new QMirClientDebugExtension);
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientClientIntegration::initialize()
|
||||
{
|
||||
// Init the ScreenObserver
|
||||
mScreenObserver.reset(new QMirClientScreenObserver(mMirConnection));
|
||||
connect(mScreenObserver.data(), &QMirClientScreenObserver::screenAdded,
|
||||
[this](QMirClientScreen *screen) { this->screenAdded(screen); });
|
||||
connect(mScreenObserver.data(), &QMirClientScreenObserver::screenRemoved,
|
||||
this, &QMirClientClientIntegration::destroyScreen);
|
||||
|
||||
Q_FOREACH (auto screen, mScreenObserver->screens()) {
|
||||
screenAdded(screen);
|
||||
}
|
||||
|
||||
// Initialize input.
|
||||
mInput = new QMirClientInput(this);
|
||||
mInputContext = QPlatformInputContextFactory::create();
|
||||
|
||||
// compute the scale factor
|
||||
const int defaultGridUnit = 8;
|
||||
int gridUnit = defaultGridUnit;
|
||||
QByteArray gridUnitString = qgetenv("GRID_UNIT_PX");
|
||||
if (!gridUnitString.isEmpty()) {
|
||||
bool ok;
|
||||
gridUnit = gridUnitString.toInt(&ok);
|
||||
if (!ok) {
|
||||
gridUnit = defaultGridUnit;
|
||||
}
|
||||
}
|
||||
mScaleFactor = static_cast<qreal>(gridUnit) / defaultGridUnit;
|
||||
}
|
||||
|
||||
QMirClientClientIntegration::~QMirClientClientIntegration()
|
||||
{
|
||||
eglTerminate(mEglDisplay);
|
||||
delete mInput;
|
||||
delete mInputContext;
|
||||
delete mServices;
|
||||
}
|
||||
|
||||
QPlatformServices *QMirClientClientIntegration::services() const
|
||||
{
|
||||
return mServices;
|
||||
}
|
||||
|
||||
void QMirClientClientIntegration::setupOptions(QStringList &args)
|
||||
{
|
||||
int argc = args.size() + 1;
|
||||
char **argv = new char*[argc];
|
||||
for (int i = 0; i < argc - 1; i++)
|
||||
argv[i] = qstrdup(args.at(i).toLocal8Bit());
|
||||
argv[argc - 1] = nullptr;
|
||||
|
||||
mOptions = u_application_options_new_from_cmd_line(argc - 1, argv);
|
||||
|
||||
for (int i = 0; i < argc; i++)
|
||||
delete [] argv[i];
|
||||
delete [] argv;
|
||||
}
|
||||
|
||||
void QMirClientClientIntegration::setupDescription(QByteArray &sessionName)
|
||||
{
|
||||
mDesc = u_application_description_new();
|
||||
|
||||
UApplicationId* id = u_application_id_new_from_stringn(sessionName.data(), sessionName.count());
|
||||
u_application_description_set_application_id(mDesc, id);
|
||||
|
||||
UApplicationLifecycleDelegate* delegate = u_application_lifecycle_delegate_new();
|
||||
u_application_lifecycle_delegate_set_application_resumed_cb(delegate, &resumedCallback);
|
||||
u_application_lifecycle_delegate_set_application_about_to_stop_cb(delegate, &aboutToStopCallback);
|
||||
u_application_lifecycle_delegate_set_context(delegate, this);
|
||||
u_application_description_set_application_lifecycle_delegate(mDesc, delegate);
|
||||
}
|
||||
|
||||
QByteArray QMirClientClientIntegration::generateSessionName(QStringList &args)
|
||||
{
|
||||
// Try to come up with some meaningful session name to uniquely identify this session,
|
||||
// helping with shell debugging
|
||||
|
||||
if (args.count() == 0) {
|
||||
return QByteArray("QtUbuntu");
|
||||
} if (args[0].contains("qmlscene")) {
|
||||
return generateSessionNameFromQmlFile(args);
|
||||
} else {
|
||||
// use the executable name
|
||||
QFileInfo fileInfo(args[0]);
|
||||
return fileInfo.fileName().toLocal8Bit();
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray QMirClientClientIntegration::generateSessionNameFromQmlFile(QStringList &args)
|
||||
{
|
||||
Q_FOREACH (QString arg, args) {
|
||||
if (arg.endsWith(".qml")) {
|
||||
QFileInfo fileInfo(arg);
|
||||
return fileInfo.fileName().toLocal8Bit();
|
||||
}
|
||||
}
|
||||
|
||||
// give up
|
||||
return "qmlscene";
|
||||
}
|
||||
|
||||
QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* window) const
|
||||
{
|
||||
if (window->type() == Qt::Desktop) {
|
||||
// Desktop windows should not be backed up by a mir surface as they don't draw anything (nor should).
|
||||
return new QMirClientDesktopWindow(window);
|
||||
} else {
|
||||
return new QMirClientWindow(window, mInput, mNativeInterface, mAppStateController.data(),
|
||||
mEglDisplay, mMirConnection, mDebugExtension.data());
|
||||
}
|
||||
}
|
||||
|
||||
bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const
|
||||
{
|
||||
switch (cap) {
|
||||
case ThreadedOpenGL:
|
||||
if (qEnvironmentVariableIsEmpty("QTUBUNTU_NO_THREADED_OPENGL")) {
|
||||
return true;
|
||||
} else {
|
||||
qCDebug(mirclient, "disabled threaded OpenGL");
|
||||
return false;
|
||||
}
|
||||
|
||||
case ThreadedPixmaps:
|
||||
case OpenGL:
|
||||
case ApplicationState:
|
||||
case MultipleWindows:
|
||||
case NonFullScreenWindows:
|
||||
#if QT_VERSION > QT_VERSION_CHECK(5, 5, 0)
|
||||
case SwitchableWidgetComposition:
|
||||
#endif
|
||||
case RasterGLSurface: // needed for QQuickWidget
|
||||
return true;
|
||||
default:
|
||||
return QPlatformIntegration::hasCapability(cap);
|
||||
}
|
||||
}
|
||||
|
||||
QAbstractEventDispatcher *QMirClientClientIntegration::createEventDispatcher() const
|
||||
{
|
||||
return createUnixEventDispatcher();
|
||||
}
|
||||
|
||||
QPlatformBackingStore* QMirClientClientIntegration::createPlatformBackingStore(QWindow* window) const
|
||||
{
|
||||
return new QMirClientBackingStore(window);
|
||||
}
|
||||
|
||||
QPlatformOpenGLContext* QMirClientClientIntegration::createPlatformOpenGLContext(
|
||||
QOpenGLContext* context) const
|
||||
{
|
||||
QSurfaceFormat format(context->format());
|
||||
|
||||
auto platformContext = new QMirClientOpenGLContext(format, context->shareHandle(), mEglDisplay);
|
||||
if (!platformContext->isValid()) {
|
||||
// Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default
|
||||
// QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a
|
||||
// 1.4 context, but the XCB EGL backend tries to honor it, and fails. The 1.4 context appears to
|
||||
// have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default
|
||||
// requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455).
|
||||
static const bool isMesa = QString(eglQueryString(mEglDisplay, EGL_VENDOR)).contains(QStringLiteral("Mesa"));
|
||||
if (isMesa) {
|
||||
qCDebug(mirclientGraphics, "Attempting to choose OpenGL 1.4 context which may suit Mesa");
|
||||
format.setMajorVersion(1);
|
||||
format.setMinorVersion(4);
|
||||
delete platformContext;
|
||||
platformContext = new QMirClientOpenGLContext(format, context->shareHandle(), mEglDisplay);
|
||||
}
|
||||
}
|
||||
return platformContext;
|
||||
}
|
||||
|
||||
QStringList QMirClientClientIntegration::themeNames() const
|
||||
{
|
||||
return QStringList(QMirClientTheme::name);
|
||||
}
|
||||
|
||||
QPlatformTheme* QMirClientClientIntegration::createPlatformTheme(const QString& name) const
|
||||
{
|
||||
Q_UNUSED(name);
|
||||
return new QMirClientTheme;
|
||||
}
|
||||
|
||||
QVariant QMirClientClientIntegration::styleHint(StyleHint hint) const
|
||||
{
|
||||
switch (hint) {
|
||||
case QPlatformIntegration::StartDragDistance: {
|
||||
// default is 10 pixels (see QPlatformTheme::defaultThemeHint)
|
||||
return 10.0 * mScaleFactor;
|
||||
}
|
||||
case QPlatformIntegration::PasswordMaskDelay: {
|
||||
// return time in milliseconds - 1 second
|
||||
return QVariant(1000);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QPlatformIntegration::styleHint(hint);
|
||||
}
|
||||
|
||||
QPlatformClipboard* QMirClientClientIntegration::clipboard() const
|
||||
{
|
||||
static QPlatformClipboard *clipboard = nullptr;
|
||||
if (!clipboard) {
|
||||
clipboard = new QMirClientClipboard;
|
||||
}
|
||||
return clipboard;
|
||||
}
|
||||
|
||||
QPlatformNativeInterface* QMirClientClientIntegration::nativeInterface() const
|
||||
{
|
||||
return mNativeInterface;
|
||||
}
|
||||
|
||||
QPlatformOffscreenSurface *QMirClientClientIntegration::createPlatformOffscreenSurface(
|
||||
QOffscreenSurface *surface) const
|
||||
{
|
||||
return new QEGLPbuffer(mEglDisplay, surface->requestedFormat(), surface);
|
||||
}
|
||||
|
||||
void QMirClientClientIntegration::destroyScreen(QMirClientScreen *screen)
|
||||
{
|
||||
// FIXME: on deleting a screen while a Window is on it, Qt will automatically
|
||||
// move the window to the primaryScreen(). This will trigger a screenChanged
|
||||
// signal, causing things like QQuickScreenAttached to re-fetch screen properties
|
||||
// like DPI and physical size. However this is crashing, as Qt is calling virtual
|
||||
// functions on QPlatformScreen, for reasons unclear. As workaround, move window
|
||||
// to primaryScreen() before deleting the screen. Might be QTBUG-38650
|
||||
|
||||
QScreen *primaryScreen = QGuiApplication::primaryScreen();
|
||||
if (screen != primaryScreen->handle()) {
|
||||
uint32_t movedWindowCount = 0;
|
||||
Q_FOREACH (QWindow *w, QGuiApplication::topLevelWindows()) {
|
||||
if (w->screen()->handle() == screen) {
|
||||
QWindowSystemInterface::handleWindowScreenChanged(w, primaryScreen);
|
||||
++movedWindowCount;
|
||||
}
|
||||
}
|
||||
if (movedWindowCount > 0) {
|
||||
QWindowSystemInterface::flushWindowSystemEvents();
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(mirclient) << "Removing Screen with id" << screen->mirOutputId() << "and geometry" << screen->geometry();
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
|
||||
delete screen;
|
||||
#else
|
||||
QPlatformIntegration::destroyScreen(screen);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
QPlatformAccessibility *QMirClientClientIntegration::accessibility() const
|
||||
{
|
||||
#if !defined(QT_NO_ACCESSIBILITY_ATSPI_BRIDGE)
|
||||
if (!mAccessibility) {
|
||||
Q_ASSERT_X(QCoreApplication::eventDispatcher(), "QMirClientIntegration",
|
||||
"Initializing accessibility without event-dispatcher!");
|
||||
mAccessibility.reset(new QSpiAccessibleBridge());
|
||||
}
|
||||
#endif
|
||||
return mAccessibility.data();
|
||||
}
|
||||
#endif
|
@ -1,131 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTINTEGRATION_H
|
||||
#define QMIRCLIENTINTEGRATION_H
|
||||
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "qmirclientappstatecontroller.h"
|
||||
#include "qmirclientplatformservices.h"
|
||||
#include "qmirclientscreenobserver.h"
|
||||
|
||||
// platform-api
|
||||
#include <ubuntu/application/description.h>
|
||||
#include <ubuntu/application/instance.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
class QMirClientDebugExtension;
|
||||
class QMirClientInput;
|
||||
class QMirClientNativeInterface;
|
||||
class QMirClientScreen;
|
||||
class MirConnection;
|
||||
|
||||
class QMirClientClientIntegration : public QObject, public QPlatformIntegration
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QMirClientClientIntegration(int argc, char **argv);
|
||||
virtual ~QMirClientClientIntegration();
|
||||
|
||||
// QPlatformIntegration methods.
|
||||
bool hasCapability(QPlatformIntegration::Capability cap) const override;
|
||||
QAbstractEventDispatcher *createEventDispatcher() const override;
|
||||
QPlatformNativeInterface* nativeInterface() const override;
|
||||
QPlatformBackingStore* createPlatformBackingStore(QWindow* window) const override;
|
||||
QPlatformOpenGLContext* createPlatformOpenGLContext(QOpenGLContext* context) const override;
|
||||
QPlatformFontDatabase* fontDatabase() const override { return mFontDb; }
|
||||
QStringList themeNames() const override;
|
||||
QPlatformTheme* createPlatformTheme(const QString& name) const override;
|
||||
QVariant styleHint(StyleHint hint) const override;
|
||||
QPlatformServices *services() const override;
|
||||
QPlatformWindow* createPlatformWindow(QWindow* window) const override;
|
||||
QPlatformInputContext* inputContext() const override { return mInputContext; }
|
||||
QPlatformClipboard* clipboard() const override;
|
||||
void initialize() override;
|
||||
QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
|
||||
QPlatformAccessibility *accessibility() const override;
|
||||
|
||||
// New methods.
|
||||
MirConnection *mirConnection() const { return mMirConnection; }
|
||||
EGLDisplay eglDisplay() const { return mEglDisplay; }
|
||||
EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; }
|
||||
QMirClientAppStateController *appStateController() const { return mAppStateController.data(); }
|
||||
QMirClientScreenObserver *screenObserver() const { return mScreenObserver.data(); }
|
||||
QMirClientDebugExtension *debugExtension() const { return mDebugExtension.data(); }
|
||||
|
||||
private Q_SLOTS:
|
||||
void destroyScreen(QMirClientScreen *screen);
|
||||
|
||||
private:
|
||||
void setupOptions(QStringList &args);
|
||||
void setupDescription(QByteArray &sessionName);
|
||||
static QByteArray generateSessionName(QStringList &args);
|
||||
static QByteArray generateSessionNameFromQmlFile(QStringList &args);
|
||||
|
||||
QMirClientNativeInterface* mNativeInterface;
|
||||
QPlatformFontDatabase* mFontDb;
|
||||
|
||||
QMirClientPlatformServices* mServices;
|
||||
|
||||
QMirClientInput* mInput;
|
||||
QPlatformInputContext* mInputContext;
|
||||
mutable QScopedPointer<QPlatformAccessibility> mAccessibility;
|
||||
QScopedPointer<QMirClientDebugExtension> mDebugExtension;
|
||||
QScopedPointer<QMirClientScreenObserver> mScreenObserver;
|
||||
QScopedPointer<QMirClientAppStateController> mAppStateController;
|
||||
qreal mScaleFactor;
|
||||
|
||||
MirConnection *mMirConnection;
|
||||
|
||||
// Platform API stuff
|
||||
UApplicationOptions* mOptions;
|
||||
UApplicationDescription* mDesc;
|
||||
UApplicationInstance* mInstance;
|
||||
|
||||
// EGL related
|
||||
EGLDisplay mEglDisplay{EGL_NO_DISPLAY};
|
||||
EGLNativeDisplayType mEglNativeDisplay;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTINTEGRATION_H
|
@ -1,55 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTLOGGING_H
|
||||
#define QMIRCLIENTLOGGING_H
|
||||
|
||||
#include <QLoggingCategory>
|
||||
|
||||
#define ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(mirclient)
|
||||
Q_DECLARE_LOGGING_CATEGORY(mirclientBufferSwap)
|
||||
Q_DECLARE_LOGGING_CATEGORY(mirclientInput)
|
||||
Q_DECLARE_LOGGING_CATEGORY(mirclientGraphics)
|
||||
Q_DECLARE_LOGGING_CATEGORY(mirclientCursor)
|
||||
Q_DECLARE_LOGGING_CATEGORY(mirclientDebug)
|
||||
|
||||
#endif // QMIRCLIENTLOGGING_H
|
@ -1,217 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
// Local
|
||||
#include "qmirclientnativeinterface.h"
|
||||
#include "qmirclientscreen.h"
|
||||
#include "qmirclientglcontext.h"
|
||||
#include "qmirclientwindow.h"
|
||||
|
||||
// Qt
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
#include <QtGui/qopenglcontext.h>
|
||||
#include <QtGui/qscreen.h>
|
||||
#include <QtCore/QMap>
|
||||
|
||||
class UbuntuResourceMap : public QMap<QByteArray, QMirClientNativeInterface::ResourceType>
|
||||
{
|
||||
public:
|
||||
UbuntuResourceMap()
|
||||
: QMap<QByteArray, QMirClientNativeInterface::ResourceType>() {
|
||||
insert("egldisplay", QMirClientNativeInterface::EglDisplay);
|
||||
insert("eglcontext", QMirClientNativeInterface::EglContext);
|
||||
insert("nativeorientation", QMirClientNativeInterface::NativeOrientation);
|
||||
insert("display", QMirClientNativeInterface::Display);
|
||||
insert("mirconnection", QMirClientNativeInterface::MirConnection);
|
||||
insert("mirsurface", QMirClientNativeInterface::MirSurface);
|
||||
insert("scale", QMirClientNativeInterface::Scale);
|
||||
insert("formfactor", QMirClientNativeInterface::FormFactor);
|
||||
}
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(UbuntuResourceMap, ubuntuResourceMap)
|
||||
|
||||
QMirClientNativeInterface::QMirClientNativeInterface(const QMirClientClientIntegration *integration)
|
||||
: mIntegration(integration)
|
||||
, mGenericEventFilterType(QByteArrayLiteral("Event"))
|
||||
, mNativeOrientation(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
QMirClientNativeInterface::~QMirClientNativeInterface()
|
||||
{
|
||||
delete mNativeOrientation;
|
||||
mNativeOrientation = nullptr;
|
||||
}
|
||||
|
||||
void* QMirClientNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString)
|
||||
{
|
||||
const QByteArray lowerCaseResource = resourceString.toLower();
|
||||
|
||||
if (!ubuntuResourceMap()->contains(lowerCaseResource)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ResourceType resourceType = ubuntuResourceMap()->value(lowerCaseResource);
|
||||
|
||||
if (resourceType == QMirClientNativeInterface::MirConnection) {
|
||||
return mIntegration->mirConnection();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void* QMirClientNativeInterface::nativeResourceForContext(
|
||||
const QByteArray& resourceString, QOpenGLContext* context)
|
||||
{
|
||||
if (!context)
|
||||
return nullptr;
|
||||
|
||||
const QByteArray kLowerCaseResource = resourceString.toLower();
|
||||
|
||||
if (!ubuntuResourceMap()->contains(kLowerCaseResource))
|
||||
return nullptr;
|
||||
|
||||
const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
|
||||
|
||||
if (kResourceType == QMirClientNativeInterface::EglContext)
|
||||
return static_cast<QMirClientOpenGLContext*>(context->handle())->eglContext();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* QMirClientNativeInterface::nativeResourceForWindow(const QByteArray& resourceString, QWindow* window)
|
||||
{
|
||||
const QByteArray kLowerCaseResource = resourceString.toLower();
|
||||
if (!ubuntuResourceMap()->contains(kLowerCaseResource))
|
||||
return NULL;
|
||||
const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
|
||||
|
||||
switch (kResourceType) {
|
||||
case EglDisplay:
|
||||
return mIntegration->eglDisplay();
|
||||
case NativeOrientation:
|
||||
// Return the device's native screen orientation.
|
||||
if (window) {
|
||||
QMirClientScreen *ubuntuScreen = static_cast<QMirClientScreen*>(window->screen()->handle());
|
||||
mNativeOrientation = new Qt::ScreenOrientation(ubuntuScreen->nativeOrientation());
|
||||
} else {
|
||||
QPlatformScreen *platformScreen = QGuiApplication::primaryScreen()->handle();
|
||||
mNativeOrientation = new Qt::ScreenOrientation(platformScreen->nativeOrientation());
|
||||
}
|
||||
return mNativeOrientation;
|
||||
case MirSurface:
|
||||
if (window) {
|
||||
auto ubuntuWindow = static_cast<QMirClientWindow*>(window->handle());
|
||||
if (ubuntuWindow) {
|
||||
return ubuntuWindow->mirSurface();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void* QMirClientNativeInterface::nativeResourceForScreen(const QByteArray& resourceString, QScreen* screen)
|
||||
{
|
||||
const QByteArray kLowerCaseResource = resourceString.toLower();
|
||||
if (!ubuntuResourceMap()->contains(kLowerCaseResource))
|
||||
return NULL;
|
||||
const ResourceType kResourceType = ubuntuResourceMap()->value(kLowerCaseResource);
|
||||
if (!screen)
|
||||
screen = QGuiApplication::primaryScreen();
|
||||
auto ubuntuScreen = static_cast<QMirClientScreen*>(screen->handle());
|
||||
if (kResourceType == QMirClientNativeInterface::Display) {
|
||||
return mIntegration->eglNativeDisplay();
|
||||
// Changes to the following properties are emitted via the QMirClientNativeInterface::screenPropertyChanged
|
||||
// signal fired by QMirClientScreen. Connect to this signal for these properties updates.
|
||||
// WARNING: code highly thread unsafe!
|
||||
} else if (kResourceType == QMirClientNativeInterface::Scale) {
|
||||
// In application code, read with:
|
||||
// float scale = *reinterpret_cast<float*>(nativeResourceForScreen("scale", screen()));
|
||||
return &ubuntuScreen->mScale;
|
||||
} else if (kResourceType == QMirClientNativeInterface::FormFactor) {
|
||||
return &ubuntuScreen->mFormFactor;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Changes to these properties are emitted via the QMirClientNativeInterface::windowPropertyChanged
|
||||
// signal fired by QMirClientWindow. Connect to this signal for these properties updates.
|
||||
QVariantMap QMirClientNativeInterface::windowProperties(QPlatformWindow *window) const
|
||||
{
|
||||
QVariantMap propertyMap;
|
||||
auto w = static_cast<QMirClientWindow*>(window);
|
||||
if (w) {
|
||||
propertyMap.insert("scale", w->scale());
|
||||
propertyMap.insert("formFactor", w->formFactor());
|
||||
}
|
||||
return propertyMap;
|
||||
}
|
||||
|
||||
QVariant QMirClientNativeInterface::windowProperty(QPlatformWindow *window, const QString &name) const
|
||||
{
|
||||
auto w = static_cast<QMirClientWindow*>(window);
|
||||
if (!w) {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if (name == QStringLiteral("scale")) {
|
||||
return w->scale();
|
||||
} else if (name == QStringLiteral("formFactor")) {
|
||||
return w->formFactor();
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant QMirClientNativeInterface::windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const
|
||||
{
|
||||
QVariant returnVal = windowProperty(window, name);
|
||||
if (!returnVal.isValid()) {
|
||||
return defaultValue;
|
||||
} else {
|
||||
return returnVal;
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTNATIVEINTERFACE_H
|
||||
#define QMIRCLIENTNATIVEINTERFACE_H
|
||||
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
|
||||
#include "qmirclientintegration.h"
|
||||
|
||||
class QPlatformScreen;
|
||||
|
||||
class QMirClientNativeInterface : public QPlatformNativeInterface {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ResourceType { EglDisplay, EglContext, NativeOrientation, Display, MirConnection, MirSurface, Scale, FormFactor };
|
||||
|
||||
QMirClientNativeInterface(const QMirClientClientIntegration *integration);
|
||||
~QMirClientNativeInterface();
|
||||
|
||||
// QPlatformNativeInterface methods.
|
||||
void* nativeResourceForIntegration(const QByteArray &resource) override;
|
||||
void* nativeResourceForContext(const QByteArray& resourceString,
|
||||
QOpenGLContext* context) override;
|
||||
void* nativeResourceForWindow(const QByteArray& resourceString,
|
||||
QWindow* window) override;
|
||||
void* nativeResourceForScreen(const QByteArray& resourceString,
|
||||
QScreen* screen) override;
|
||||
|
||||
QVariantMap windowProperties(QPlatformWindow *window) const override;
|
||||
QVariant windowProperty(QPlatformWindow *window, const QString &name) const override;
|
||||
QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const override;
|
||||
|
||||
// New methods.
|
||||
const QByteArray& genericEventFilterType() const { return mGenericEventFilterType; }
|
||||
|
||||
Q_SIGNALS: // New signals
|
||||
void screenPropertyChanged(QPlatformScreen *screen, const QString &propertyName);
|
||||
|
||||
private:
|
||||
const QMirClientClientIntegration *mIntegration;
|
||||
const QByteArray mGenericEventFilterType;
|
||||
Qt::ScreenOrientation* mNativeOrientation;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTNATIVEINTERFACE_H
|
@ -1,61 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
|
||||
#define QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
|
||||
|
||||
#include <QEvent>
|
||||
#include "qmirclientlogging.h"
|
||||
|
||||
class OrientationChangeEvent : public QEvent {
|
||||
public:
|
||||
enum Orientation { TopUp, LeftUp, TopDown, RightUp };
|
||||
|
||||
OrientationChangeEvent(QEvent::Type type, Orientation orientation)
|
||||
: QEvent(type)
|
||||
, mOrientation(orientation)
|
||||
{
|
||||
}
|
||||
|
||||
static const QEvent::Type mType;
|
||||
Orientation mOrientation;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTORIENTATIONCHANGEEVENT_P_H
|
@ -1,75 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 "qmirclientplatformservices.h"
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
#include <ubuntu/application/url_dispatcher/service.h>
|
||||
#include <ubuntu/application/url_dispatcher/session.h>
|
||||
|
||||
bool QMirClientPlatformServices::openUrl(const QUrl &url)
|
||||
{
|
||||
return callDispatcher(url);
|
||||
}
|
||||
|
||||
bool QMirClientPlatformServices::openDocument(const QUrl &url)
|
||||
{
|
||||
return callDispatcher(url);
|
||||
}
|
||||
|
||||
bool QMirClientPlatformServices::callDispatcher(const QUrl &url)
|
||||
{
|
||||
UAUrlDispatcherSession* session = ua_url_dispatcher_session();
|
||||
if (!session)
|
||||
return false;
|
||||
|
||||
ua_url_dispatcher_session_open(session, url.toEncoded().constData(), NULL, NULL);
|
||||
|
||||
free(session);
|
||||
|
||||
// We are returning true here because the other option
|
||||
// is spawning a nested event loop and wait for the
|
||||
// callback. But there is no guarantee on how fast
|
||||
// the callback is going to be so we prefer to avoid the
|
||||
// nested event loop. Long term plan is improve Qt API
|
||||
// to support an async openUrl
|
||||
return true;
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTPLATFORMSERVICES_H
|
||||
#define QMIRCLIENTPLATFORMSERVICES_H
|
||||
|
||||
#include <qpa/qplatformservices.h>
|
||||
#include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
|
||||
#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
|
||||
|
||||
class QMirClientPlatformServices : public QPlatformServices {
|
||||
public:
|
||||
bool openUrl(const QUrl &url) override;
|
||||
bool openDocument(const QUrl &url) override;
|
||||
|
||||
private:
|
||||
bool callDispatcher(const QUrl &url);
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTPLATFORMSERVICES_H
|
@ -1,56 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 "qmirclientplugin.h"
|
||||
#include "qmirclientintegration.h"
|
||||
#include "qmirclientlogging.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(mirclient, "qt.qpa.mirclient", QtWarningMsg)
|
||||
|
||||
QPlatformIntegration *QMirClientIntegrationPlugin::create(const QString &system,
|
||||
const QStringList &/*paramList*/,
|
||||
int &argc, char **argv)
|
||||
{
|
||||
if (system.toLower() == QLatin1String("mirclient")) {
|
||||
return new QMirClientClientIntegration(argc, argv);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTPLUGIN_H
|
||||
#define QMIRCLIENTPLUGIN_H
|
||||
|
||||
#include <qpa/qplatformintegrationplugin.h>
|
||||
|
||||
class QMirClientIntegrationPlugin : public QPlatformIntegrationPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "mirclient.json")
|
||||
|
||||
public:
|
||||
QPlatformIntegration *create(const QString &system, const QStringList ¶mList,
|
||||
int &argc, char **argv) override;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTPLUGIN_H
|
@ -1,262 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014-2016 Canonical, Ltd.
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
// local
|
||||
#include "qmirclientscreen.h"
|
||||
#include "qmirclientlogging.h"
|
||||
#include "qmirclientorientationchangeevent_p.h"
|
||||
#include "qmirclientnativeinterface.h"
|
||||
|
||||
#include <mir_toolkit/mir_client_library.h>
|
||||
|
||||
// Qt
|
||||
#include <QGuiApplication>
|
||||
#include <QtCore/qmath.h>
|
||||
#include <QScreen>
|
||||
#include <QThread>
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <QtEglSupport/private/qeglconvenience_p.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
static const int overrideDevicePixelRatio = qgetenv("QT_DEVICE_PIXEL_RATIO").toInt();
|
||||
|
||||
static const char *orientationToStr(Qt::ScreenOrientation orientation) {
|
||||
switch (orientation) {
|
||||
case Qt::PrimaryOrientation:
|
||||
return "primary";
|
||||
case Qt::PortraitOrientation:
|
||||
return "portrait";
|
||||
case Qt::LandscapeOrientation:
|
||||
return "landscape";
|
||||
case Qt::InvertedPortraitOrientation:
|
||||
return "inverted portrait";
|
||||
case Qt::InvertedLandscapeOrientation:
|
||||
return "inverted landscape";
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
const QEvent::Type OrientationChangeEvent::mType =
|
||||
static_cast<QEvent::Type>(QEvent::registerEventType());
|
||||
|
||||
|
||||
QMirClientScreen::QMirClientScreen(const MirOutput *output, MirConnection *connection)
|
||||
: mDevicePixelRatio(1.0)
|
||||
, mFormat(QImage::Format_RGB32)
|
||||
, mDepth(32)
|
||||
, mDpi{0}
|
||||
, mFormFactor{mir_form_factor_unknown}
|
||||
, mScale{1.0}
|
||||
, mOutputId(0)
|
||||
, mCursor(connection)
|
||||
{
|
||||
setMirOutput(output);
|
||||
}
|
||||
|
||||
QMirClientScreen::~QMirClientScreen()
|
||||
{
|
||||
}
|
||||
|
||||
void QMirClientScreen::customEvent(QEvent* event) {
|
||||
Q_ASSERT(QThread::currentThread() == thread());
|
||||
|
||||
OrientationChangeEvent* oReadingEvent = static_cast<OrientationChangeEvent*>(event);
|
||||
switch (oReadingEvent->mOrientation) {
|
||||
case OrientationChangeEvent::LeftUp: {
|
||||
mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
|
||||
Qt::InvertedPortraitOrientation : Qt::LandscapeOrientation;
|
||||
break;
|
||||
}
|
||||
case OrientationChangeEvent::TopUp: {
|
||||
mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
|
||||
Qt::LandscapeOrientation : Qt::PortraitOrientation;
|
||||
break;
|
||||
}
|
||||
case OrientationChangeEvent::RightUp: {
|
||||
mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
|
||||
Qt::PortraitOrientation : Qt::InvertedLandscapeOrientation;
|
||||
break;
|
||||
}
|
||||
case OrientationChangeEvent::TopDown: {
|
||||
mCurrentOrientation = (screen()->primaryOrientation() == Qt::LandscapeOrientation) ?
|
||||
Qt::InvertedLandscapeOrientation : Qt::InvertedPortraitOrientation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Raise the event signal so that client apps know the orientation changed
|
||||
qCDebug(mirclient, "QMirClientScreen::customEvent - handling orientation change to %s", orientationToStr(mCurrentOrientation));
|
||||
QWindowSystemInterface::handleScreenOrientationChange(screen(), mCurrentOrientation);
|
||||
}
|
||||
|
||||
void QMirClientScreen::handleWindowSurfaceResize(int windowWidth, int windowHeight)
|
||||
{
|
||||
if ((windowWidth > windowHeight && mGeometry.width() < mGeometry.height())
|
||||
|| (windowWidth < windowHeight && mGeometry.width() > mGeometry.height())) {
|
||||
|
||||
// The window aspect ratio differ's from the screen one. This means that
|
||||
// unity8 has rotated the window in its scene.
|
||||
// As there's no way to express window rotation in Qt's API, we have
|
||||
// Flip QScreen's dimensions so that orientation properties match
|
||||
// (primaryOrientation particularly).
|
||||
// FIXME: This assumes a phone scenario. Won't work, or make sense,
|
||||
// on the desktop
|
||||
|
||||
QRect currGeometry = mGeometry;
|
||||
mGeometry.setWidth(currGeometry.height());
|
||||
mGeometry.setHeight(currGeometry.width());
|
||||
|
||||
qCDebug(mirclient, "QMirClientScreen::handleWindowSurfaceResize - new screen geometry (w=%d, h=%d)",
|
||||
mGeometry.width(), mGeometry.height());
|
||||
QWindowSystemInterface::handleScreenGeometryChange(screen(),
|
||||
mGeometry /* newGeometry */,
|
||||
mGeometry /* newAvailableGeometry */);
|
||||
|
||||
if (mGeometry.width() < mGeometry.height()) {
|
||||
mCurrentOrientation = Qt::PortraitOrientation;
|
||||
} else {
|
||||
mCurrentOrientation = Qt::LandscapeOrientation;
|
||||
}
|
||||
qCDebug(mirclient, "QMirClientScreen::handleWindowSurfaceResize - new orientation %s",orientationToStr(mCurrentOrientation));
|
||||
QWindowSystemInterface::handleScreenOrientationChange(screen(), mCurrentOrientation);
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientScreen::setMirOutput(const MirOutput *output)
|
||||
{
|
||||
// Physical screen size (in mm)
|
||||
mPhysicalSize.setWidth(mir_output_get_physical_width_mm(output));
|
||||
mPhysicalSize.setHeight(mir_output_get_physical_height_mm(output));
|
||||
|
||||
// Pixel Format
|
||||
// mFormat = qImageFormatFromMirPixelFormat(mir_output_get_current_pixel_format(output)); // GERRY: TODO
|
||||
|
||||
// Pixel depth
|
||||
mDepth = 8 * MIR_BYTES_PER_PIXEL(mir_output_get_current_pixel_format(output));
|
||||
|
||||
// Mode = Resolution & refresh rate
|
||||
const MirOutputMode *mode = mir_output_get_current_mode(output);
|
||||
mNativeGeometry.setX(mir_output_get_position_x(output));
|
||||
mNativeGeometry.setY(mir_output_get_position_y(output));
|
||||
mNativeGeometry.setWidth(mir_output_mode_get_width(mode));
|
||||
mNativeGeometry.setHeight(mir_output_mode_get_height(mode));
|
||||
|
||||
mRefreshRate = mir_output_mode_get_refresh_rate(mode);
|
||||
|
||||
// UI scale & DPR
|
||||
mScale = mir_output_get_scale_factor(output);
|
||||
if (overrideDevicePixelRatio > 0) {
|
||||
mDevicePixelRatio = overrideDevicePixelRatio;
|
||||
} else {
|
||||
mDevicePixelRatio = 1.0; // FIXME - need to determine suitable DPR for the specified scale
|
||||
}
|
||||
|
||||
mFormFactor = mir_output_get_form_factor(output);
|
||||
|
||||
mOutputId = mir_output_get_id(output);
|
||||
|
||||
mGeometry.setX(mNativeGeometry.x());
|
||||
mGeometry.setY(mNativeGeometry.y());
|
||||
mGeometry.setWidth(mNativeGeometry.width());
|
||||
mGeometry.setHeight(mNativeGeometry.height());
|
||||
|
||||
// Set the default orientation based on the initial screen dimensions.
|
||||
mNativeOrientation = (mGeometry.width() >= mGeometry.height()) ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
|
||||
|
||||
// If it's a landscape device (i.e. some tablets), start in landscape, otherwise portrait
|
||||
mCurrentOrientation = (mNativeOrientation == Qt::LandscapeOrientation) ? Qt::LandscapeOrientation : Qt::PortraitOrientation;
|
||||
}
|
||||
|
||||
void QMirClientScreen::updateMirOutput(const MirOutput *output)
|
||||
{
|
||||
auto oldRefreshRate = mRefreshRate;
|
||||
auto oldScale = mScale;
|
||||
auto oldFormFactor = mFormFactor;
|
||||
auto oldGeometry = mGeometry;
|
||||
|
||||
setMirOutput(output);
|
||||
|
||||
// Emit change signals in particular order
|
||||
if (oldGeometry != mGeometry) {
|
||||
QWindowSystemInterface::handleScreenGeometryChange(screen(),
|
||||
mGeometry /* newGeometry */,
|
||||
mGeometry /* newAvailableGeometry */);
|
||||
}
|
||||
|
||||
if (!qFuzzyCompare(mRefreshRate, oldRefreshRate)) {
|
||||
QWindowSystemInterface::handleScreenRefreshRateChange(screen(), mRefreshRate);
|
||||
}
|
||||
|
||||
auto nativeInterface = static_cast<QMirClientNativeInterface *>(qGuiApp->platformNativeInterface());
|
||||
if (!qFuzzyCompare(mScale, oldScale)) {
|
||||
nativeInterface->screenPropertyChanged(this, QStringLiteral("scale"));
|
||||
}
|
||||
if (mFormFactor != oldFormFactor) {
|
||||
nativeInterface->screenPropertyChanged(this, QStringLiteral("formFactor"));
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientScreen::setAdditionalMirDisplayProperties(float scale, MirFormFactor formFactor, int dpi)
|
||||
{
|
||||
if (mDpi != dpi) {
|
||||
mDpi = dpi;
|
||||
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), dpi, dpi);
|
||||
}
|
||||
|
||||
auto nativeInterface = static_cast<QMirClientNativeInterface *>(qGuiApp->platformNativeInterface());
|
||||
if (!qFuzzyCompare(mScale, scale)) {
|
||||
mScale = scale;
|
||||
nativeInterface->screenPropertyChanged(this, QStringLiteral("scale"));
|
||||
}
|
||||
if (mFormFactor != formFactor) {
|
||||
mFormFactor = formFactor;
|
||||
nativeInterface->screenPropertyChanged(this, QStringLiteral("formFactor"));
|
||||
}
|
||||
}
|
||||
|
||||
QDpi QMirClientScreen::logicalDpi() const
|
||||
{
|
||||
if (mDpi > 0) {
|
||||
return QDpi(mDpi, mDpi);
|
||||
} else {
|
||||
return QPlatformScreen::logicalDpi();
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014-2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTSCREEN_H
|
||||
#define QMIRCLIENTSCREEN_H
|
||||
|
||||
#include <qpa/qplatformscreen.h>
|
||||
#include <QSurfaceFormat>
|
||||
|
||||
#include <mir_toolkit/common.h> // just for MirFormFactor enum
|
||||
|
||||
#include "qmirclientcursor.h"
|
||||
|
||||
struct MirConnection;
|
||||
struct MirOutput;
|
||||
|
||||
class QMirClientScreen : public QObject, public QPlatformScreen
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QMirClientScreen(const MirOutput *output, MirConnection *connection);
|
||||
virtual ~QMirClientScreen();
|
||||
|
||||
// QPlatformScreen methods.
|
||||
QImage::Format format() const override { return mFormat; }
|
||||
int depth() const override { return mDepth; }
|
||||
QRect geometry() const override { return mGeometry; }
|
||||
QRect availableGeometry() const override { return mGeometry; }
|
||||
QSizeF physicalSize() const override { return mPhysicalSize; }
|
||||
qreal devicePixelRatio() const override { return mDevicePixelRatio; }
|
||||
QDpi logicalDpi() const override;
|
||||
Qt::ScreenOrientation nativeOrientation() const override { return mNativeOrientation; }
|
||||
Qt::ScreenOrientation orientation() const override { return mNativeOrientation; }
|
||||
QPlatformCursor *cursor() const override { return const_cast<QMirClientCursor*>(&mCursor); }
|
||||
|
||||
// Additional Screen properties from Mir
|
||||
int mirOutputId() const { return mOutputId; }
|
||||
MirFormFactor formFactor() const { return mFormFactor; }
|
||||
float scale() const { return mScale; }
|
||||
|
||||
// Internally used methods
|
||||
void updateMirOutput(const MirOutput *output);
|
||||
void setAdditionalMirDisplayProperties(float scale, MirFormFactor formFactor, int dpi);
|
||||
void handleWindowSurfaceResize(int width, int height);
|
||||
|
||||
// QObject methods.
|
||||
void customEvent(QEvent* event) override;
|
||||
|
||||
private:
|
||||
void setMirOutput(const MirOutput *output);
|
||||
|
||||
QRect mGeometry, mNativeGeometry;
|
||||
QSizeF mPhysicalSize;
|
||||
qreal mDevicePixelRatio;
|
||||
Qt::ScreenOrientation mNativeOrientation;
|
||||
Qt::ScreenOrientation mCurrentOrientation;
|
||||
QImage::Format mFormat;
|
||||
int mDepth;
|
||||
int mDpi;
|
||||
qreal mRefreshRate;
|
||||
MirFormFactor mFormFactor;
|
||||
float mScale;
|
||||
int mOutputId;
|
||||
QMirClientCursor mCursor;
|
||||
|
||||
friend class QMirClientNativeInterface;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTSCREEN_H
|
@ -1,161 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 "qmirclientscreenobserver.h"
|
||||
#include "qmirclientscreen.h"
|
||||
#include "qmirclientwindow.h"
|
||||
#include "qmirclientlogging.h"
|
||||
|
||||
// Qt
|
||||
#include <QMetaObject>
|
||||
#include <QPointer>
|
||||
|
||||
// Mir
|
||||
#include <mirclient/mir_toolkit/mir_connection.h>
|
||||
#include <mirclient/mir_toolkit/mir_display_configuration.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace {
|
||||
static void displayConfigurationChangedCallback(MirConnection */*connection*/, void* context)
|
||||
{
|
||||
ASSERT(context != NULL);
|
||||
QMirClientScreenObserver *observer = static_cast<QMirClientScreenObserver *>(context);
|
||||
QMetaObject::invokeMethod(observer, "update");
|
||||
}
|
||||
|
||||
const char *mirFormFactorToStr(MirFormFactor formFactor)
|
||||
{
|
||||
switch (formFactor) {
|
||||
case mir_form_factor_unknown: return "unknown";
|
||||
case mir_form_factor_phone: return "phone";
|
||||
case mir_form_factor_tablet: return "tablet";
|
||||
case mir_form_factor_monitor: return "monitor";
|
||||
case mir_form_factor_tv: return "tv";
|
||||
case mir_form_factor_projector: return "projector";
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
QMirClientScreenObserver::QMirClientScreenObserver(MirConnection *mirConnection)
|
||||
: mMirConnection(mirConnection)
|
||||
{
|
||||
mir_connection_set_display_config_change_callback(mirConnection, ::displayConfigurationChangedCallback, this);
|
||||
update();
|
||||
}
|
||||
|
||||
void QMirClientScreenObserver::update()
|
||||
{
|
||||
// Wrap MirDisplayConfiguration to always delete when out of scope
|
||||
auto configDeleter = [](MirDisplayConfig *config) { mir_display_config_release(config); };
|
||||
using configUp = std::unique_ptr<MirDisplayConfig, decltype(configDeleter)>;
|
||||
configUp displayConfig(mir_connection_create_display_configuration(mMirConnection), configDeleter);
|
||||
|
||||
// Mir only tells us something changed, it is up to us to figure out what.
|
||||
QList<QMirClientScreen*> newScreenList;
|
||||
QList<QMirClientScreen*> oldScreenList = mScreenList;
|
||||
mScreenList.clear();
|
||||
|
||||
for (int i = 0; i < mir_display_config_get_num_outputs(displayConfig.get()); i++) {
|
||||
const MirOutput *output = mir_display_config_get_output(displayConfig.get(), i);
|
||||
if (mir_output_is_enabled(output)) {
|
||||
QMirClientScreen *screen = findScreenWithId(oldScreenList, mir_output_get_id(output));
|
||||
if (screen) { // we've already set up this display before
|
||||
screen->updateMirOutput(output);
|
||||
oldScreenList.removeAll(screen);
|
||||
} else {
|
||||
// new display, so create QMirClientScreen for it
|
||||
screen = new QMirClientScreen(output, mMirConnection);
|
||||
newScreenList.append(screen);
|
||||
qCDebug(mirclient) << "Added Screen with id" << mir_output_get_id(output)
|
||||
<< "and geometry" << screen->geometry();
|
||||
}
|
||||
mScreenList.append(screen);
|
||||
}
|
||||
}
|
||||
|
||||
// Announce old & unused Screens, should be deleted by the slot
|
||||
Q_FOREACH (const auto screen, oldScreenList) {
|
||||
Q_EMIT screenRemoved(screen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mir's MirDisplayOutput does not include formFactor or scale for some reason, but Qt
|
||||
* will want that information on creating the QScreen. Only way we get that info is when
|
||||
* Mir positions a Window on that Screen. See "handleScreenPropertiesChange" method
|
||||
*/
|
||||
|
||||
// Announce new Screens
|
||||
Q_FOREACH (const auto screen, newScreenList) {
|
||||
Q_EMIT screenAdded(screen);
|
||||
}
|
||||
|
||||
qCDebug(mirclient) << "=======================================";
|
||||
for (auto screen: mScreenList) {
|
||||
qCDebug(mirclient) << screen << "- id:" << screen->mirOutputId()
|
||||
<< "geometry:" << screen->geometry()
|
||||
<< "form factor:" << mirFormFactorToStr(screen->formFactor())
|
||||
<< "scale:" << screen->scale();
|
||||
}
|
||||
qCDebug(mirclient) << "=======================================";
|
||||
}
|
||||
|
||||
QMirClientScreen *QMirClientScreenObserver::findScreenWithId(int id)
|
||||
{
|
||||
return findScreenWithId(mScreenList, id);
|
||||
}
|
||||
|
||||
QMirClientScreen *QMirClientScreenObserver::findScreenWithId(const QList<QMirClientScreen *> &list, int id)
|
||||
{
|
||||
Q_FOREACH (const auto screen, list) {
|
||||
if (screen->mirOutputId() == id) {
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void QMirClientScreenObserver::handleScreenPropertiesChange(QMirClientScreen *screen, int dpi,
|
||||
MirFormFactor formFactor, float scale)
|
||||
{
|
||||
screen->setAdditionalMirDisplayProperties(scale, formFactor, dpi);
|
||||
}
|
||||
|
@ -1,78 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTSCREENOBSERVER_H
|
||||
#define QMIRCLIENTSCREENOBSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <mir_toolkit/mir_connection.h>
|
||||
|
||||
class QMirClientScreen;
|
||||
|
||||
class QMirClientScreenObserver : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QMirClientScreenObserver(MirConnection *connection);
|
||||
|
||||
QList<QMirClientScreen*> screens() const { return mScreenList; }
|
||||
QMirClientScreen *findScreenWithId(int id);
|
||||
|
||||
void handleScreenPropertiesChange(QMirClientScreen *screen, int dpi,
|
||||
MirFormFactor formFactor, float scale);
|
||||
|
||||
Q_SIGNALS:
|
||||
void screenAdded(QMirClientScreen *screen);
|
||||
void screenRemoved(QMirClientScreen *screen);
|
||||
|
||||
private Q_SLOTS:
|
||||
void update();
|
||||
|
||||
private:
|
||||
QMirClientScreen *findScreenWithId(const QList<QMirClientScreen *> &list, int id);
|
||||
void removeScreen(QMirClientScreen *screen);
|
||||
|
||||
MirConnection *mMirConnection;
|
||||
QList<QMirClientScreen*> mScreenList;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTSCREENOBSERVER_H
|
@ -1,67 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 "qmirclienttheme.h"
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
const char *QMirClientTheme::name = "ubuntu";
|
||||
|
||||
QMirClientTheme::QMirClientTheme()
|
||||
{
|
||||
}
|
||||
|
||||
QMirClientTheme::~QMirClientTheme()
|
||||
{
|
||||
}
|
||||
|
||||
QVariant QMirClientTheme::themeHint(ThemeHint hint) const
|
||||
{
|
||||
if (hint == QPlatformTheme::SystemIconThemeName) {
|
||||
QByteArray iconTheme = qgetenv("QTUBUNTU_ICON_THEME");
|
||||
if (iconTheme.isEmpty()) {
|
||||
return QVariant(QStringLiteral("ubuntu-mobile"));
|
||||
} else {
|
||||
return QVariant(QString(iconTheme));
|
||||
}
|
||||
} else {
|
||||
return QGenericUnixTheme::themeHint(hint);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTTHEME_H
|
||||
#define QMIRCLIENTTHEME_H
|
||||
|
||||
#include <QtThemeSupport/private/qgenericunixthemes_p.h>
|
||||
|
||||
class QMirClientTheme : public QGenericUnixTheme
|
||||
{
|
||||
public:
|
||||
static const char* name;
|
||||
QMirClientTheme();
|
||||
virtual ~QMirClientTheme();
|
||||
|
||||
// From QPlatformTheme
|
||||
QVariant themeHint(ThemeHint hint) const override;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTTHEME_H
|
@ -1,968 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014-2016 Canonical, Ltd.
|
||||
** 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$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
// Local
|
||||
#include "qmirclientwindow.h"
|
||||
#include "qmirclientdebugextension.h"
|
||||
#include "qmirclientnativeinterface.h"
|
||||
#include "qmirclientinput.h"
|
||||
#include "qmirclientintegration.h"
|
||||
#include "qmirclientscreen.h"
|
||||
#include "qmirclientlogging.h"
|
||||
|
||||
#include <mir_toolkit/mir_client_library.h>
|
||||
#include <mir_toolkit/version.h>
|
||||
|
||||
// Qt
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <QMutexLocker>
|
||||
#include <QSize>
|
||||
#include <QtMath>
|
||||
#include <QtEglSupport/private/qeglconvenience_p.h>
|
||||
|
||||
// Platform API
|
||||
#include <ubuntu/application/instance.h>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
Q_LOGGING_CATEGORY(mirclientBufferSwap, "qt.qpa.mirclient.bufferSwap", QtWarningMsg)
|
||||
|
||||
namespace
|
||||
{
|
||||
const Qt::WindowType LowChromeWindowHint = (Qt::WindowType)0x00800000;
|
||||
|
||||
// FIXME: this used to be defined by platform-api, but it's been removed in v3. Change ubuntu-keyboard to use
|
||||
// a different enum for window roles.
|
||||
enum UAUiWindowRole {
|
||||
U_MAIN_ROLE = 1,
|
||||
U_DASH_ROLE,
|
||||
U_INDICATOR_ROLE,
|
||||
U_NOTIFICATIONS_ROLE,
|
||||
U_GREETER_ROLE,
|
||||
U_LAUNCHER_ROLE,
|
||||
U_ON_SCREEN_KEYBOARD_ROLE,
|
||||
U_SHUTDOWN_DIALOG_ROLE,
|
||||
};
|
||||
|
||||
struct MirSpecDeleter
|
||||
{
|
||||
void operator()(MirSurfaceSpec *spec) { mir_surface_spec_release(spec); }
|
||||
};
|
||||
|
||||
using Spec = std::unique_ptr<MirSurfaceSpec, MirSpecDeleter>;
|
||||
|
||||
EGLNativeWindowType nativeWindowFor(MirSurface *surf)
|
||||
{
|
||||
auto stream = mir_surface_get_buffer_stream(surf);
|
||||
return reinterpret_cast<EGLNativeWindowType>(mir_buffer_stream_get_egl_native_window(stream));
|
||||
}
|
||||
|
||||
const char *qtWindowStateToStr(Qt::WindowState state)
|
||||
{
|
||||
switch (state) {
|
||||
case Qt::WindowNoState:
|
||||
return "NoState";
|
||||
case Qt::WindowFullScreen:
|
||||
return "FullScreen";
|
||||
case Qt::WindowMaximized:
|
||||
return "Maximized";
|
||||
case Qt::WindowMinimized:
|
||||
return "Minimized";
|
||||
case Qt::WindowActive:
|
||||
return "Active";
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
const char *mirSurfaceStateToStr(MirSurfaceState surfaceState)
|
||||
{
|
||||
switch (surfaceState) {
|
||||
case mir_surface_state_unknown: return "unknown";
|
||||
case mir_surface_state_restored: return "restored";
|
||||
case mir_surface_state_minimized: return "minimized";
|
||||
case mir_surface_state_maximized: return "vertmaximized";
|
||||
case mir_surface_state_vertmaximized: return "vertmaximized";
|
||||
case mir_surface_state_fullscreen: return "fullscreen";
|
||||
case mir_surface_state_horizmaximized: return "horizmaximized";
|
||||
case mir_surface_state_hidden: return "hidden";
|
||||
case mir_surface_states: Q_UNREACHABLE();
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
const char *mirPixelFormatToStr(MirPixelFormat pixelFormat)
|
||||
{
|
||||
switch (pixelFormat) {
|
||||
case mir_pixel_format_invalid: return "invalid";
|
||||
case mir_pixel_format_abgr_8888: return "ABGR8888";
|
||||
case mir_pixel_format_xbgr_8888: return "XBGR8888";
|
||||
case mir_pixel_format_argb_8888: return "ARGB8888";
|
||||
case mir_pixel_format_xrgb_8888: return "XRGB8888";
|
||||
case mir_pixel_format_bgr_888: return "BGR888";
|
||||
case mir_pixel_format_rgb_888: return "RGB888";
|
||||
case mir_pixel_format_rgb_565: return "RGB565";
|
||||
case mir_pixel_format_rgba_5551: return "RGBA5551";
|
||||
case mir_pixel_format_rgba_4444: return "RGBA4444";
|
||||
case mir_pixel_formats: Q_UNREACHABLE();
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
const char *mirSurfaceTypeToStr(MirSurfaceType type)
|
||||
{
|
||||
switch (type) {
|
||||
case mir_surface_type_normal: return "Normal"; /**< AKA "regular" */
|
||||
case mir_surface_type_utility: return "Utility"; /**< AKA "floating regular" */
|
||||
case mir_surface_type_dialog: return "Dialog";
|
||||
case mir_surface_type_gloss: return "Gloss";
|
||||
case mir_surface_type_freestyle: return "Freestyle";
|
||||
case mir_surface_type_menu: return "Menu";
|
||||
case mir_surface_type_inputmethod: return "Input Method"; /**< AKA "OSK" or handwriting etc. */
|
||||
case mir_surface_type_satellite: return "Satellite"; /**< AKA "toolbox"/"toolbar" */
|
||||
case mir_surface_type_tip: return "Tip"; /**< AKA "tooltip" */
|
||||
case mir_surface_types: Q_UNREACHABLE();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
|
||||
{
|
||||
switch (state) {
|
||||
case Qt::WindowNoState:
|
||||
case Qt::WindowActive:
|
||||
return mir_surface_state_restored;
|
||||
case Qt::WindowFullScreen:
|
||||
return mir_surface_state_fullscreen;
|
||||
case Qt::WindowMaximized:
|
||||
return mir_surface_state_maximized;
|
||||
case Qt::WindowMinimized:
|
||||
return mir_surface_state_minimized;
|
||||
}
|
||||
return mir_surface_state_unknown; // should never be reached
|
||||
}
|
||||
|
||||
MirSurfaceType qtWindowTypeToMirSurfaceType(Qt::WindowType type)
|
||||
{
|
||||
switch (type & Qt::WindowType_Mask) {
|
||||
case Qt::Dialog:
|
||||
return mir_surface_type_dialog;
|
||||
case Qt::Sheet:
|
||||
case Qt::Drawer:
|
||||
return mir_surface_type_utility;
|
||||
case Qt::Popup:
|
||||
case Qt::Tool:
|
||||
return mir_surface_type_menu;
|
||||
case Qt::ToolTip:
|
||||
return mir_surface_type_tip;
|
||||
case Qt::SplashScreen:
|
||||
return mir_surface_type_freestyle;
|
||||
case Qt::Window:
|
||||
default:
|
||||
return mir_surface_type_normal;
|
||||
}
|
||||
}
|
||||
|
||||
WId makeId()
|
||||
{
|
||||
static int id = 1;
|
||||
return id++;
|
||||
}
|
||||
|
||||
UAUiWindowRole roleFor(QWindow *window)
|
||||
{
|
||||
QVariant roleVariant = window->property("role");
|
||||
if (!roleVariant.isValid())
|
||||
return U_MAIN_ROLE;
|
||||
|
||||
uint role = roleVariant.toUInt();
|
||||
if (role < U_MAIN_ROLE || role > U_SHUTDOWN_DIALOG_ROLE)
|
||||
return U_MAIN_ROLE;
|
||||
|
||||
return static_cast<UAUiWindowRole>(role);
|
||||
}
|
||||
|
||||
QMirClientWindow *transientParentFor(QWindow *window)
|
||||
{
|
||||
QWindow *parent = window->transientParent();
|
||||
return parent ? static_cast<QMirClientWindow *>(parent->handle()) : nullptr;
|
||||
}
|
||||
|
||||
bool requiresParent(const MirSurfaceType type)
|
||||
{
|
||||
switch (type) {
|
||||
case mir_surface_type_dialog: //FIXME - not quite what the specification dictates, but is what Mir's api dictates
|
||||
case mir_surface_type_utility:
|
||||
case mir_surface_type_gloss:
|
||||
case mir_surface_type_menu:
|
||||
case mir_surface_type_satellite:
|
||||
case mir_surface_type_tip:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool requiresParent(const Qt::WindowType type)
|
||||
{
|
||||
return requiresParent(qtWindowTypeToMirSurfaceType(type));
|
||||
}
|
||||
|
||||
bool isMovable(const Qt::WindowType type)
|
||||
{
|
||||
auto mirType = qtWindowTypeToMirSurfaceType(type);
|
||||
switch (mirType) {
|
||||
case mir_surface_type_menu:
|
||||
case mir_surface_type_tip:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Spec makeSurfaceSpec(QWindow *window, MirPixelFormat pixelFormat, QMirClientWindow *parentWindowHandle,
|
||||
MirConnection *connection)
|
||||
{
|
||||
const auto geometry = window->geometry();
|
||||
const int width = geometry.width() > 0 ? geometry.width() : 1;
|
||||
const int height = geometry.height() > 0 ? geometry.height() : 1;
|
||||
auto type = qtWindowTypeToMirSurfaceType(window->type());
|
||||
|
||||
if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) {
|
||||
type = mir_surface_type_inputmethod;
|
||||
}
|
||||
|
||||
MirRectangle location{geometry.x(), geometry.y(), 0, 0};
|
||||
MirSurface *parent = nullptr;
|
||||
if (parentWindowHandle) {
|
||||
parent = parentWindowHandle->mirSurface();
|
||||
// Qt uses absolute positioning, but Mir positions surfaces relative to parent.
|
||||
location.top -= parentWindowHandle->geometry().top();
|
||||
location.left -= parentWindowHandle->geometry().left();
|
||||
}
|
||||
|
||||
Spec spec;
|
||||
|
||||
switch (type) {
|
||||
case mir_surface_type_menu:
|
||||
spec = Spec{mir_connection_create_spec_for_menu(connection, width, height, pixelFormat, parent,
|
||||
&location, mir_edge_attachment_any)};
|
||||
break;
|
||||
case mir_surface_type_dialog:
|
||||
spec = Spec{mir_connection_create_spec_for_modal_dialog(connection, width, height, pixelFormat, parent)};
|
||||
break;
|
||||
case mir_surface_type_utility:
|
||||
spec = Spec{mir_connection_create_spec_for_dialog(connection, width, height, pixelFormat)};
|
||||
break;
|
||||
case mir_surface_type_tip:
|
||||
#if MIR_CLIENT_VERSION < MIR_VERSION_NUMBER(3, 4, 0)
|
||||
spec = Spec{mir_connection_create_spec_for_tooltip(connection, width, height, pixelFormat, parent,
|
||||
&location)};
|
||||
#else
|
||||
spec = Spec{mir_connection_create_spec_for_tip(connection, width, height, pixelFormat, parent,
|
||||
&location, mir_edge_attachment_any)};
|
||||
#endif
|
||||
break;
|
||||
case mir_surface_type_inputmethod:
|
||||
spec = Spec{mir_connection_create_spec_for_input_method(connection, width, height, pixelFormat)};
|
||||
break;
|
||||
default:
|
||||
spec = Spec{mir_connection_create_spec_for_normal_surface(connection, width, height, pixelFormat)};
|
||||
break;
|
||||
}
|
||||
|
||||
qCDebug(mirclient, "makeSurfaceSpec(window=%p): %s spec (type=0x%x, position=(%d, %d)px, size=(%dx%d)px)",
|
||||
window, mirSurfaceTypeToStr(type), window->type(), location.left, location.top, width, height);
|
||||
|
||||
return std::move(spec);
|
||||
}
|
||||
|
||||
void setSizingConstraints(MirSurfaceSpec *spec, const QSize& minSize, const QSize& maxSize, const QSize& increment)
|
||||
{
|
||||
mir_surface_spec_set_min_width(spec, minSize.width());
|
||||
mir_surface_spec_set_min_height(spec, minSize.height());
|
||||
if (maxSize.width() >= minSize.width()) {
|
||||
mir_surface_spec_set_max_width(spec, maxSize.width());
|
||||
}
|
||||
if (maxSize.height() >= minSize.height()) {
|
||||
mir_surface_spec_set_max_height(spec, maxSize.height());
|
||||
}
|
||||
if (increment.width() > 0) {
|
||||
mir_surface_spec_set_width_increment(spec, increment.width());
|
||||
}
|
||||
if (increment.height() > 0) {
|
||||
mir_surface_spec_set_height_increment(spec, increment.height());
|
||||
}
|
||||
}
|
||||
|
||||
MirSurface *createMirSurface(QWindow *window, int mirOutputId, QMirClientWindow *parentWindowHandle,
|
||||
MirPixelFormat pixelFormat, MirConnection *connection,
|
||||
mir_surface_event_callback inputCallback, void *inputContext)
|
||||
{
|
||||
auto spec = makeSurfaceSpec(window, pixelFormat, parentWindowHandle, connection);
|
||||
|
||||
// Install event handler as early as possible
|
||||
mir_surface_spec_set_event_handler(spec.get(), inputCallback, inputContext);
|
||||
|
||||
const auto title = window->title().toUtf8();
|
||||
mir_surface_spec_set_name(spec.get(), title.constData());
|
||||
|
||||
setSizingConstraints(spec.get(), window->minimumSize(), window->maximumSize(), window->sizeIncrement());
|
||||
|
||||
if (window->windowState() == Qt::WindowFullScreen) {
|
||||
mir_surface_spec_set_fullscreen_on_output(spec.get(), mirOutputId);
|
||||
}
|
||||
|
||||
if (window->flags() & LowChromeWindowHint) {
|
||||
mir_surface_spec_set_shell_chrome(spec.get(), mir_shell_chrome_low);
|
||||
}
|
||||
|
||||
if (!window->isVisible()) {
|
||||
mir_surface_spec_set_state(spec.get(), mir_surface_state_hidden);
|
||||
}
|
||||
|
||||
auto surface = mir_surface_create_sync(spec.get());
|
||||
Q_ASSERT(mir_surface_is_valid(surface));
|
||||
return surface;
|
||||
}
|
||||
|
||||
QMirClientWindow *getParentIfNecessary(QWindow *window, QMirClientInput *input)
|
||||
{
|
||||
QMirClientWindow *parentWindowHandle = nullptr;
|
||||
if (requiresParent(window->type())) {
|
||||
parentWindowHandle = transientParentFor(window);
|
||||
if (parentWindowHandle == nullptr) {
|
||||
// NOTE: Mir requires this surface have a parent. Try using the last surface to receive input as that will
|
||||
// most likely be the one that caused this surface to be created
|
||||
parentWindowHandle = input->lastInputWindow();
|
||||
}
|
||||
}
|
||||
return parentWindowHandle;
|
||||
}
|
||||
|
||||
MirPixelFormat disableAlphaBufferIfPossible(MirPixelFormat pixelFormat)
|
||||
{
|
||||
switch (pixelFormat) {
|
||||
case mir_pixel_format_abgr_8888:
|
||||
return mir_pixel_format_xbgr_8888;
|
||||
case mir_pixel_format_argb_8888:
|
||||
return mir_pixel_format_xrgb_8888;
|
||||
default: // can do nothing, leave it alone
|
||||
return pixelFormat;
|
||||
}
|
||||
}
|
||||
} //namespace
|
||||
|
||||
|
||||
|
||||
class UbuntuSurface
|
||||
{
|
||||
public:
|
||||
UbuntuSurface(QMirClientWindow *platformWindow, EGLDisplay display, QMirClientInput *input, MirConnection *connection);
|
||||
~UbuntuSurface();
|
||||
|
||||
UbuntuSurface(const UbuntuSurface &) = delete;
|
||||
UbuntuSurface& operator=(const UbuntuSurface &) = delete;
|
||||
|
||||
void updateGeometry(const QRect &newGeometry);
|
||||
void updateTitle(const QString& title);
|
||||
void setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment);
|
||||
|
||||
void onSwapBuffersDone();
|
||||
void handleSurfaceResized(int width, int height);
|
||||
int needsRepaint() const;
|
||||
|
||||
MirSurfaceState state() const { return mir_surface_get_state(mMirSurface); }
|
||||
void setState(MirSurfaceState state);
|
||||
|
||||
MirSurfaceType type() const { return mir_surface_get_type(mMirSurface); }
|
||||
|
||||
void setShellChrome(MirShellChrome shellChrome);
|
||||
|
||||
EGLSurface eglSurface() const { return mEglSurface; }
|
||||
MirSurface *mirSurface() const { return mMirSurface; }
|
||||
|
||||
void setSurfaceParent(MirSurface*);
|
||||
bool hasParent() const { return mParented; }
|
||||
|
||||
QSurfaceFormat format() const { return mFormat; }
|
||||
|
||||
bool mNeedsExposeCatchup;
|
||||
|
||||
QString persistentSurfaceId();
|
||||
|
||||
private:
|
||||
static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context);
|
||||
void postEvent(const MirEvent *event);
|
||||
|
||||
QWindow * const mWindow;
|
||||
QMirClientWindow * const mPlatformWindow;
|
||||
QMirClientInput * const mInput;
|
||||
MirConnection * const mConnection;
|
||||
QMirClientWindow * mParentWindowHandle{nullptr};
|
||||
|
||||
MirSurface* mMirSurface;
|
||||
const EGLDisplay mEglDisplay;
|
||||
EGLSurface mEglSurface;
|
||||
|
||||
bool mNeedsRepaint;
|
||||
bool mParented;
|
||||
QSize mBufferSize;
|
||||
QSurfaceFormat mFormat;
|
||||
MirPixelFormat mPixelFormat;
|
||||
|
||||
QMutex mTargetSizeMutex;
|
||||
QSize mTargetSize;
|
||||
MirShellChrome mShellChrome;
|
||||
QString mPersistentIdStr;
|
||||
};
|
||||
|
||||
UbuntuSurface::UbuntuSurface(QMirClientWindow *platformWindow, EGLDisplay display, QMirClientInput *input, MirConnection *connection)
|
||||
: mWindow(platformWindow->window())
|
||||
, mPlatformWindow(platformWindow)
|
||||
, mInput(input)
|
||||
, mConnection(connection)
|
||||
, mEglDisplay(display)
|
||||
, mNeedsRepaint(false)
|
||||
, mParented(mWindow->transientParent() || mWindow->parent())
|
||||
, mFormat(mWindow->requestedFormat())
|
||||
, mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal)
|
||||
{
|
||||
// Have Qt choose most suitable EGLConfig for the requested surface format, and update format to reflect it
|
||||
EGLConfig config = q_configFromGLFormat(display, mFormat, true);
|
||||
if (config == 0) {
|
||||
// Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default
|
||||
// QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a
|
||||
// 1.4 context, but the XCB EGL backend tries to honor it, and fails. The 1.4 context appears to
|
||||
// have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default
|
||||
// requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455).
|
||||
static const bool isMesa = QString(eglQueryString(display, EGL_VENDOR)).contains(QStringLiteral("Mesa"));
|
||||
if (isMesa) {
|
||||
qCDebug(mirclientGraphics, "Attempting to choose OpenGL 1.4 context which may suit Mesa");
|
||||
mFormat.setMajorVersion(1);
|
||||
mFormat.setMinorVersion(4);
|
||||
config = q_configFromGLFormat(display, mFormat, true);
|
||||
}
|
||||
}
|
||||
if (config == 0) {
|
||||
qCritical() << "Qt failed to choose a suitable EGLConfig to suit the surface format" << mFormat;
|
||||
}
|
||||
|
||||
mFormat = q_glFormatFromConfig(display, config, mFormat);
|
||||
|
||||
// Have Mir decide the pixel format most suited to the chosen EGLConfig. This is the only way
|
||||
// Mir will know what EGLConfig has been chosen - it cannot deduce it from the buffers.
|
||||
mPixelFormat = mir_connection_get_egl_pixel_format(connection, display, config);
|
||||
// But the chosen EGLConfig might have an alpha buffer enabled, even if not requested by the client.
|
||||
// If that's the case, try to edit the chosen pixel format in order to disable the alpha buffer.
|
||||
// This is an optimization for the compositor, as it can avoid blending this surface.
|
||||
if (mWindow->requestedFormat().alphaBufferSize() < 0) {
|
||||
mPixelFormat = disableAlphaBufferIfPossible(mPixelFormat);
|
||||
}
|
||||
|
||||
const auto outputId = static_cast<QMirClientScreen *>(mWindow->screen()->handle())->mirOutputId();
|
||||
|
||||
mParentWindowHandle = getParentIfNecessary(mWindow, input);
|
||||
|
||||
mMirSurface = createMirSurface(mWindow, outputId, mParentWindowHandle, mPixelFormat, connection, surfaceEventCallback, this);
|
||||
mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindowFor(mMirSurface), nullptr);
|
||||
|
||||
mNeedsExposeCatchup = mir_surface_get_visibility(mMirSurface) == mir_surface_visibility_occluded;
|
||||
|
||||
// Window manager can give us a final size different from what we asked for
|
||||
// so let's check what we ended up getting
|
||||
MirSurfaceParameters parameters;
|
||||
mir_surface_get_parameters(mMirSurface, ¶meters);
|
||||
|
||||
auto geom = mWindow->geometry();
|
||||
geom.setWidth(parameters.width);
|
||||
geom.setHeight(parameters.height);
|
||||
|
||||
// Assume that the buffer size matches the surface size at creation time
|
||||
mBufferSize = geom.size();
|
||||
QWindowSystemInterface::handleGeometryChange(mWindow, geom);
|
||||
|
||||
qCDebug(mirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title()
|
||||
<< "role:" << roleFor(mWindow);
|
||||
qCDebug(mirclientGraphics)
|
||||
<< "Requested format:" << mWindow->requestedFormat()
|
||||
<< "\nActual format:" << mFormat
|
||||
<< "with associated Mir pixel format:" << mirPixelFormatToStr(mPixelFormat);
|
||||
}
|
||||
|
||||
UbuntuSurface::~UbuntuSurface()
|
||||
{
|
||||
if (mEglSurface != EGL_NO_SURFACE)
|
||||
eglDestroySurface(mEglDisplay, mEglSurface);
|
||||
if (mMirSurface) {
|
||||
mir_surface_release_sync(mMirSurface);
|
||||
}
|
||||
}
|
||||
|
||||
void UbuntuSurface::updateGeometry(const QRect &newGeometry)
|
||||
{
|
||||
qCDebug(mirclient,"updateGeometry(window=%p, width=%d, height=%d)", mWindow,
|
||||
newGeometry.width(), newGeometry.height());
|
||||
|
||||
Spec spec;
|
||||
if (isMovable(mWindow->type())) {
|
||||
spec = Spec{makeSurfaceSpec(mWindow, mPixelFormat, mParentWindowHandle, mConnection)};
|
||||
} else {
|
||||
spec = Spec{mir_connection_create_spec_for_changes(mConnection)};
|
||||
mir_surface_spec_set_width(spec.get(), newGeometry.width());
|
||||
mir_surface_spec_set_height(spec.get(), newGeometry.height());
|
||||
}
|
||||
mir_surface_apply_spec(mMirSurface, spec.get());
|
||||
}
|
||||
|
||||
void UbuntuSurface::updateTitle(const QString& newTitle)
|
||||
{
|
||||
const auto title = newTitle.toUtf8();
|
||||
Spec spec{mir_connection_create_spec_for_changes(mConnection)};
|
||||
mir_surface_spec_set_name(spec.get(), title.constData());
|
||||
mir_surface_apply_spec(mMirSurface, spec.get());
|
||||
}
|
||||
|
||||
void UbuntuSurface::setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment)
|
||||
{
|
||||
Spec spec{mir_connection_create_spec_for_changes(mConnection)};
|
||||
::setSizingConstraints(spec.get(), minSize, maxSize, increment);
|
||||
mir_surface_apply_spec(mMirSurface, spec.get());
|
||||
}
|
||||
|
||||
void UbuntuSurface::handleSurfaceResized(int width, int height)
|
||||
{
|
||||
QMutexLocker lock(&mTargetSizeMutex);
|
||||
|
||||
// mir's resize event is mainly a signal that we need to redraw our content. We use the
|
||||
// width/height as identifiers to figure out if this is the latest surface resize event
|
||||
// that has posted, discarding any old ones. This avoids issuing too many redraw events.
|
||||
// see TODO in postEvent as the ideal way we should handle this.
|
||||
// The actual buffer size may or may have not changed at this point, so let the rendering
|
||||
// thread drive the window geometry updates.
|
||||
mNeedsRepaint = mTargetSize.width() == width && mTargetSize.height() == height;
|
||||
}
|
||||
|
||||
int UbuntuSurface::needsRepaint() const
|
||||
{
|
||||
if (mNeedsRepaint) {
|
||||
if (mTargetSize != mBufferSize) {
|
||||
//If the buffer hasn't changed yet, we need at least two redraws,
|
||||
//once to get the new buffer size and propagate the geometry changes
|
||||
//and the second to redraw the content at the new size
|
||||
return 2;
|
||||
} else {
|
||||
// The buffer size has already been updated so we only need one redraw
|
||||
// to render at the new size
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UbuntuSurface::setState(MirSurfaceState state)
|
||||
{
|
||||
mir_wait_for(mir_surface_set_state(mMirSurface, state));
|
||||
}
|
||||
|
||||
void UbuntuSurface::setShellChrome(MirShellChrome chrome)
|
||||
{
|
||||
if (chrome != mShellChrome) {
|
||||
auto spec = Spec{mir_connection_create_spec_for_changes(mConnection)};
|
||||
mir_surface_spec_set_shell_chrome(spec.get(), chrome);
|
||||
mir_surface_apply_spec(mMirSurface, spec.get());
|
||||
|
||||
mShellChrome = chrome;
|
||||
}
|
||||
}
|
||||
|
||||
void UbuntuSurface::onSwapBuffersDone()
|
||||
{
|
||||
static int sFrameNumber = 0;
|
||||
++sFrameNumber;
|
||||
|
||||
EGLint eglSurfaceWidth = -1;
|
||||
EGLint eglSurfaceHeight = -1;
|
||||
eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &eglSurfaceWidth);
|
||||
eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &eglSurfaceHeight);
|
||||
|
||||
const bool validSize = eglSurfaceWidth > 0 && eglSurfaceHeight > 0;
|
||||
|
||||
if (validSize && (mBufferSize.width() != eglSurfaceWidth || mBufferSize.height() != eglSurfaceHeight)) {
|
||||
|
||||
qCDebug(mirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - size changed (%d, %d) => (%d, %d)",
|
||||
mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height(), eglSurfaceWidth, eglSurfaceHeight);
|
||||
|
||||
mBufferSize.rwidth() = eglSurfaceWidth;
|
||||
mBufferSize.rheight() = eglSurfaceHeight;
|
||||
|
||||
QRect newGeometry = mPlatformWindow->geometry();
|
||||
newGeometry.setSize(mBufferSize);
|
||||
|
||||
QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry);
|
||||
} else {
|
||||
qCDebug(mirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - buffer size (%d,%d)",
|
||||
mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height());
|
||||
}
|
||||
}
|
||||
|
||||
void UbuntuSurface::surfaceEventCallback(MirSurface *surface, const MirEvent *event, void* context)
|
||||
{
|
||||
Q_UNUSED(surface);
|
||||
Q_ASSERT(context != nullptr);
|
||||
|
||||
auto s = static_cast<UbuntuSurface *>(context);
|
||||
s->postEvent(event);
|
||||
}
|
||||
|
||||
void UbuntuSurface::postEvent(const MirEvent *event)
|
||||
{
|
||||
if (mir_event_type_resize == mir_event_get_type(event)) {
|
||||
// TODO: The current event queue just accumulates all resize events;
|
||||
// It would be nicer if we could update just one event if that event has not been dispatched.
|
||||
// As a workaround, we use the width/height as an identifier of this latest event
|
||||
// so the event handler (handleSurfaceResized) can discard/ignore old ones.
|
||||
const auto resizeEvent = mir_event_get_resize_event(event);
|
||||
const auto width = mir_resize_event_get_width(resizeEvent);
|
||||
const auto height = mir_resize_event_get_height(resizeEvent);
|
||||
qCDebug(mirclient, "resizeEvent(window=%p, width=%d, height=%d)", mWindow, width, height);
|
||||
|
||||
QMutexLocker lock(&mTargetSizeMutex);
|
||||
mTargetSize.rwidth() = width;
|
||||
mTargetSize.rheight() = height;
|
||||
}
|
||||
|
||||
mInput->postEvent(mPlatformWindow, event);
|
||||
}
|
||||
|
||||
void UbuntuSurface::setSurfaceParent(MirSurface* parent)
|
||||
{
|
||||
qCDebug(mirclient, "setSurfaceParent(window=%p)", mWindow);
|
||||
|
||||
mParented = true;
|
||||
Spec spec{mir_connection_create_spec_for_changes(mConnection)};
|
||||
mir_surface_spec_set_parent(spec.get(), parent);
|
||||
mir_surface_apply_spec(mMirSurface, spec.get());
|
||||
}
|
||||
|
||||
QString UbuntuSurface::persistentSurfaceId()
|
||||
{
|
||||
if (mPersistentIdStr.isEmpty()) {
|
||||
MirPersistentId* mirPermaId = mir_surface_request_persistent_id_sync(mMirSurface);
|
||||
mPersistentIdStr = mir_persistent_id_as_string(mirPermaId);
|
||||
mir_persistent_id_release(mirPermaId);
|
||||
}
|
||||
return mPersistentIdStr;
|
||||
}
|
||||
|
||||
QMirClientWindow::QMirClientWindow(QWindow *w, QMirClientInput *input, QMirClientNativeInterface *native,
|
||||
QMirClientAppStateController *appState, EGLDisplay eglDisplay,
|
||||
MirConnection *mirConnection, QMirClientDebugExtension *debugExt)
|
||||
: QObject(nullptr)
|
||||
, QPlatformWindow(w)
|
||||
, mId(makeId())
|
||||
, mWindowState(w->windowState())
|
||||
, mWindowFlags(w->flags())
|
||||
, mWindowVisible(false)
|
||||
, mAppStateController(appState)
|
||||
, mDebugExtention(debugExt)
|
||||
, mNativeInterface(native)
|
||||
, mSurface(new UbuntuSurface{this, eglDisplay, input, mirConnection})
|
||||
, mScale(1.0)
|
||||
, mFormFactor(mir_form_factor_unknown)
|
||||
{
|
||||
mWindowExposed = mSurface->mNeedsExposeCatchup == false;
|
||||
|
||||
qCDebug(mirclient, "QMirClientWindow(window=%p, screen=%p, input=%p, surf=%p) with title '%s', role: '%d'",
|
||||
w, w->screen()->handle(), input, mSurface.get(), qPrintable(window()->title()), roleFor(window()));
|
||||
}
|
||||
|
||||
QMirClientWindow::~QMirClientWindow()
|
||||
{
|
||||
qCDebug(mirclient, "~QMirClientWindow(window=%p)", this);
|
||||
}
|
||||
|
||||
void QMirClientWindow::handleSurfaceResized(int width, int height)
|
||||
{
|
||||
QMutexLocker lock(&mMutex);
|
||||
qCDebug(mirclient, "handleSurfaceResize(window=%p, size=(%dx%d)px", window(), width, height);
|
||||
|
||||
mSurface->handleSurfaceResized(width, height);
|
||||
|
||||
// This resize event could have occurred just after the last buffer swap for this window.
|
||||
// This means the client may still be holding a buffer with the older size. The first redraw call
|
||||
// will then render at the old size. After swapping the client now will get a new buffer with the
|
||||
// updated size but it still needs re-rendering so another redraw may be needed.
|
||||
// A mir API to drop the currently held buffer would help here, so that we wouldn't have to redraw twice
|
||||
auto const numRepaints = mSurface->needsRepaint();
|
||||
lock.unlock();
|
||||
qCDebug(mirclient, "handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints);
|
||||
for (int i = 0; i < numRepaints; i++) {
|
||||
qCDebug(mirclient, "handleSurfaceResize(window=%p) repainting size=(%dx%d)dp", window(), geometry().size().width(), geometry().size().height());
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientWindow::handleSurfaceExposeChange(bool exposed)
|
||||
{
|
||||
QMutexLocker lock(&mMutex);
|
||||
qCDebug(mirclient, "handleSurfaceExposeChange(window=%p, exposed=%s)", window(), exposed ? "true" : "false");
|
||||
|
||||
mSurface->mNeedsExposeCatchup = false;
|
||||
if (mWindowExposed == exposed) return;
|
||||
mWindowExposed = exposed;
|
||||
|
||||
lock.unlock();
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
|
||||
}
|
||||
|
||||
void QMirClientWindow::handleSurfaceFocusChanged(bool focused)
|
||||
{
|
||||
qCDebug(mirclient, "handleSurfaceFocusChanged(window=%p, focused=%d)", window(), focused);
|
||||
if (focused) {
|
||||
mAppStateController->setWindowFocused(true);
|
||||
QWindowSystemInterface::handleWindowActivated(window(), Qt::ActiveWindowFocusReason);
|
||||
} else {
|
||||
mAppStateController->setWindowFocused(false);
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientWindow::handleSurfaceVisibilityChanged(bool visible)
|
||||
{
|
||||
qCDebug(mirclient, "handleSurfaceVisibilityChanged(window=%p, visible=%d)", window(), visible);
|
||||
|
||||
if (mWindowVisible == visible) return;
|
||||
mWindowVisible = visible;
|
||||
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
|
||||
}
|
||||
|
||||
void QMirClientWindow::handleSurfaceStateChanged(Qt::WindowState state)
|
||||
{
|
||||
qCDebug(mirclient, "handleSurfaceStateChanged(window=%p, %s)", window(), qtWindowStateToStr(state));
|
||||
|
||||
if (mWindowState == state) return;
|
||||
mWindowState = state;
|
||||
|
||||
QWindowSystemInterface::handleWindowStateChanged(window(), state);
|
||||
}
|
||||
|
||||
void QMirClientWindow::setWindowState(Qt::WindowStates states)
|
||||
{
|
||||
Qt::WindowState state = Qt::WindowNoState;
|
||||
if (states & Qt::WindowMinimized)
|
||||
state = Qt::WindowMinimized;
|
||||
else if (states & Qt::WindowFullScreen)
|
||||
state = Qt::WindowFullScreen;
|
||||
else if (states & Qt::WindowMaximized)
|
||||
state = Qt::WindowMaximized;
|
||||
|
||||
QMutexLocker lock(&mMutex);
|
||||
qCDebug(mirclient, "setWindowState(window=%p, %s)", this, qtWindowStateToStr(state));
|
||||
|
||||
if (mWindowState == state) return;
|
||||
mWindowState = state;
|
||||
|
||||
lock.unlock();
|
||||
updateSurfaceState();
|
||||
}
|
||||
|
||||
void QMirClientWindow::setWindowFlags(Qt::WindowFlags flags)
|
||||
{
|
||||
QMutexLocker lock(&mMutex);
|
||||
qCDebug(mirclient, "setWindowFlags(window=%p, 0x%x)", this, (int)flags);
|
||||
|
||||
if (mWindowFlags == flags) return;
|
||||
mWindowFlags = flags;
|
||||
|
||||
mSurface->setShellChrome(mWindowFlags & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal);
|
||||
}
|
||||
|
||||
QRect QMirClientWindow::geometry() const
|
||||
{
|
||||
if (mDebugExtention) {
|
||||
auto geom = QPlatformWindow::geometry();
|
||||
geom.moveTopLeft(mDebugExtention->mapSurfacePointToScreen(mSurface->mirSurface(), QPoint(0,0)));
|
||||
return geom;
|
||||
} else {
|
||||
return QPlatformWindow::geometry();
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientWindow::setGeometry(const QRect& rect)
|
||||
{
|
||||
QMutexLocker lock(&mMutex);
|
||||
|
||||
if (window()->windowState() == Qt::WindowFullScreen || window()->windowState() == Qt::WindowMaximized) {
|
||||
qCDebug(mirclient, "setGeometry(window=%p) - not resizing, window is maximized or fullscreen", window());
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(mirclient, "setGeometry (window=%p, position=(%d, %d)dp, size=(%dx%d)dp)",
|
||||
window(), rect.x(), rect.y(), rect.width(), rect.height());
|
||||
// Immediately update internal geometry so Qt believes position updated
|
||||
QRect newPosition(geometry());
|
||||
newPosition.moveTo(rect.topLeft());
|
||||
QPlatformWindow::setGeometry(newPosition);
|
||||
|
||||
mSurface->updateGeometry(rect);
|
||||
// Note: don't call handleGeometryChange here, wait to see what Mir replies with.
|
||||
}
|
||||
|
||||
void QMirClientWindow::setVisible(bool visible)
|
||||
{
|
||||
QMutexLocker lock(&mMutex);
|
||||
qCDebug(mirclient, "setVisible (window=%p, visible=%s)", window(), visible ? "true" : "false");
|
||||
|
||||
if (mWindowVisible == visible) return;
|
||||
mWindowVisible = visible;
|
||||
|
||||
if (visible) {
|
||||
if (!mSurface->hasParent() && window()->type() == Qt::Dialog) {
|
||||
// The dialog may have been parented after creation time
|
||||
// so morph it into a modal dialog
|
||||
auto parent = transientParentFor(window());
|
||||
if (parent) {
|
||||
mSurface->setSurfaceParent(parent->mirSurface());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
updateSurfaceState();
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
|
||||
}
|
||||
|
||||
void QMirClientWindow::setWindowTitle(const QString& title)
|
||||
{
|
||||
QMutexLocker lock(&mMutex);
|
||||
qCDebug(mirclient, "setWindowTitle(window=%p) title=%s)", window(), title.toUtf8().constData());
|
||||
mSurface->updateTitle(title);
|
||||
}
|
||||
|
||||
void QMirClientWindow::propagateSizeHints()
|
||||
{
|
||||
QMutexLocker lock(&mMutex);
|
||||
const auto win = window();
|
||||
qCDebug(mirclient, "propagateSizeHints(window=%p) min(%d,%d), max(%d,%d) increment(%d, %d)",
|
||||
win, win->minimumSize().width(), win->minimumSize().height(),
|
||||
win->maximumSize().width(), win->maximumSize().height(),
|
||||
win->sizeIncrement().width(), win->sizeIncrement().height());
|
||||
mSurface->setSizingConstraints(win->minimumSize(), win->maximumSize(), win->sizeIncrement());
|
||||
}
|
||||
|
||||
bool QMirClientWindow::isExposed() const
|
||||
{
|
||||
// mNeedsExposeCatchup because we need to render a frame to get the expose surface event from mir.
|
||||
return mWindowVisible && (mWindowExposed || (mSurface && mSurface->mNeedsExposeCatchup));
|
||||
}
|
||||
|
||||
QSurfaceFormat QMirClientWindow::format() const
|
||||
{
|
||||
return mSurface->format();
|
||||
}
|
||||
|
||||
QPoint QMirClientWindow::mapToGlobal(const QPoint &pos) const
|
||||
{
|
||||
if (mDebugExtention) {
|
||||
return mDebugExtention->mapSurfacePointToScreen(mSurface->mirSurface(), pos);
|
||||
} else {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
void* QMirClientWindow::eglSurface() const
|
||||
{
|
||||
return mSurface->eglSurface();
|
||||
}
|
||||
|
||||
MirSurface *QMirClientWindow::mirSurface() const
|
||||
{
|
||||
return mSurface->mirSurface();
|
||||
}
|
||||
|
||||
WId QMirClientWindow::winId() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
void QMirClientWindow::onSwapBuffersDone()
|
||||
{
|
||||
QMutexLocker lock(&mMutex);
|
||||
mSurface->onSwapBuffersDone();
|
||||
|
||||
if (mSurface->mNeedsExposeCatchup) {
|
||||
mSurface->mNeedsExposeCatchup = false;
|
||||
mWindowExposed = false;
|
||||
|
||||
lock.unlock();
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientWindow::handleScreenPropertiesChange(MirFormFactor formFactor, float scale)
|
||||
{
|
||||
// Update the scale & form factor native-interface properties for the windows affected
|
||||
// as there is no convenient way to emit signals for those custom properties on a QScreen
|
||||
if (formFactor != mFormFactor) {
|
||||
mFormFactor = formFactor;
|
||||
Q_EMIT mNativeInterface->windowPropertyChanged(this, QStringLiteral("formFactor"));
|
||||
}
|
||||
|
||||
if (!qFuzzyCompare(scale, mScale)) {
|
||||
mScale = scale;
|
||||
Q_EMIT mNativeInterface->windowPropertyChanged(this, QStringLiteral("scale"));
|
||||
}
|
||||
}
|
||||
|
||||
void QMirClientWindow::updateSurfaceState()
|
||||
{
|
||||
QMutexLocker lock(&mMutex);
|
||||
MirSurfaceState newState = mWindowVisible ? qtWindowStateToMirSurfaceState(mWindowState) :
|
||||
mir_surface_state_hidden;
|
||||
qCDebug(mirclient, "updateSurfaceState (window=%p, surfaceState=%s)", window(), mirSurfaceStateToStr(newState));
|
||||
if (newState != mSurface->state()) {
|
||||
mSurface->setState(newState);
|
||||
}
|
||||
}
|
||||
|
||||
QString QMirClientWindow::persistentSurfaceId()
|
||||
{
|
||||
return mSurface->persistentSurfaceId();
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2014-2016 Canonical, Ltd.
|
||||
** 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 QMIRCLIENTWINDOW_H
|
||||
#define QMIRCLIENTWINDOW_H
|
||||
|
||||
#include <qpa/qplatformwindow.h>
|
||||
#include <QSharedPointer>
|
||||
#include <QMutex>
|
||||
|
||||
#include <mir_toolkit/common.h> // needed only for MirFormFactor enum
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
||||
class QMirClientAppStateController;
|
||||
class QMirClientDebugExtension;
|
||||
class QMirClientNativeInterface;
|
||||
class QMirClientInput;
|
||||
class QMirClientScreen;
|
||||
class UbuntuSurface;
|
||||
struct MirSurface;
|
||||
class MirConnection;
|
||||
|
||||
class QMirClientWindow : public QObject, public QPlatformWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QMirClientWindow(QWindow *w, QMirClientInput *input, QMirClientNativeInterface* native,
|
||||
QMirClientAppStateController *appState, EGLDisplay eglDisplay,
|
||||
MirConnection *mirConnection, QMirClientDebugExtension *debugExt);
|
||||
virtual ~QMirClientWindow();
|
||||
|
||||
// QPlatformWindow methods.
|
||||
WId winId() const override;
|
||||
QRect geometry() const override;
|
||||
void setGeometry(const QRect&) override;
|
||||
void setWindowState(Qt::WindowStates state) override;
|
||||
void setWindowFlags(Qt::WindowFlags flags) override;
|
||||
void setVisible(bool visible) override;
|
||||
void setWindowTitle(const QString &title) override;
|
||||
void propagateSizeHints() override;
|
||||
bool isExposed() const override;
|
||||
|
||||
QPoint mapToGlobal(const QPoint &pos) const override;
|
||||
QSurfaceFormat format() const override;
|
||||
|
||||
// Additional Window properties exposed by NativeInterface
|
||||
MirFormFactor formFactor() const { return mFormFactor; }
|
||||
float scale() const { return mScale; }
|
||||
|
||||
// New methods.
|
||||
void *eglSurface() const;
|
||||
MirSurface *mirSurface() const;
|
||||
void handleSurfaceResized(int width, int height);
|
||||
void handleSurfaceExposeChange(bool exposed);
|
||||
void handleSurfaceFocusChanged(bool focused);
|
||||
void handleSurfaceVisibilityChanged(bool visible);
|
||||
void handleSurfaceStateChanged(Qt::WindowState state);
|
||||
void onSwapBuffersDone();
|
||||
void handleScreenPropertiesChange(MirFormFactor formFactor, float scale);
|
||||
QString persistentSurfaceId();
|
||||
|
||||
private:
|
||||
void updateSurfaceState();
|
||||
mutable QMutex mMutex;
|
||||
const WId mId;
|
||||
Qt::WindowState mWindowState;
|
||||
Qt::WindowFlags mWindowFlags;
|
||||
bool mWindowVisible;
|
||||
bool mWindowExposed;
|
||||
QMirClientAppStateController *mAppStateController;
|
||||
QMirClientDebugExtension *mDebugExtention;
|
||||
QMirClientNativeInterface *mNativeInterface;
|
||||
std::unique_ptr<UbuntuSurface> mSurface;
|
||||
float mScale;
|
||||
MirFormFactor mFormFactor;
|
||||
};
|
||||
|
||||
#endif // QMIRCLIENTWINDOW_H
|
@ -48,6 +48,4 @@ haiku {
|
||||
|
||||
wasm: SUBDIRS += wasm
|
||||
|
||||
qtConfig(mirclient): SUBDIRS += mirclient
|
||||
|
||||
qtConfig(integrityfb): SUBDIRS += integrity
|
||||
|
Loading…
x
Reference in New Issue
Block a user