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:
Gerry Boland 2018-07-18 15:28:02 +01:00 committed by Johan Helsing
parent e48b854087
commit 8c73ddd8e3
39 changed files with 2 additions and 5285 deletions

View File

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

View File

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

View File

@ -1,3 +0,0 @@
{
"Keys": [ "mirclient" ]
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 &paramList,
int &argc, char **argv) override;
};
#endif // QMIRCLIENTPLUGIN_H

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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, &parameters);
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();
}

View File

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

View File

@ -48,6 +48,4 @@ haiku {
wasm: SUBDIRS += wasm
qtConfig(mirclient): SUBDIRS += mirclient
qtConfig(integrityfb): SUBDIRS += integrity