summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--src/client/client.pro6
-rw-r--r--src/client/inputdeviceintegration/inputdeviceintegration.pri11
-rw-r--r--src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h64
-rw-r--r--src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp96
-rw-r--r--src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory_p.h61
-rw-r--r--src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin.cpp55
-rw-r--r--src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin_p.h69
-rw-r--r--src/client/qwaylanddisplay.cpp12
-rw-r--r--src/client/qwaylanddisplay_p.h1
-rw-r--r--src/client/qwaylandinputdevice.cpp296
-rw-r--r--src/client/qwaylandinputdevice_p.h143
-rw-r--r--src/client/qwaylandintegration.cpp32
-rw-r--r--src/client/qwaylandintegration_p.h9
-rw-r--r--src/client/qwaylandwindow.cpp20
-rw-r--r--src/client/qwaylandwindow_p.h3
-rw-r--r--src/compositor/compositor_api/compositor_api.pri3
-rw-r--r--src/compositor/compositor_api/qwaylandclient.cpp174
-rw-r--r--src/compositor/compositor_api/qwaylandclient.h87
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp15
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.h11
-rw-r--r--src/compositor/compositor_api/qwaylandinput.cpp6
-rw-r--r--src/compositor/compositor_api/qwaylandinput.h3
-rw-r--r--src/compositor/compositor_api/qwaylandquickcompositor.cpp2
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp32
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.h8
-rw-r--r--src/compositor/compositor_api/qwaylandsurface_p.h6
-rw-r--r--src/compositor/compositor_api/qwaylandsurfaceitem.cpp54
-rw-r--r--src/compositor/compositor_api/qwaylandsurfaceitem.h3
-rw-r--r--src/compositor/global/qwaylandexport.h2
-rw-r--r--src/compositor/wayland_wrapper/qwlcompositor.cpp65
-rw-r--r--src/compositor/wayland_wrapper/qwlcompositor_p.h24
-rw-r--r--src/compositor/wayland_wrapper/qwlsurface.cpp22
-rw-r--r--src/compositor/wayland_wrapper/qwlsurface_p.h1
-rw-r--r--src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp3
-rw-r--r--tests/auto/compositor/compositor.pro4
-rw-r--r--tests/auto/compositor/mockclient.cpp4
-rw-r--r--tests/auto/compositor/mockclient.h5
-rw-r--r--tests/auto/compositor/mockseat.cpp56
-rw-r--r--tests/auto/compositor/mockseat.h58
-rw-r--r--tests/auto/compositor/testinputdevice.cpp70
-rw-r--r--tests/auto/compositor/testinputdevice.h65
-rw-r--r--tests/auto/compositor/tst_compositor.cpp85
43 files changed, 1483 insertions, 265 deletions
diff --git a/.qmake.conf b/.qmake.conf
index e28797de2..a98bcf66b 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,3 +1,3 @@
load(qt_build_config)
-MODULE_VERSION = 5.4.0
+MODULE_VERSION = 5.5.0
diff --git a/src/client/client.pro b/src/client/client.pro
index a8a1136ea..ef3cff054 100644
--- a/src/client/client.pro
+++ b/src/client/client.pro
@@ -3,7 +3,10 @@ QT += core-private gui-private
QT_FOR_PRIVATE += platformsupport-private
MODULE=waylandclient
-MODULE_PLUGIN_TYPES = wayland-graphics-integration-client wayland-decoration-client
+MODULE_PLUGIN_TYPES = \
+ wayland-graphics-integration-client \
+ wayland-inputdevice-integration \
+ wayland-decoration-client
load(qt_module)
@@ -112,3 +115,4 @@ HEADERS += qwaylandintegration_p.h \
include(hardwareintegration/hardwareintegration.pri)
include(shellintegration/shellintegration.pri)
+include(inputdeviceintegration/inputdeviceintegration.pri)
diff --git a/src/client/inputdeviceintegration/inputdeviceintegration.pri b/src/client/inputdeviceintegration/inputdeviceintegration.pri
new file mode 100644
index 000000000..f16dfc3c9
--- /dev/null
+++ b/src/client/inputdeviceintegration/inputdeviceintegration.pri
@@ -0,0 +1,11 @@
+INCLUDEPATH += $$PWD
+
+SOURCES += \
+ $$PWD/qwaylandinputdeviceintegrationplugin.cpp \
+ $$PWD/qwaylandinputdeviceintegrationfactory.cpp
+
+HEADERS += \
+ $$PWD/qwaylandinputdeviceintegration_p.h \
+ $$PWD/qwaylandinputdeviceintegrationplugin_p.h \
+ $$PWD/qwaylandinputdeviceintegrationfactory_p.h
+
diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h b/src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h
new file mode 100644
index 000000000..5fa187e69
--- /dev/null
+++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 LG Electronics Ltd
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDINPUTDEVICEINTEGRATION_H
+#define QWAYLANDINPUTDEVICEINTEGRATION_H
+
+#include <QtCore/qglobal.h>
+#include <QtWaylandClient/private/qwaylandclientexport_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandDisplay;
+class QWaylandInputDevice;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDeviceIntegration
+{
+public:
+ QWaylandInputDeviceIntegration() {}
+ virtual ~QWaylandInputDeviceIntegration() {}
+
+ virtual QWaylandInputDevice *createInputDevice(QWaylandDisplay *d, int version, uint32_t id) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDINPUTDEVICEINTEGRATION_H
diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp
new file mode 100644
index 000000000..58a82fb2c
--- /dev/null
+++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 LG Electronics Ltd
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandinputdeviceintegrationfactory_p.h"
+#include "qwaylandinputdeviceintegrationplugin_p.h"
+#include "qwaylandinputdeviceintegration_p.h"
+#include <QtCore/private/qfactoryloader_p.h>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDir>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_LIBRARY
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QWaylandInputDeviceIntegrationFactoryInterface_iid, QLatin1String("/wayland-inputdevice-integration"), Qt::CaseInsensitive))
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader,
+ (QWaylandInputDeviceIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive))
+#endif
+
+QStringList QWaylandInputDeviceIntegrationFactory::keys(const QString &pluginPath)
+{
+#ifndef QT_NO_LIBRARY
+ QStringList list;
+ if (!pluginPath.isEmpty()) {
+ QCoreApplication::addLibraryPath(pluginPath);
+ list = directLoader()->keyMap().values();
+ if (!list.isEmpty()) {
+ const QString postFix = QStringLiteral(" (from ")
+ + QDir::toNativeSeparators(pluginPath)
+ + QLatin1Char(')');
+ const QStringList::iterator end = list.end();
+ for (QStringList::iterator it = list.begin(); it != end; ++it)
+ (*it).append(postFix);
+ }
+ }
+ list.append(loader()->keyMap().values());
+ return list;
+#else
+ return QStringList();
+#endif
+}
+
+QWaylandInputDeviceIntegration *QWaylandInputDeviceIntegrationFactory::create(const QString &name, const QStringList &args, const QString &pluginPath)
+{
+#ifndef QT_NO_LIBRARY
+ // Try loading the plugin from platformPluginPath first:
+ if (!pluginPath.isEmpty()) {
+ QCoreApplication::addLibraryPath(pluginPath);
+ if (QWaylandInputDeviceIntegration *ret = qLoadPlugin1<QWaylandInputDeviceIntegration, QWaylandInputDeviceIntegrationPlugin>(directLoader(), name, args))
+ return ret;
+ }
+ if (QWaylandInputDeviceIntegration *ret = qLoadPlugin1<QWaylandInputDeviceIntegration, QWaylandInputDeviceIntegrationPlugin>(loader(), name, args))
+ return ret;
+#endif
+ return Q_NULLPTR;
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory_p.h b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory_p.h
new file mode 100644
index 000000000..13cddc24f
--- /dev/null
+++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory_p.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 LG Electronics Ltd
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDINPUTDEVICEINTEGRATIONFACTORY_H
+#define QWAYLANDINPUTDEVICEINTEGRATIONFACTORY_H
+
+#include <QtWaylandClient/private/qwaylandclientexport_p.h>
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandInputDeviceIntegration;
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDeviceIntegrationFactory
+{
+public:
+ static QStringList keys(const QString &pluginPath = QString());
+ static QWaylandInputDeviceIntegration *create(const QString &name, const QStringList &args, const QString &pluginPath = QString());
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDINPUTDEVICENTEGRATIONFACTORY_H
diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin.cpp b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin.cpp
new file mode 100644
index 000000000..71a933254
--- /dev/null
+++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 LG Electronics Ltd
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandinputdeviceintegrationplugin_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QWaylandInputDeviceIntegrationPlugin::QWaylandInputDeviceIntegrationPlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QWaylandInputDeviceIntegrationPlugin::~QWaylandInputDeviceIntegrationPlugin()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin_p.h b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin_p.h
new file mode 100644
index 000000000..a0a062f4c
--- /dev/null
+++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 LG Electronics Ltd
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDINPUTDEVICEINTEGRATIONPLUGIN_H
+#define QWAYLANDINPUTDEVICEINTEGRATIONPLUGIN_H
+
+#include <QtWaylandClient/private/qwaylandclientexport_p.h>
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandInputDeviceIntegration;
+
+#define QWaylandInputDeviceIntegrationFactoryInterface_iid "org.qt-project.Qt.WaylandClient.QWaylandInputDeviceIntegrationFactoryInterface.5.3"
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDeviceIntegrationPlugin : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QWaylandInputDeviceIntegrationPlugin(QObject *parent = 0);
+ ~QWaylandInputDeviceIntegrationPlugin();
+
+ virtual QWaylandInputDeviceIntegration *create(const QString &key, const QStringList &paramList) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDINPUTDEVICEINTEGRATIONPLUGIN_H
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index fda2c204e..023050326 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -97,6 +97,16 @@ QWaylandShellSurface *QWaylandDisplay::createShellSurface(QWaylandWindow *window
return Q_NULLPTR;
}
+struct ::wl_region *QWaylandDisplay::createRegion(const QRegion &qregion)
+{
+ struct ::wl_region *region = mCompositor.create_region();
+
+ Q_FOREACH (const QRect &rect, qregion.rects())
+ wl_region_add(region, rect.x(), rect.y(), rect.width(), rect.height());
+
+ return region;
+}
+
QWaylandClientBufferIntegration * QWaylandDisplay::clientBufferIntegration() const
{
return mWaylandIntegration->clientBufferIntegration();
@@ -242,7 +252,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
} else if (interface == QStringLiteral("wl_shell")){
mShell.reset(new QtWayland::wl_shell(registry, id, 1));
} else if (interface == QStringLiteral("wl_seat")) {
- QWaylandInputDevice *inputDevice = new QWaylandInputDevice(this, version, id);
+ QWaylandInputDevice *inputDevice = mWaylandIntegration->createInputDevice(this, version, id);
mInputDevices.append(inputDevice);
} else if (interface == QStringLiteral("wl_data_device_manager")) {
mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id));
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
index 8d1d26bba..2f12ee7f9 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -103,6 +103,7 @@ public:
struct wl_surface *createSurface(void *handle);
QWaylandShellSurface *createShellSurface(QWaylandWindow *window);
+ struct ::wl_region *createRegion(const QRegion &qregion);
QWaylandClientBufferIntegration *clientBufferIntegration() const;
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index 39d1705c0..43c5807d4 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -63,170 +63,99 @@
#include <QtGui/QGuiApplication>
-#ifndef QT_NO_WAYLAND_XKB
-#include <xkbcommon/xkbcommon.h>
-#include <xkbcommon/xkbcommon-keysyms.h>
-#endif
-
QT_BEGIN_NAMESPACE
-class QWaylandInputDevice::Keyboard : public QtWayland::wl_keyboard
-{
-public:
- Keyboard(QWaylandInputDevice *p)
- : mParent(p)
- , mFocus(0)
+QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
+ : mParent(p)
+ , mFocus(0)
#ifndef QT_NO_WAYLAND_XKB
- , mXkbContext(0)
- , mXkbMap(0)
- , mXkbState(0)
+ , mXkbContext(0)
+ , mXkbMap(0)
+ , mXkbState(0)
#endif
- , mFocusCallback(0)
- , mNativeModifiers(0)
- {
+ , mFocusCallback(0)
+ , mNativeModifiers(0)
+{
+ connect(&mRepeatTimer, SIGNAL(timeout()), this, SLOT(repeatKey()));
+}
+
#ifndef QT_NO_WAYLAND_XKB
- xkb_rule_names names;
- names.rules = strdup("evdev");
- names.model = strdup("pc105");
- names.layout = strdup("us");
- names.variant = strdup("");
- names.options = strdup("");
-
- mXkbContext = xkb_context_new(xkb_context_flags(0));
- if (mXkbContext) {
- mXkbMap = xkb_map_new_from_names(mXkbContext, &names, xkb_map_compile_flags(0));
- if (mXkbMap) {
- mXkbState = xkb_state_new(mXkbMap);
- }
- }
+bool QWaylandInputDevice::Keyboard::createDefaultKeyMap()
+{
+ if (mXkbContext && mXkbMap && mXkbState) {
+ return true;
+ }
- if (!mXkbContext || !mXkbMap || !mXkbState)
- qWarning() << "xkb_map_new_from_names failed, no key input";
-#endif
+ xkb_rule_names names;
+ names.rules = strdup("evdev");
+ names.model = strdup("pc105");
+ names.layout = strdup("us");
+ names.variant = strdup("");
+ names.options = strdup("");
+
+ mXkbContext = xkb_context_new(xkb_context_flags(0));
+ if (mXkbContext) {
+ mXkbMap = xkb_map_new_from_names(mXkbContext, &names, xkb_map_compile_flags(0));
+ if (mXkbMap) {
+ mXkbState = xkb_state_new(mXkbMap);
+ }
}
- ~Keyboard()
- {
-#ifndef QT_NO_WAYLAND_XKB
- if (mXkbState)
- xkb_state_unref(mXkbState);
- if (mXkbMap)
- xkb_map_unref(mXkbMap);
- if (mXkbContext)
- xkb_context_unref(mXkbContext);
-#endif
- wl_keyboard_destroy(object());
+
+ if (!mXkbContext || !mXkbMap || !mXkbState) {
+ qWarning() << "xkb_map_new_from_names failed, no key input";
+ return false;
}
+ return true;
+}
- void keyboard_keymap(uint32_t format,
- int32_t fd,
- uint32_t size) Q_DECL_OVERRIDE;
- void keyboard_enter(uint32_t time,
- struct wl_surface *surface,
- struct wl_array *keys) Q_DECL_OVERRIDE;
- void keyboard_leave(uint32_t time,
- struct wl_surface *surface) Q_DECL_OVERRIDE;
- void keyboard_key(uint32_t serial, uint32_t time,
- uint32_t key, uint32_t state) Q_DECL_OVERRIDE;
- void keyboard_modifiers(uint32_t serial,
- uint32_t mods_depressed,
- uint32_t mods_latched,
- uint32_t mods_locked,
- uint32_t group) Q_DECL_OVERRIDE;
-
- QWaylandInputDevice *mParent;
- QWaylandWindow *mFocus;
-#ifndef QT_NO_WAYLAND_XKB
- xkb_context *mXkbContext;
- xkb_keymap *mXkbMap;
- xkb_state *mXkbState;
+void QWaylandInputDevice::Keyboard::releaseKeyMap()
+{
+ if (mXkbState)
+ xkb_state_unref(mXkbState);
+ if (mXkbMap)
+ xkb_map_unref(mXkbMap);
+ if (mXkbContext)
+ xkb_context_unref(mXkbContext);
+}
#endif
- struct wl_callback *mFocusCallback;
- uint32_t mNativeModifiers;
- int mRepeatKey;
- uint32_t mRepeatCode;
- uint32_t mRepeatTime;
- QString mRepeatText;
+QWaylandInputDevice::Keyboard::~Keyboard()
+{
#ifndef QT_NO_WAYLAND_XKB
- xkb_keysym_t mRepeatSym;
+ releaseKeyMap();
#endif
+ wl_keyboard_destroy(object());
+}
- static const wl_callback_listener callback;
- static void focusCallback(void *data, struct wl_callback *callback, uint32_t time);
-};
+void QWaylandInputDevice::Keyboard::stopRepeat()
+{
+ mRepeatTimer.stop();
+}
-class QWaylandInputDevice::Pointer : public QtWayland::wl_pointer
+QWaylandInputDevice::Pointer::Pointer(QWaylandInputDevice *p)
+ : mParent(p)
+ , mFocus(0)
+ , mEnterSerial(0)
+ , mCursorSerial(0)
+ , mButtons(0)
{
-public:
- Pointer(QWaylandInputDevice *p)
- : mParent(p)
- , mFocus(0)
- , mEnterSerial(0)
- , mCursorSerial(0)
- , mButtons(0)
- {
- }
- ~Pointer()
- {
- wl_pointer_destroy(object());
- }
+}
- void pointer_enter(uint32_t serial, struct wl_surface *surface,
- wl_fixed_t sx, wl_fixed_t sy) Q_DECL_OVERRIDE;
- void pointer_leave(uint32_t time, struct wl_surface *surface);
- void pointer_motion(uint32_t time,
- wl_fixed_t sx, wl_fixed_t sy) Q_DECL_OVERRIDE;
- void pointer_button(uint32_t serial, uint32_t time,
- uint32_t button, uint32_t state) Q_DECL_OVERRIDE;
- void pointer_axis(uint32_t time,
- uint32_t axis,
- wl_fixed_t value) Q_DECL_OVERRIDE;
-
- QWaylandInputDevice *mParent;
- QWaylandWindow *mFocus;
- uint32_t mEnterSerial;
- uint32_t mCursorSerial;
- QPointF mSurfacePos;
- QPointF mGlobalPos;
- Qt::MouseButtons mButtons;
-};
+QWaylandInputDevice::Pointer::~Pointer()
+{
+ wl_pointer_destroy(object());
+}
-class QWaylandInputDevice::Touch : public QtWayland::wl_touch
+QWaylandInputDevice::Touch::Touch(QWaylandInputDevice *p)
+ : mParent(p)
+ , mFocus(0)
{
-public:
- Touch(QWaylandInputDevice *p)
- : mParent(p)
- , mFocus(0)
- {
- }
- ~Touch()
- {
- wl_touch_destroy(object());
- }
+}
- void touch_down(uint32_t serial,
- uint32_t time,
- struct wl_surface *surface,
- int32_t id,
- wl_fixed_t x,
- wl_fixed_t y) Q_DECL_OVERRIDE;
- void touch_up(uint32_t serial,
- uint32_t time,
- int32_t id) Q_DECL_OVERRIDE;
- void touch_motion(uint32_t time,
- int32_t id,
- wl_fixed_t x,
- wl_fixed_t y) Q_DECL_OVERRIDE;
- void touch_frame() Q_DECL_OVERRIDE;
- void touch_cancel() Q_DECL_OVERRIDE;
-
- bool allTouchPointsReleased();
-
- QWaylandInputDevice *mParent;
- QWaylandWindow *mFocus;
- QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
- QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints;
-};
+QWaylandInputDevice::Touch::~Touch()
+{
+ wl_touch_destroy(object());
+}
QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version, uint32_t id)
: QObject()
@@ -246,7 +175,6 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version,
mDataDevice = mQDisplay->dndSelectionHandler()->getDataDevice(this);
}
- connect(&mRepeatTimer, SIGNAL(timeout()), this, SLOT(repeatKey()));
}
QWaylandInputDevice::~QWaylandInputDevice()
@@ -261,16 +189,15 @@ void QWaylandInputDevice::seat_capabilities(uint32_t caps)
mCaps = caps;
if (caps & WL_SEAT_CAPABILITY_KEYBOARD && !mKeyboard) {
- mKeyboard = new Keyboard(this);
+ mKeyboard = createKeyboard(this);
mKeyboard->init(get_keyboard());
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && mKeyboard) {
delete mKeyboard;
mKeyboard = 0;
- mRepeatTimer.stop();
}
if (caps & WL_SEAT_CAPABILITY_POINTER && !mPointer) {
- mPointer = new Pointer(this);
+ mPointer = createPointer(this);
mPointer->init(get_pointer());
pointerSurface = mQDisplay->createSurface(this);
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && mPointer) {
@@ -279,7 +206,7 @@ void QWaylandInputDevice::seat_capabilities(uint32_t caps)
}
if (caps & WL_SEAT_CAPABILITY_TOUCH && !mTouch) {
- mTouch = new Touch(this);
+ mTouch = createTouch(this);
mTouch->init(get_touch());
if (!mTouchDevice) {
@@ -294,13 +221,28 @@ void QWaylandInputDevice::seat_capabilities(uint32_t caps)
}
}
+QWaylandInputDevice::Keyboard *QWaylandInputDevice::createKeyboard(QWaylandInputDevice *device)
+{
+ return new Keyboard(device);
+}
+
+QWaylandInputDevice::Pointer *QWaylandInputDevice::createPointer(QWaylandInputDevice *device)
+{
+ return new Pointer(device);
+}
+
+QWaylandInputDevice::Touch *QWaylandInputDevice::createTouch(QWaylandInputDevice *device)
+{
+ return new Touch(device);
+}
+
void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window)
{
if (mPointer && window == mPointer->mFocus)
mPointer->mFocus = 0;
if (mKeyboard && window == mKeyboard->mFocus) {
mKeyboard->mFocus = 0;
- mRepeatTimer.stop();
+ mKeyboard->stopRepeat();
}
}
@@ -341,20 +283,25 @@ Qt::KeyboardModifiers QWaylandInputDevice::modifiers() const
if (!mKeyboard)
return Qt::NoModifier;
+ return mKeyboard->modifiers();
+}
+
+Qt::KeyboardModifiers QWaylandInputDevice::Keyboard::modifiers() const
+{
Qt::KeyboardModifiers ret = Qt::NoModifier;
#ifndef QT_NO_WAYLAND_XKB
xkb_state_component cstate = static_cast<xkb_state_component>(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED);
- if (xkb_state_mod_name_is_active(mKeyboard->mXkbState, "Shift", cstate))
+ if (xkb_state_mod_name_is_active(mXkbState, "Shift", cstate))
ret |= Qt::ShiftModifier;
- if (xkb_state_mod_name_is_active(mKeyboard->mXkbState, "Control", cstate))
+ if (xkb_state_mod_name_is_active(mXkbState, "Control", cstate))
ret |= Qt::ControlModifier;
- if (xkb_state_mod_name_is_active(mKeyboard->mXkbState, "Alt", cstate))
+ if (xkb_state_mod_name_is_active(mXkbState, "Alt", cstate))
ret |= Qt::AltModifier;
- if (xkb_state_mod_name_is_active(mKeyboard->mXkbState, "Mod1", cstate))
+ if (xkb_state_mod_name_is_active(mXkbState, "Mod1", cstate))
ret |= Qt::AltModifier;
- if (xkb_state_mod_name_is_active(mKeyboard->mXkbState, "Mod4", cstate))
+ if (xkb_state_mod_name_is_active(mXkbState, "Mod4", cstate))
ret |= Qt::MetaModifier;
#endif
@@ -682,6 +629,11 @@ void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd,
return;
}
+ // Release the old keymap resources in the case they were already created in
+ // the key event or when the compositor issues a new map
+ releaseKeyMap();
+
+ mXkbContext = xkb_context_new(xkb_context_flags(0));
mXkbMap = xkb_map_new_from_string(mXkbContext, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, (xkb_keymap_compile_flags)0);
munmap(map_str, size);
close(fd);
@@ -731,7 +683,7 @@ void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surf
mFocusCallback = wl_display_sync(mParent->mDisplay);
wl_callback_add_listener(mFocusCallback, &QWaylandInputDevice::Keyboard::callback, this);
}
- mParent->mRepeatTimer.stop();
+ mRepeatTimer.stop();
}
const wl_callback_listener QWaylandInputDevice::Keyboard::callback = {
@@ -769,8 +721,9 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
}
#ifndef QT_NO_WAYLAND_XKB
- if (!mXkbMap)
+ if (!createDefaultKeyMap()) {
return;
+ }
const xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState, code);
xkb_state_update_key(mXkbState, code, isDown ? XKB_KEY_DOWN : XKB_KEY_UP);
@@ -807,38 +760,37 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
#ifndef QT_NO_WAYLAND_XKB
mRepeatSym = sym;
#endif
- mParent->mRepeatTimer.setInterval(400);
- mParent->mRepeatTimer.start();
+ mRepeatTimer.setInterval(400);
+ mRepeatTimer.start();
} else if (mRepeatCode == code) {
- mParent->mRepeatTimer.stop();
+ mRepeatTimer.stop();
}
}
-void QWaylandInputDevice::repeatKey()
+void QWaylandInputDevice::Keyboard::repeatKey()
{
mRepeatTimer.setInterval(25);
-
- QWindowSystemInterface::handleExtendedKeyEvent(mKeyboard->mFocus->window(),
- mKeyboard->mRepeatTime, QEvent::KeyRelease, mKeyboard->mRepeatKey,
+ QWindowSystemInterface::handleExtendedKeyEvent(mFocus->window(),
+ mRepeatTime, QEvent::KeyRelease, mRepeatKey,
modifiers(),
- mKeyboard->mRepeatCode,
+ mRepeatCode,
#ifndef QT_NO_WAYLAND_XKB
- mKeyboard->mRepeatSym, mKeyboard->mNativeModifiers,
+ mRepeatSym, mNativeModifiers,
#else
0, 0,
#endif
- mKeyboard->mRepeatText, true);
+ mRepeatText, true);
- QWindowSystemInterface::handleExtendedKeyEvent(mKeyboard->mFocus->window(),
- mKeyboard->mRepeatTime, QEvent::KeyPress, mKeyboard->mRepeatKey,
+ QWindowSystemInterface::handleExtendedKeyEvent(mFocus->window(),
+ mRepeatTime, QEvent::KeyPress, mRepeatKey,
modifiers(),
- mKeyboard->mRepeatCode,
+ mRepeatCode,
#ifndef QT_NO_WAYLAND_XKB
- mKeyboard->mRepeatSym, mKeyboard->mNativeModifiers,
+ mRepeatSym, mNativeModifiers,
#else
0, 0,
#endif
- mKeyboard->mRepeatText, true);
+ mRepeatText, true);
}
void QWaylandInputDevice::Keyboard::keyboard_modifiers(uint32_t serial,
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index 630640f87..f1c264545 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -56,15 +56,17 @@
#include <QtWaylandClient/private/qwayland-wayland.h>
#ifndef QT_NO_WAYLAND_XKB
-struct xkb_context;
-struct xkb_keymap;
-struct xkb_state;
+#include <xkbcommon/xkbcommon.h>
+#include <xkbcommon/xkbcommon-keysyms.h>
#endif
+#include <QtCore/QDebug>
+
struct wl_cursor_image;
QT_BEGIN_NAMESPACE
+
class QWaylandWindow;
class QWaylandDisplay;
class QWaylandDataDevice;
@@ -75,6 +77,10 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice
{
Q_OBJECT
public:
+ class Keyboard;
+ class Pointer;
+ class Touch;
+
QWaylandInputDevice(QWaylandDisplay *display, int version, uint32_t id);
~QWaylandInputDevice();
@@ -100,14 +106,11 @@ public:
uint32_t serial() const;
uint32_t cursorSerial() const;
-private slots:
- void repeatKey();
+ virtual Keyboard *createKeyboard(QWaylandInputDevice *device);
+ virtual Pointer *createPointer(QWaylandInputDevice *device);
+ virtual Touch *createTouch(QWaylandInputDevice *device);
private:
- class Keyboard;
- class Pointer;
- class Touch;
-
QWaylandDisplay *mQDisplay;
struct wl_display *mDisplay;
@@ -123,7 +126,6 @@ private:
uint32_t mTime;
uint32_t mSerial;
- QTimer mRepeatTimer;
void seat_capabilities(uint32_t caps) Q_DECL_OVERRIDE;
void handleTouchPoint(int id, double x, double y, Qt::TouchPointState state);
@@ -139,6 +141,127 @@ inline uint32_t QWaylandInputDevice::serial() const
return mSerial;
}
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice::Keyboard : public QObject, public QtWayland::wl_keyboard
+{
+ Q_OBJECT
+
+public:
+ Keyboard(QWaylandInputDevice *p);
+ virtual ~Keyboard();
+
+ void stopRepeat();
+
+ void keyboard_keymap(uint32_t format,
+ int32_t fd,
+ uint32_t size) Q_DECL_OVERRIDE;
+ void keyboard_enter(uint32_t time,
+ struct wl_surface *surface,
+ struct wl_array *keys) Q_DECL_OVERRIDE;
+ void keyboard_leave(uint32_t time,
+ struct wl_surface *surface) Q_DECL_OVERRIDE;
+ void keyboard_key(uint32_t serial, uint32_t time,
+ uint32_t key, uint32_t state) Q_DECL_OVERRIDE;
+ void keyboard_modifiers(uint32_t serial,
+ uint32_t mods_depressed,
+ uint32_t mods_latched,
+ uint32_t mods_locked,
+ uint32_t group) Q_DECL_OVERRIDE;
+
+ QWaylandInputDevice *mParent;
+ QWaylandWindow *mFocus;
+#ifndef QT_NO_WAYLAND_XKB
+ xkb_context *mXkbContext;
+ xkb_keymap *mXkbMap;
+ xkb_state *mXkbState;
+#endif
+ struct wl_callback *mFocusCallback;
+ uint32_t mNativeModifiers;
+
+ int mRepeatKey;
+ uint32_t mRepeatCode;
+ uint32_t mRepeatTime;
+ QString mRepeatText;
+#ifndef QT_NO_WAYLAND_XKB
+ xkb_keysym_t mRepeatSym;
+#endif
+ QTimer mRepeatTimer;
+
+ static const wl_callback_listener callback;
+ static void focusCallback(void *data, struct wl_callback *callback, uint32_t time);
+
+ Qt::KeyboardModifiers modifiers() const;
+
+private slots:
+ void repeatKey();
+
+private:
+#ifndef QT_NO_WAYLAND_XKB
+ bool createDefaultKeyMap();
+ void releaseKeyMap();
+#endif
+
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice::Pointer : public QtWayland::wl_pointer
+{
+
+public:
+ Pointer(QWaylandInputDevice *p);
+ virtual ~Pointer();
+
+ void pointer_enter(uint32_t serial, struct wl_surface *surface,
+ wl_fixed_t sx, wl_fixed_t sy) Q_DECL_OVERRIDE;
+ void pointer_leave(uint32_t time, struct wl_surface *surface);
+ void pointer_motion(uint32_t time,
+ wl_fixed_t sx, wl_fixed_t sy) Q_DECL_OVERRIDE;
+ void pointer_button(uint32_t serial, uint32_t time,
+ uint32_t button, uint32_t state) Q_DECL_OVERRIDE;
+ void pointer_axis(uint32_t time,
+ uint32_t axis,
+ wl_fixed_t value) Q_DECL_OVERRIDE;
+
+ QWaylandInputDevice *mParent;
+ QWaylandWindow *mFocus;
+ uint32_t mEnterSerial;
+ uint32_t mCursorSerial;
+ QPointF mSurfacePos;
+ QPointF mGlobalPos;
+ Qt::MouseButtons mButtons;
+};
+
+class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice::Touch : public QtWayland::wl_touch
+{
+public:
+ Touch(QWaylandInputDevice *p);
+ virtual ~Touch();
+
+ void touch_down(uint32_t serial,
+ uint32_t time,
+ struct wl_surface *surface,
+ int32_t id,
+ wl_fixed_t x,
+ wl_fixed_t y) Q_DECL_OVERRIDE;
+ void touch_up(uint32_t serial,
+ uint32_t time,
+ int32_t id) Q_DECL_OVERRIDE;
+ void touch_motion(uint32_t time,
+ int32_t id,
+ wl_fixed_t x,
+ wl_fixed_t y) Q_DECL_OVERRIDE;
+ void touch_frame() Q_DECL_OVERRIDE;
+ void touch_cancel() Q_DECL_OVERRIDE;
+
+ bool allTouchPointsReleased();
+
+ QWaylandInputDevice *mParent;
+ QWaylandWindow *mFocus;
+ QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
+ QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints;
+};
+
+
+
QT_END_NAMESPACE
#endif
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
index aa5a1cea8..27613eef7 100644
--- a/src/client/qwaylandintegration.cpp
+++ b/src/client/qwaylandintegration.cpp
@@ -43,6 +43,7 @@
#include "qwaylanddisplay_p.h"
#include "qwaylandshmwindow_p.h"
+#include "qwaylandinputdevice_p.h"
#include "qwaylandinputcontext_p.h"
#include "qwaylandshmbackingstore_p.h"
#include "qwaylandnativeinterface_p.h"
@@ -76,6 +77,9 @@
#include "qwaylandshellintegration_p.h"
#include "qwaylandshellintegrationfactory_p.h"
+#include "qwaylandinputdeviceintegration_p.h"
+#include "qwaylandinputdeviceintegrationfactory_p.h"
+
QT_BEGIN_NAMESPACE
class GenericWaylandTheme: public QGenericUnixTheme
@@ -113,6 +117,7 @@ public:
QWaylandIntegration::QWaylandIntegration()
: mClientBufferIntegration(0)
, mShellIntegration(Q_NULLPTR)
+ , mInputDeviceIntegration(Q_NULLPTR)
, mFontDb(new QGenericUnixFontDatabase())
, mNativeInterface(new QWaylandNativeInterface(this))
#ifndef QT_NO_ACCESSIBILITY
@@ -124,6 +129,7 @@ QWaylandIntegration::QWaylandIntegration()
, mServerBufferIntegrationInitialized(false)
, mShellIntegrationInitialized(false)
{
+ initializeInputDeviceIntegration();
mDisplay = new QWaylandDisplay(this);
mClipboard = new QWaylandClipboard(mDisplay);
mDrag = new QWaylandDrag(mDisplay);
@@ -363,4 +369,30 @@ void QWaylandIntegration::initializeShellIntegration()
}
}
+QWaylandInputDevice *QWaylandIntegration::createInputDevice(QWaylandDisplay *display, int version, uint32_t id)
+{
+ if (mInputDeviceIntegration) {
+ return mInputDeviceIntegration->createInputDevice(display, version, id);
+ }
+ return new QWaylandInputDevice(display, version, id);
+}
+
+void QWaylandIntegration::initializeInputDeviceIntegration()
+{
+ QByteArray integrationName = qgetenv("QT_WAYLAND_INPUTDEVICE_INTEGRATION");
+ QString targetKey = QString::fromLocal8Bit(integrationName);
+
+ if (targetKey.isEmpty()) {
+ return;
+ }
+
+ QStringList keys = QWaylandInputDeviceIntegrationFactory::keys();
+ if (keys.contains(targetKey)) {
+ mInputDeviceIntegration = QWaylandInputDeviceIntegrationFactory::create(targetKey, QStringList());
+ qDebug("Using the '%s' input device integration", qPrintable(targetKey));
+ } else {
+ qWarning("Wayland inputdevice integration '%s' not found, using default", qPrintable(targetKey));
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/client/qwaylandintegration_p.h b/src/client/qwaylandintegration_p.h
index 699702482..c0909418e 100644
--- a/src/client/qwaylandintegration_p.h
+++ b/src/client/qwaylandintegration_p.h
@@ -52,6 +52,8 @@ class QWaylandDisplay;
class QWaylandClientBufferIntegration;
class QWaylandServerBufferIntegration;
class QWaylandShellIntegration;
+class QWaylandInputDeviceIntegration;
+class QWaylandInputDevice;
class Q_WAYLAND_CLIENT_EXPORT QWaylandIntegration : public QPlatformIntegration
{
@@ -91,17 +93,24 @@ public:
QPlatformTheme *createPlatformTheme(const QString &name) const;
+ QWaylandInputDevice *createInputDevice(QWaylandDisplay *display, int version, uint32_t id);
+
virtual QWaylandClientBufferIntegration *clientBufferIntegration() const;
virtual QWaylandServerBufferIntegration *serverBufferIntegration() const;
virtual QWaylandShellIntegration *shellIntegration() const;
+
protected:
QWaylandClientBufferIntegration *mClientBufferIntegration;
QWaylandServerBufferIntegration *mServerBufferIntegration;
QWaylandShellIntegration *mShellIntegration;
+ QWaylandInputDeviceIntegration *mInputDeviceIntegration;
+
private:
void initializeClientBufferIntegration();
void initializeServerBufferIntegration();
void initializeShellIntegration();
+ void initializeInputDeviceIntegration();
+
QPlatformFontDatabase *mFontDb;
QPlatformClipboard *mClipboard;
QPlatformDrag *mDrag;
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 6c4a339f1..9f7bdda1f 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -91,6 +91,7 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
, mMouseDevice(0)
, mMouseSerial(0)
, mState(Qt::WindowNoState)
+ , mMask()
, mBackingStore(Q_NULLPTR)
{
init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this)));
@@ -128,6 +129,7 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
setOrientationMask(window->screen()->orientationUpdateMask());
setWindowFlags(window->flags());
setGeometry_helper(window->geometry());
+ setMask(window->mask());
setWindowStateInternal(window->windowState());
handleContentOrientationChange(window->contentOrientation());
}
@@ -271,6 +273,24 @@ void QWaylandWindow::lower()
mShellSurface->lower();
}
+void QWaylandWindow::setMask(const QRegion &mask)
+{
+ if (mMask == mask)
+ return;
+
+ mMask = mask;
+
+ if (mMask.isEmpty()) {
+ set_input_region(0);
+ } else {
+ struct ::wl_region *region = mDisplay->createRegion(mMask);
+ set_input_region(region);
+ wl_region_destroy(region);
+ }
+
+ commit();
+}
+
void QWaylandWindow::configure(uint32_t edges, int32_t width, int32_t height)
{
QMutexLocker resizeLocker(&mResizeLock);
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 6c32bc3ef..0c55cd88d 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -140,6 +140,8 @@ public:
void raise() Q_DECL_OVERRIDE;
void lower() Q_DECL_OVERRIDE;
+ void setMask(const QRegion &region) Q_DECL_OVERRIDE;
+
void requestActivateWindow() Q_DECL_OVERRIDE;
bool isExposed() const Q_DECL_OVERRIDE;
void unfocus();
@@ -224,6 +226,7 @@ protected:
int mMouseSerial;
Qt::WindowState mState;
+ QRegion mMask;
QWaylandShmBackingStore *mBackingStore;
diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri
index 2ef7231bf..bc46def80 100644
--- a/src/compositor/compositor_api/compositor_api.pri
+++ b/src/compositor/compositor_api/compositor_api.pri
@@ -2,6 +2,8 @@ INCLUDEPATH += compositor_api
HEADERS += \
compositor_api/qwaylandcompositor.h \
+ compositor_api/qwaylandcompositor_p.h \
+ compositor_api/qwaylandclient.h \
compositor_api/qwaylandsurface.h \
compositor_api/qwaylandsurface_p.h \
compositor_api/qwaylandinput.h \
@@ -14,6 +16,7 @@ HEADERS += \
SOURCES += \
compositor_api/qwaylandcompositor.cpp \
+ compositor_api/qwaylandclient.cpp \
compositor_api/qwaylandsurface.cpp \
compositor_api/qwaylandinput.cpp \
compositor_api/qwaylandinputpanel.cpp \
diff --git a/src/compositor/compositor_api/qwaylandclient.cpp b/src/compositor/compositor_api/qwaylandclient.cpp
new file mode 100644
index 000000000..e5567584e
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandclient.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Compositor.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qobject_p.h>
+
+#include "wayland_wrapper/qwlcompositor_p.h"
+#include "qwaylandcompositor.h"
+#include "qwaylandclient.h"
+
+#include <wayland-server.h>
+#include <wayland-util.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandClientPrivate : public QObjectPrivate
+{
+public:
+ QWaylandClientPrivate(wl_client *_client)
+ : client(_client)
+ {
+ // Save client credentials
+ wl_client_get_credentials(client, &pid, &uid, &gid);
+ }
+
+ ~QWaylandClientPrivate()
+ {
+ }
+
+ static void client_destroy_callback(wl_listener *listener, void *data)
+ {
+ Q_UNUSED(data);
+
+ QWaylandClient *client = reinterpret_cast<Listener *>(listener)->parent;
+ Q_ASSERT(client != 0);
+ QtWayland::Compositor::instance()->m_clients.removeOne(client);
+ delete client;
+ }
+
+ wl_client *client;
+
+ uid_t uid;
+ gid_t gid;
+ pid_t pid;
+
+ struct Listener {
+ wl_listener listener;
+ QWaylandClient *parent;
+ };
+ Listener listener;
+};
+
+QWaylandClient::QWaylandClient(wl_client *client)
+ : QObject(*new QWaylandClientPrivate(client))
+{
+ Q_D(QWaylandClient);
+
+ // Destroy wrapper when the client goes away
+ d->listener.parent = this;
+ d->listener.listener.notify = QWaylandClientPrivate::client_destroy_callback;
+ wl_client_add_destroy_listener(client, &d->listener.listener);
+}
+
+QWaylandClient::~QWaylandClient()
+{
+ Q_D(QWaylandClient);
+
+ // Remove listener from signal
+ wl_list_remove(&d->listener.listener.link);
+}
+
+QWaylandClient *QWaylandClient::fromWlClient(wl_client *wlClient)
+{
+ if (!wlClient)
+ return 0;
+
+ QWaylandClient *client = Q_NULLPTR;
+
+ wl_listener *l = wl_client_get_destroy_listener(wlClient,
+ QWaylandClientPrivate::client_destroy_callback);
+ if (l)
+ client = reinterpret_cast<QWaylandClientPrivate::Listener *>(
+ wl_container_of(l, (QWaylandClientPrivate::Listener *)0, listener))->parent;
+
+ if (!client) {
+ // The original idea was to create QWaylandClient instances when
+ // a client bound wl_compositor, but it's legal for a client to
+ // bind several times resulting in multiple QWaylandClient
+ // instances for the same wl_client therefore we create it from
+ // here on demand
+ client = new QWaylandClient(wlClient);
+ QtWayland::Compositor::instance()->m_clients.append(client);
+ }
+
+ return client;
+}
+
+wl_client *QWaylandClient::client() const
+{
+ Q_D(const QWaylandClient);
+
+ return d->client;
+}
+
+qint64 QWaylandClient::userId() const
+{
+ Q_D(const QWaylandClient);
+
+ return d->uid;
+}
+
+qint64 QWaylandClient::groupId() const
+{
+ Q_D(const QWaylandClient);
+
+ return d->gid;
+}
+
+qint64 QWaylandClient::processId() const
+{
+ Q_D(const QWaylandClient);
+
+ return d->pid;
+}
+
+void QWaylandClient::kill(int sig)
+{
+ Q_D(QWaylandClient);
+
+ ::kill(d->pid, sig);
+}
+
+void QWaylandClient::close()
+{
+ QtWayland::Compositor::instance()->waylandCompositor()->destroyClient(this);
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandclient.h b/src/compositor/compositor_api/qwaylandclient.h
new file mode 100644
index 000000000..ba6e3e274
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandclient.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Compositor.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDCLIENT_H
+#define QWAYLANDCLIENT_H
+
+#include <QtCompositor/qwaylandexport.h>
+
+#include <QObject>
+
+#include <signal.h>
+
+struct wl_client;
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandClientPrivate;
+
+class Q_COMPOSITOR_EXPORT QWaylandClient : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandClient)
+
+ Q_PROPERTY(qint64 userId READ userId CONSTANT)
+ Q_PROPERTY(qint64 groupId READ groupId CONSTANT)
+ Q_PROPERTY(qint64 processId READ processId CONSTANT)
+public:
+ ~QWaylandClient();
+
+ static QWaylandClient *fromWlClient(wl_client *wlClient);
+
+ wl_client *client() const;
+
+ qint64 userId() const;
+ qint64 groupId() const;
+
+ qint64 processId() const;
+
+ Q_INVOKABLE void kill(int sig = SIGTERM);
+
+public Q_SLOTS:
+ void close();
+
+private:
+ explicit QWaylandClient(wl_client *client);
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDCLIENT_H
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index 3248e4b1c..25ceb6e85 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -114,21 +114,19 @@ void QWaylandCompositor::destroyClientForSurface(QWaylandSurface *surface)
destroyClient(surface->client());
}
-void QWaylandCompositor::destroyClient(WaylandClient *client)
+void QWaylandCompositor::destroyClient(QWaylandClient *client)
{
m_compositor->destroyClient(client);
}
-QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(WaylandClient* c) const
+QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(QWaylandClient* client) const
{
- wl_client *client = static_cast<wl_client *>(c);
-
QList<QtWayland::Surface *> surfaces = m_compositor->surfaces();
QList<QWaylandSurface *> result;
for (int i = 0; i < surfaces.count(); ++i) {
- if (surfaces.at(i)->resource()->client() == client) {
+ if (surfaces.at(i)->waylandSurface()->client() == client) {
result.append(surfaces.at(i)->waylandSurface());
}
}
@@ -181,7 +179,7 @@ QPointF QWaylandCompositor::mapToView(QWaylandSurfaceView *surface, const QPoint
The default implementation simply forwards the request to QDesktopServices::openUrl().
*/
-bool QWaylandCompositor::openUrl(WaylandClient *client, const QUrl &url)
+bool QWaylandCompositor::openUrl(QWaylandClient *client, const QUrl &url)
{
Q_UNUSED(client);
return QDesktopServices::openUrl(url);
@@ -299,4 +297,9 @@ QWaylandSurfaceView *QWaylandCompositor::createView(QWaylandSurface *surface)
return new QWaylandSurfaceView(surface);
}
+QWaylandInputDevice *QWaylandCompositor::inputDeviceFor(QInputEvent *inputEvent)
+{
+ return m_compositor->inputDeviceFor(inputEvent);
+}
+
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h
index 740f2553d..2c73a1d3e 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.h
+++ b/src/compositor/compositor_api/qwaylandcompositor.h
@@ -51,9 +51,12 @@ struct wl_display;
QT_BEGIN_NAMESPACE
+class QInputEvent;
+
class QMimeData;
class QUrl;
class QOpenGLContext;
+class QWaylandClient;
class QWaylandSurface;
class QWaylandInputDevice;
class QWaylandInputPanel;
@@ -94,9 +97,9 @@ public:
void sendFrameCallbacks(QList<QWaylandSurface *> visibleSurfaces);
void destroyClientForSurface(QWaylandSurface *surface);
- void destroyClient(WaylandClient *client);
+ void destroyClient(QWaylandClient *client);
- QList<QWaylandSurface *> surfacesForClient(WaylandClient* client) const;
+ QList<QWaylandSurface *> surfacesForClient(QWaylandClient* client) const;
QList<QWaylandSurface *> surfaces() const;
QWindow *window()const;
@@ -107,7 +110,7 @@ public:
virtual QWaylandSurfaceView *pickView(const QPointF &globalPosition) const;
virtual QPointF mapToView(QWaylandSurfaceView *view, const QPointF &surfacePosition) const;
- virtual bool openUrl(WaylandClient *client, const QUrl &url);
+ virtual bool openUrl(QWaylandClient *client, const QUrl &url);
QtWayland::Compositor *handle() const;
@@ -148,6 +151,8 @@ public:
virtual QWaylandSurfaceView *createView(QWaylandSurface *surface);
+ QWaylandInputDevice *inputDeviceFor(QInputEvent *inputEvent);
+
protected:
QWaylandCompositor(QWindow *window, const char *socketName, QtWayland::Compositor *dptr);
virtual void retainedSelectionReceived(QMimeData *mimeData);
diff --git a/src/compositor/compositor_api/qwaylandinput.cpp b/src/compositor/compositor_api/qwaylandinput.cpp
index 97bbb23b3..76e365fb5 100644
--- a/src/compositor/compositor_api/qwaylandinput.cpp
+++ b/src/compositor/compositor_api/qwaylandinput.cpp
@@ -183,4 +183,10 @@ QWaylandInputDevice::CapabilityFlags QWaylandInputDevice::capabilities()
return d->capabilities();
}
+bool QWaylandInputDevice::isOwner(QInputEvent *inputEvent)
+{
+ Q_UNUSED(inputEvent);
+ return true;
+}
+
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandinput.h b/src/compositor/compositor_api/qwaylandinput.h
index 2c0b9ee7c..209228b97 100644
--- a/src/compositor/compositor_api/qwaylandinput.h
+++ b/src/compositor/compositor_api/qwaylandinput.h
@@ -54,6 +54,7 @@ class QWaylandSurface;
class QKeyEvent;
class QTouchEvent;
class QWaylandSurfaceView;
+class QInputEvent;
namespace QtWayland {
class InputDevice;
@@ -125,6 +126,8 @@ public:
QWaylandInputDevice::CapabilityFlags capabilities();
+ virtual bool isOwner(QInputEvent *inputEvent);
+
private:
QtWayland::InputDevice *d;
Q_DISABLE_COPY(QWaylandInputDevice)
diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
index ae472f219..1333100c6 100644
--- a/src/compositor/compositor_api/qwaylandquickcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
@@ -43,6 +43,7 @@
#include <QtCompositor/private/qwlcompositor_p.h>
+#include "qwaylandclient.h"
#include "qwaylandquickcompositor.h"
#include "qwaylandquicksurface.h"
#include "qwaylandsurfaceitem.h"
@@ -84,6 +85,7 @@ QWaylandQuickCompositor::QWaylandQuickCompositor(QQuickWindow *window, const cha
qmlRegisterUncreatableType<QWaylandSurfaceItem>("QtCompositor", 1, 0, "WaylandSurfaceItem", QObject::tr("Cannot create instance of WaylandSurfaceItem"));
qmlRegisterUncreatableType<QWaylandQuickSurface>("QtCompositor", 1, 0, "WaylandQuickSurface", QObject::tr("Cannot create instance of WaylandQuickSurface"));
+ qmlRegisterUncreatableType<QWaylandClient>("QtCompositor", 1, 0, "WaylandClient", QObject::tr("Cannot create instance of WaylandClient"));
}
QWaylandQuickCompositorPrivate *QWaylandQuickCompositor::d_ptr()
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp
index 205cea7a3..b5c38d88e 100644
--- a/src/compositor/compositor_api/qwaylandsurface.cpp
+++ b/src/compositor/compositor_api/qwaylandsurface.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
@@ -52,6 +53,7 @@
#include "wayland_wrapper/qwldatadevicemanager_p.h"
#include "qwaylandcompositor.h"
+#include "qwaylandclient.h"
#include "qwaylandsurface_p.h"
#include "qwaylandbufferref.h"
#include "qwaylandsurfaceinterface.h"
@@ -61,10 +63,11 @@
QT_BEGIN_NAMESPACE
-QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *client, quint32 id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface)
- : QtWayland::Surface(client, id, version, compositor, surface)
+QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface)
+ : QtWayland::Surface(wlClient, id, version, compositor, surface)
, closing(false)
, refCount(1)
+ , client(QWaylandClient::fromWlClient(wlClient))
, windowType(QWaylandSurface::WindowType::None)
{}
@@ -89,10 +92,13 @@ QWaylandSurface::~QWaylandSurface()
delete d->m_attacher;
}
-WaylandClient *QWaylandSurface::client() const
+QWaylandClient *QWaylandSurface::client() const
{
Q_D(const QWaylandSurface);
- return d->resource()->client();
+
+ if (!d->compositor()->clients().contains(d->client))
+ return Q_NULLPTR;
+ return d->client;
}
QWaylandSurface *QWaylandSurface::parentSurface() const
@@ -210,18 +216,6 @@ QtWayland::Surface * QWaylandSurface::handle()
return d;
}
-qint64 QWaylandSurface::processId() const
-{
- Q_D(const QWaylandSurface);
- if (d->isDestroyed())
- return -1;
-
- struct wl_client *client = static_cast<struct wl_client *>(this->client());
- pid_t pid;
- wl_client_get_credentials(client,&pid, 0,0);
- return pid;
-}
-
QVariantMap QWaylandSurface::windowProperties() const
{
Q_D(const QWaylandSurface);
@@ -319,6 +313,12 @@ bool QWaylandSurface::transientInactive() const
return d->transientInactive();
}
+bool QWaylandSurface::inputRegionContains(const QPoint &p) const
+{
+ Q_D(const QWaylandSurface);
+ return d->inputRegion().contains(p);
+}
+
void QWaylandSurface::destroy()
{
Q_D(QWaylandSurface);
diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h
index 7c7ec4d76..4b802d778 100644
--- a/src/compositor/compositor_api/qwaylandsurface.h
+++ b/src/compositor/compositor_api/qwaylandsurface.h
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
@@ -54,6 +55,7 @@ struct wl_resource;
QT_BEGIN_NAMESPACE
class QTouchEvent;
+class QWaylandClient;
class QWaylandSurfacePrivate;
class QWaylandCompositor;
class QWaylandBufferRef;
@@ -82,6 +84,7 @@ class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QWaylandSurface)
+ Q_PROPERTY(QWaylandClient *client READ client CONSTANT)
Q_PROPERTY(QSize size READ size NOTIFY sizeChanged)
Q_PROPERTY(QWaylandSurface::WindowFlags windowFlags READ windowFlags NOTIFY windowFlagsChanged)
Q_PROPERTY(QWaylandSurface::WindowType windowType READ windowType NOTIFY windowTypeChanged)
@@ -120,7 +123,7 @@ public:
QWaylandSurface(wl_client *client, quint32 id, int version, QWaylandCompositor *compositor);
virtual ~QWaylandSurface();
- WaylandClient *client() const;
+ QWaylandClient *client() const;
QWaylandSurface *parentSurface() const;
QLinkedList<QWaylandSurface *> subSurfaces() const;
@@ -153,7 +156,6 @@ public:
QtWayland::Surface *handle();
- qint64 processId() const;
QByteArray authenticationToken() const;
QVariantMap windowProperties() const;
void setWindowProperty(const QString &name, const QVariant &value);
@@ -168,6 +170,8 @@ public:
bool transientInactive() const;
+ bool inputRegionContains(const QPoint &p) const;
+
Q_INVOKABLE void destroy();
Q_INVOKABLE void destroySurface();
Q_INVOKABLE void ping();
diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h
index 5e2188883..2e6f75a64 100644
--- a/src/compositor/compositor_api/qwaylandsurface_p.h
+++ b/src/compositor/compositor_api/qwaylandsurface_p.h
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
** Contact: http://www.qt-project.org/legal
**
@@ -58,13 +59,16 @@ class Q_COMPOSITOR_EXPORT QWaylandSurfacePrivate : public QObjectPrivate, public
{
Q_DECLARE_PUBLIC(QWaylandSurface)
public:
- QWaylandSurfacePrivate(wl_client *client, quint32 id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface);
+ QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface);
void setType(QWaylandSurface::WindowType type);
void setTitle(const QString &title);
void setClassName(const QString &className);
bool closing;
int refCount;
+
+ QWaylandClient *client;
+
QWaylandSurface::WindowType windowType;
QList<QWaylandSurfaceView *> views;
QList<QWaylandSurfaceInterface *> interfaces;
diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp
index cf9880b58..79afa3786 100644
--- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp
+++ b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp
@@ -144,7 +144,12 @@ void QWaylandSurfaceItem::mousePressEvent(QMouseEvent *event)
if (!surface())
return;
- QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice();
+ if (!surface()->inputRegionContains(event->pos())) {
+ event->ignore();
+ return;
+ }
+
+ QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event);
if (inputDevice->mouseFocus() != this)
inputDevice->setMouseFocus(this, event->localPos(), event->windowPos());
inputDevice->sendMousePressEvent(event->button(), event->localPos(), event->windowPos());
@@ -153,7 +158,7 @@ void QWaylandSurfaceItem::mousePressEvent(QMouseEvent *event)
void QWaylandSurfaceItem::mouseMoveEvent(QMouseEvent *event)
{
if (surface()) {
- QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice();
+ QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event);
inputDevice->sendMouseMoveEvent(this, event->localPos(), event->windowPos());
}
}
@@ -161,7 +166,7 @@ void QWaylandSurfaceItem::mouseMoveEvent(QMouseEvent *event)
void QWaylandSurfaceItem::mouseReleaseEvent(QMouseEvent *event)
{
if (surface()) {
- QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice();
+ QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event);
inputDevice->sendMouseReleaseEvent(event->button(), event->localPos(), event->windowPos());
}
}
@@ -169,7 +174,7 @@ void QWaylandSurfaceItem::mouseReleaseEvent(QMouseEvent *event)
void QWaylandSurfaceItem::hoverEnterEvent(QHoverEvent *event)
{
if (surface()) {
- QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice();
+ QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event);
inputDevice->sendMouseMoveEvent(this, event->pos());
}
}
@@ -177,7 +182,7 @@ void QWaylandSurfaceItem::hoverEnterEvent(QHoverEvent *event)
void QWaylandSurfaceItem::hoverMoveEvent(QHoverEvent *event)
{
if (surface()) {
- QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice();
+ QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event);
inputDevice->sendMouseMoveEvent(this, event->pos());
}
}
@@ -185,7 +190,7 @@ void QWaylandSurfaceItem::hoverMoveEvent(QHoverEvent *event)
void QWaylandSurfaceItem::hoverLeaveEvent(QHoverEvent *event)
{
if (surface()) {
- QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice();
+ QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event);
inputDevice->sendMouseMoveEvent(this, event->pos());
}
}
@@ -193,7 +198,12 @@ void QWaylandSurfaceItem::hoverLeaveEvent(QHoverEvent *event)
void QWaylandSurfaceItem::wheelEvent(QWheelEvent *event)
{
if (surface()) {
- QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice();
+ if (!surface()->inputRegionContains(event->pos())) {
+ event->ignore();
+ return;
+ }
+
+ QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event);
inputDevice->sendMouseWheelEvent(event->orientation(), event->delta());
}
}
@@ -201,7 +211,7 @@ void QWaylandSurfaceItem::wheelEvent(QWheelEvent *event)
void QWaylandSurfaceItem::keyPressEvent(QKeyEvent *event)
{
if (surface()) {
- QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice();
+ QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event);
inputDevice->sendFullKeyEvent(event);
}
}
@@ -209,7 +219,7 @@ void QWaylandSurfaceItem::keyPressEvent(QKeyEvent *event)
void QWaylandSurfaceItem::keyReleaseEvent(QKeyEvent *event)
{
if (surface() && hasFocus()) {
- QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice();
+ QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event);
inputDevice->sendFullKeyEvent(event);
}
}
@@ -217,13 +227,20 @@ void QWaylandSurfaceItem::keyReleaseEvent(QKeyEvent *event)
void QWaylandSurfaceItem::touchEvent(QTouchEvent *event)
{
if (m_touchEventsEnabled) {
- QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice();
+ QWaylandInputDevice *inputDevice = compositor()->inputDeviceFor(event);
+
+ QPoint pointPos;
+ const QList<QTouchEvent::TouchPoint> &points = event->touchPoints();
+ if (!points.isEmpty())
+ pointPos = points.at(0).pos().toPoint();
+
+ if (event->type() == QEvent::TouchBegin && !surface()->inputRegionContains(pointPos)) {
+ event->ignore();
+ return;
+ }
+
event->accept();
if (inputDevice->mouseFocus() != this) {
- QPoint pointPos;
- QList<QTouchEvent::TouchPoint> points = event->touchPoints();
- if (!points.isEmpty())
- pointPos = points.at(0).pos().toPoint();
inputDevice->setMouseFocus(this, pointPos, pointPos);
}
inputDevice->sendFullTouchEvent(event);
@@ -232,15 +249,18 @@ void QWaylandSurfaceItem::touchEvent(QTouchEvent *event)
}
}
-void QWaylandSurfaceItem::takeFocus()
+void QWaylandSurfaceItem::takeFocus(QWaylandInputDevice *device)
{
setFocus(true);
if (!surface())
return;
- QWaylandInputDevice *inputDevice = compositor()->defaultInputDevice();
- inputDevice->setKeyboardFocus(surface());
+ QWaylandInputDevice *target = device;
+ if (!target) {
+ target = compositor()->defaultInputDevice();
+ }
+ target->setKeyboardFocus(surface());
}
void QWaylandSurfaceItem::surfaceMapped()
diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.h b/src/compositor/compositor_api/qwaylandsurfaceitem.h
index 58dc4d871..fb70705b2 100644
--- a/src/compositor/compositor_api/qwaylandsurfaceitem.h
+++ b/src/compositor/compositor_api/qwaylandsurfaceitem.h
@@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE
class QWaylandSurfaceTextureProvider;
class QMutex;
+class QWaylandInputDevice;
class Q_COMPOSITOR_EXPORT QWaylandSurfaceItem : public QQuickItem, public QWaylandSurfaceView
{
@@ -101,7 +102,7 @@ protected:
void touchEvent(QTouchEvent *event);
public slots:
- void takeFocus();
+ virtual void takeFocus(QWaylandInputDevice *device = 0);
void setPaintEnabled(bool paintEnabled);
private slots:
diff --git a/src/compositor/global/qwaylandexport.h b/src/compositor/global/qwaylandexport.h
index 45ddc159d..2812d433d 100644
--- a/src/compositor/global/qwaylandexport.h
+++ b/src/compositor/global/qwaylandexport.h
@@ -55,8 +55,6 @@ QT_BEGIN_NAMESPACE
# endif
#endif
-typedef void WaylandClient;
-
QT_END_NAMESPACE
#endif //WAYLANDEXPORT_H
diff --git a/src/compositor/wayland_wrapper/qwlcompositor.cpp b/src/compositor/wayland_wrapper/qwlcompositor.cpp
index faf32dc57..91fd1818a 100644
--- a/src/compositor/wayland_wrapper/qwlcompositor.cpp
+++ b/src/compositor/wayland_wrapper/qwlcompositor.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
@@ -44,6 +45,7 @@
#include "qwldisplay_p.h"
#include "qwloutput_p.h"
#include "qwlsurface_p.h"
+#include "qwaylandclient.h"
#include "qwaylandcompositor.h"
#include "qwldatadevicemanager_p.h"
#include "qwldatadevice_p.h"
@@ -107,7 +109,6 @@ Compositor *Compositor::instance()
Compositor::Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::ExtensionFlags extensions)
: m_extensions(extensions)
, m_display(new Display)
- , m_default_input_device(0)
, m_current_frame(0)
, m_last_queued_buf(-1)
, m_qt_compositor(qt_compositor)
@@ -163,6 +164,7 @@ void Compositor::init()
connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processWaylandEvents()));
qRegisterMetaType<SurfaceBuffer*>("SurfaceBuffer*");
+ qRegisterMetaType<QWaylandClient*>("WaylandClient*");
qRegisterMetaType<QWaylandSurface*>("WaylandSurface*");
qRegisterMetaType<QWaylandSurfaceView*>("WaylandSurfaceView*");
//initialize distancefieldglyphcache here
@@ -176,6 +178,8 @@ Compositor::~Compositor()
{
if (!m_destroyed_surfaces.isEmpty())
qWarning("QWaylandCompositor::cleanupGraphicsResources() must be called manually");
+ qDeleteAll(m_clients);
+
delete m_outputExtension;
delete m_surfaceExtension;
@@ -183,6 +187,7 @@ Compositor::~Compositor()
delete m_touchExtension;
delete m_qtkeyExtension;
+ removeInputDevice(m_default_wayland_input_device);
delete m_default_wayland_input_device;
delete m_data_device_manager;
@@ -221,6 +226,16 @@ void Compositor::destroySurface(Surface *surface)
m_destroyed_surfaces << surface->waylandSurface();
}
+void Compositor::resetInputDevice(Surface *surface)
+{
+ foreach (QWaylandInputDevice *dev, m_inputDevices) {
+ if (dev->keyboardFocus() == surface->waylandSurface())
+ dev->setKeyboardFocus(0);
+ if (dev->mouseFocus() && dev->mouseFocus()->surface() == surface->waylandSurface())
+ dev->setMouseFocus(0, QPointF(), QPointF());
+ }
+}
+
void Compositor::cleanupGraphicsResources()
{
qDeleteAll(m_destroyed_surfaces);
@@ -241,16 +256,15 @@ void Compositor::compositor_create_region(Resource *resource, uint32_t id)
new Region(resource->client(), id);
}
-void Compositor::destroyClient(WaylandClient *c)
+void Compositor::destroyClient(QWaylandClient *client)
{
- wl_client *client = static_cast<wl_client *>(c);
if (!client)
return;
if (m_windowManagerIntegration)
- m_windowManagerIntegration->sendQuitMessage(client);
+ m_windowManagerIntegration->sendQuitMessage(client->client());
- wl_client_destroy(client);
+ wl_client_destroy(client->client());
}
QWindow *Compositor::window() const
@@ -319,18 +333,12 @@ void Compositor::initializeExtensions()
void Compositor::initializeDefaultInputDevice()
{
m_default_wayland_input_device = new QWaylandInputDevice(m_qt_compositor);
- m_default_input_device = m_default_wayland_input_device->handle();
+ registerInputDevice(m_default_wayland_input_device);
}
-QList<struct wl_client *> Compositor::clients() const
+QList<QWaylandClient *> Compositor::clients() const
{
- QList<struct wl_client *> list;
- foreach (Surface *surface, m_surfaces) {
- struct wl_client *client = surface->resource()->client();
- if (!list.contains(client))
- list.append(client);
- }
- return list;
+ return m_clients;
}
void Compositor::setScreenOrientation(Qt::ScreenOrientation orientation)
@@ -383,7 +391,8 @@ QWaylandCompositor::ExtensionFlags Compositor::extensions() const
InputDevice* Compositor::defaultInputDevice()
{
- return m_default_input_device;
+ // The list gets prepended so that default is the last element
+ return m_inputDevices.last()->handle();
}
QList<QtWayland::Surface *> Compositor::surfacesForClient(wl_client *client)
@@ -501,6 +510,32 @@ void Compositor::loadServerBufferIntegration()
}
}
+void Compositor::registerInputDevice(QWaylandInputDevice *device)
+{
+ // The devices get prepended as the first input device that gets added
+ // is assumed to be the default and it will claim to accept all the input
+ // events if asked
+ m_inputDevices.prepend(device);
+}
+
+void Compositor::removeInputDevice(QWaylandInputDevice *device)
+{
+ m_inputDevices.removeOne(device);
+}
+
+QWaylandInputDevice *Compositor::inputDeviceFor(QInputEvent *inputEvent)
+{
+ QWaylandInputDevice *dev = NULL;
+ for (int i = 0; i < m_inputDevices.size(); i++) {
+ QWaylandInputDevice *candidate = m_inputDevices.at(i);
+ if (candidate->isOwner(inputEvent)) {
+ dev = candidate;
+ break;
+ }
+ }
+ return dev;
+}
+
} // namespace Wayland
QT_END_NAMESPACE
diff --git a/src/compositor/wayland_wrapper/qwlcompositor_p.h b/src/compositor/wayland_wrapper/qwlcompositor_p.h
index 599f79b6d..9c3a0f9de 100644
--- a/src/compositor/wayland_wrapper/qwlcompositor_p.h
+++ b/src/compositor/wayland_wrapper/qwlcompositor_p.h
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
@@ -56,6 +57,10 @@
QT_BEGIN_NAMESPACE
+class QWaylandClient;
+class QWaylandClientPrivate;
+class QInputEvent;
+
class QWaylandCompositor;
class QWaylandInputDevice;
class WindowManagerServerIntegration;
@@ -93,11 +98,16 @@ public:
void sendFrameCallbacks(QList<QWaylandSurface *> visibleSurfaces);
void frameFinished(Surface *surface = 0);
- InputDevice *defaultInputDevice(); //we just have 1 default device for now (since QPA doesn't give us anything else)
+ InputDevice *defaultInputDevice();
+
+ void registerInputDevice(QWaylandInputDevice *device);
+ QList<QWaylandInputDevice *> inputDevices() const { return m_inputDevices; }
+ QWaylandInputDevice *inputDeviceFor(QInputEvent *inputEvent);
+ void removeInputDevice(QWaylandInputDevice *device);
void destroySurface(Surface *surface);
- void destroyClient(WaylandClient *client);
+ void destroyClient(QWaylandClient *client);
uint currentTimeMsecs() const;
@@ -119,7 +129,7 @@ public:
static Compositor *instance();
- QList<struct wl_client *> clients() const;
+ QList<QWaylandClient *> clients() const;
WindowManagerServerIntegration *windowManagerIntegration() const { return m_windowManagerIntegration; }
@@ -153,6 +163,8 @@ public:
void feedRetainedSelectionData(QMimeData *data);
static void bindGlobal(wl_client *client, void *data, uint32_t version, uint32_t id);
+ void resetInputDevice(Surface *surface);
+
public slots:
void cleanupGraphicsResources();
@@ -173,7 +185,8 @@ protected:
/* Input */
QWaylandInputDevice *m_default_wayland_input_device;
- InputDevice *m_default_input_device;
+
+ QList<QWaylandInputDevice *> m_inputDevices;
/* Output */
//make this a list of the available screens
@@ -193,6 +206,7 @@ protected:
QWaylandCompositor *m_qt_compositor;
Qt::ScreenOrientation m_orientation;
+ QList<QWaylandClient *> m_clients;
#ifdef QT_COMPOSITOR_WAYLAND_GL
QScopedPointer<HardwareIntegration> m_hw_integration;
@@ -218,6 +232,8 @@ protected:
bool m_retainSelection;
friend class QT_PREPEND_NAMESPACE(QWaylandCompositor);
+ friend class QT_PREPEND_NAMESPACE(QWaylandClient);
+ friend class QT_PREPEND_NAMESPACE(QWaylandClientPrivate);
};
}
diff --git a/src/compositor/wayland_wrapper/qwlsurface.cpp b/src/compositor/wayland_wrapper/qwlsurface.cpp
index 5cd8bb506..ee8197013 100644
--- a/src/compositor/wayland_wrapper/qwlsurface.cpp
+++ b/src/compositor/wayland_wrapper/qwlsurface.cpp
@@ -104,6 +104,11 @@ public:
bool canSend;
};
+static QRegion infiniteRegion() {
+ return QRegion(QRect(QPoint(std::numeric_limits<int>::min(), std::numeric_limits<int>::min()),
+ QPoint(std::numeric_limits<int>::max(), std::numeric_limits<int>::max())));
+}
+
Surface::Surface(struct wl_client *client, uint32_t id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface)
: QtWaylandServer::wl_surface(client, id, version)
, m_compositor(compositor->handle())
@@ -114,6 +119,7 @@ Surface::Surface(struct wl_client *client, uint32_t id, int version, QWaylandCom
, m_extendedSurface(0)
, m_subSurface(0)
, m_inputPanelSurface(0)
+ , m_inputRegion(infiniteRegion())
, m_transientParent(0)
, m_transientInactive(false)
, m_transientOffset(QPointF(0, 0))
@@ -124,6 +130,7 @@ Surface::Surface(struct wl_client *client, uint32_t id, int version, QWaylandCom
{
m_pending.buffer = 0;
m_pending.newlyAttached = false;
+ m_pending.inputRegion = infiniteRegion();
}
Surface::~Surface()
@@ -190,7 +197,6 @@ void Surface::setSize(const QSize &size)
{
if (size != m_size) {
m_opaqueRegion = QRegion();
- m_inputRegion = QRegion(QRect(QPoint(), size));
m_size = size;
m_waylandSurface->sizeChanged();
}
@@ -288,11 +294,7 @@ void Surface::setBackBuffer(SurfaceBuffer *buffer)
m_damage = m_damage.intersected(QRect(QPoint(), m_size));
emit m_waylandSurface->damaged(m_damage);
} else {
- InputDevice *inputDevice = m_compositor->defaultInputDevice();
- if (inputDevice->keyboardFocus() == this)
- inputDevice->setKeyboardFocus(0);
- if (inputDevice->mouseFocus() && inputDevice->mouseFocus()->surface() == waylandSurface())
- inputDevice->setMouseFocus(0, QPointF(), QPointF());
+ m_compositor->resetInputDevice(this);
}
m_damage = QRegion();
}
@@ -379,7 +381,11 @@ void Surface::surface_set_opaque_region(Resource *, struct wl_resource *region)
void Surface::surface_set_input_region(Resource *, struct wl_resource *region)
{
- m_inputRegion = region ? Region::fromResource(region)->region() : QRegion(QRect(QPoint(), size()));
+ if (region) {
+ m_pending.inputRegion = Region::fromResource(region)->region();
+ } else {
+ m_pending.inputRegion = infiniteRegion();
+ }
}
void Surface::surface_commit(Resource *)
@@ -406,6 +412,8 @@ void Surface::surface_commit(Resource *)
m_frameCallbacks << m_pendingFrameCallbacks;
m_pendingFrameCallbacks.clear();
+ m_inputRegion = m_pending.inputRegion.intersected(QRect(QPoint(), m_size));
+
emit m_waylandSurface->redraw();
}
diff --git a/src/compositor/wayland_wrapper/qwlsurface_p.h b/src/compositor/wayland_wrapper/qwlsurface_p.h
index 5a3c4be3d..bbab57a4d 100644
--- a/src/compositor/wayland_wrapper/qwlsurface_p.h
+++ b/src/compositor/wayland_wrapper/qwlsurface_p.h
@@ -171,6 +171,7 @@ protected:
QRegion damage;
QPoint offset;
bool newlyAttached;
+ QRegion inputRegion;
} m_pending;
QPoint m_lastLocalMousePos;
diff --git a/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp
index 5387854a4..150a04e5b 100644
--- a/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp
+++ b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp
@@ -43,6 +43,7 @@
#include <wayland_wrapper/qwldisplay_p.h>
#include <wayland_wrapper/qwlcompositor_p.h>
+#include <compositor_api/qwaylandclient.h>
#include <compositor_api/qwaylandcompositor.h>
#include <wayland-server.h>
@@ -104,7 +105,7 @@ void WindowManagerServerIntegration::windowmanager_open_url(Resource *resource,
m_urls.insert(resource, url);
else {
m_urls.remove(resource);
- m_compositor->openUrl(resource->client(), QUrl(url));
+ m_compositor->openUrl(QWaylandClient::fromWlClient(resource->client()), QUrl(url));
}
}
diff --git a/tests/auto/compositor/compositor.pro b/tests/auto/compositor/compositor.pro
index d173d2ed6..035beeb41 100644
--- a/tests/auto/compositor/compositor.pro
+++ b/tests/auto/compositor/compositor.pro
@@ -24,7 +24,11 @@ SOURCES += tst_compositor.cpp \
testcompositor.cpp \
testkeyboardgrabber.cpp \
mockclient.cpp \
+ mockseat.cpp \
+ testinputdevice.cpp
HEADERS += testcompositor.h \
testkeyboardgrabber.h \
mockclient.h \
+ mockseat.h \
+ testinputdevice.h
diff --git a/tests/auto/compositor/mockclient.cpp b/tests/auto/compositor/mockclient.cpp
index 9bbe56519..8f2bbbc6d 100644
--- a/tests/auto/compositor/mockclient.cpp
+++ b/tests/auto/compositor/mockclient.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "mockclient.h"
+#include "mockseat.h"
#include <QElapsedTimer>
#include <QSocketNotifier>
@@ -145,6 +146,9 @@ void MockClient::handleGlobal(uint32_t id, const QByteArray &interface)
shm = static_cast<wl_shm *>(wl_registry_bind(registry, id, &wl_shm_interface, 1));
} else if (interface == "wl_shell") {
wlshell = static_cast<wl_shell *>(wl_registry_bind(registry, id, &wl_shell_interface, 1));
+ } else if (interface == "wl_seat") {
+ wl_seat *s = static_cast<wl_seat *>(wl_registry_bind(registry, id, &wl_seat_interface, 1));
+ m_seats << new MockSeat(s);
}
}
diff --git a/tests/auto/compositor/mockclient.h b/tests/auto/compositor/mockclient.h
index de1084ab9..04c5dc831 100644
--- a/tests/auto/compositor/mockclient.h
+++ b/tests/auto/compositor/mockclient.h
@@ -44,6 +44,9 @@
#include <QObject>
#include <QImage>
#include <QRect>
+#include <QList>
+
+class MockSeat;
class ShmBuffer
{
@@ -74,6 +77,8 @@ public:
wl_registry *registry;
wl_shell *wlshell;
+ QList<MockSeat *> m_seats;
+
QRect geometry;
int fd;
diff --git a/tests/auto/compositor/mockseat.cpp b/tests/auto/compositor/mockseat.cpp
new file mode 100644
index 000000000..ff6e449dd
--- /dev/null
+++ b/tests/auto/compositor/mockseat.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 LG Electronics Ltd., author: <mikko.levonmaa@lge.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mockseat.h"
+
+MockSeat::MockSeat(wl_seat *seat)
+ : m_seat(seat)
+{
+ // Bind to the keyboard interface so that the compositor has
+ // the right resource associations
+ m_keyboard = wl_seat_get_keyboard(seat);
+}
+
+MockSeat::~MockSeat()
+{
+ wl_keyboard_destroy(m_keyboard);
+ wl_seat_destroy(m_seat);
+}
diff --git a/tests/auto/compositor/mockseat.h b/tests/auto/compositor/mockseat.h
new file mode 100644
index 000000000..19b777619
--- /dev/null
+++ b/tests/auto/compositor/mockseat.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 LG Electronics Ltd., author: <mikko.levonmaa@lge.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef MOCKSEAT
+#define MOCKSEAT
+
+#include <QObject>
+#include <wayland-client.h>
+
+class MockSeat : public QObject
+{
+ Q_OBJECT
+
+public:
+ MockSeat(wl_seat *seat);
+ ~MockSeat();
+
+ wl_seat *m_seat;
+ wl_keyboard *m_keyboard;
+};
+#endif
diff --git a/tests/auto/compositor/testinputdevice.cpp b/tests/auto/compositor/testinputdevice.cpp
new file mode 100644
index 000000000..627578514
--- /dev/null
+++ b/tests/auto/compositor/testinputdevice.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 LG Electronics, Inc., author: <mikko.levonmaa@lge.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "testinputdevice.h"
+
+#include <QMouseEvent>
+
+TestInputDevice::TestInputDevice(QWaylandCompositor *compositor, QWaylandInputDevice::CapabilityFlags caps)
+ : QWaylandInputDevice(compositor, caps)
+{
+ m_queryCount = 0;
+}
+
+TestInputDevice::~TestInputDevice()
+{
+}
+
+bool TestInputDevice::isOwner(QInputEvent *event)
+{
+ m_queryCount++;
+ QMouseEvent *me = dynamic_cast<QMouseEvent *>(event);
+ return m_events.contains(me);
+}
+
+QList<QMouseEvent *> TestInputDevice::createMouseEvents(int count)
+{
+ for (int i = 0; i < count; i++) {
+ m_events.append(new QMouseEvent(QEvent::MouseMove, QPointF(10 + i, 10 + i), Qt::NoButton, Qt::NoButton, Qt::NoModifier));
+ }
+ return m_events;
+}
+
diff --git a/tests/auto/compositor/testinputdevice.h b/tests/auto/compositor/testinputdevice.h
new file mode 100644
index 000000000..cc930843a
--- /dev/null
+++ b/tests/auto/compositor/testinputdevice.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 LG Electronics, Inc., author: <mikko.levonmaa@lge.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QWaylandInputDevice>
+#include <QList>
+
+class QInputEvent;
+class QMouseEvent;
+
+class TestInputDevice : public QWaylandInputDevice
+{
+
+public:
+
+ TestInputDevice(QWaylandCompositor *compositor, QWaylandInputDevice::CapabilityFlags caps);
+ ~TestInputDevice();
+
+ bool isOwner(QInputEvent *event);
+
+ QList<QMouseEvent *> createMouseEvents(int count);
+
+ int queryCount() { return m_queryCount; }
+
+private:
+ int m_queryCount;
+ QList<QMouseEvent *> m_events;
+};
diff --git a/tests/auto/compositor/tst_compositor.cpp b/tests/auto/compositor/tst_compositor.cpp
index e97d3b16d..2e404a79d 100644
--- a/tests/auto/compositor/tst_compositor.cpp
+++ b/tests/auto/compositor/tst_compositor.cpp
@@ -45,6 +45,8 @@
#include "QtCompositor/private/qwlkeyboard_p.h"
#include "QtCompositor/private/qwlinputdevice_p.h"
+#include "QtCompositor/private/qwlcompositor_p.h"
+#include "testinputdevice.h"
#include "qwaylandbufferref.h"
@@ -64,6 +66,8 @@ public:
private slots:
void inputDeviceCapabilities();
void keyboardGrab();
+ void inputDeviceCreation();
+ void inputDeviceKeyboardFocus();
void singleClient();
void multipleClients();
void geometry();
@@ -83,10 +87,11 @@ void tst_WaylandCompositor::singleClient()
wl_surface *sb = client.createSurface();
QTRY_COMPARE(compositor.surfaces.size(), 2);
- WaylandClient *ca = compositor.surfaces.at(0)->client();
- WaylandClient *cb = compositor.surfaces.at(1)->client();
+ QWaylandClient *ca = compositor.surfaces.at(0)->client();
+ QWaylandClient *cb = compositor.surfaces.at(1)->client();
QCOMPARE(ca, cb);
+ QVERIFY(ca != 0);
QList<QWaylandSurface *> surfaces = compositor.surfacesForClient(ca);
QCOMPARE(surfaces.size(), 2);
@@ -114,13 +119,14 @@ void tst_WaylandCompositor::multipleClients()
QTRY_COMPARE(compositor.surfaces.size(), 3);
- WaylandClient *ca = compositor.surfaces.at(0)->client();
- WaylandClient *cb = compositor.surfaces.at(1)->client();
- WaylandClient *cc = compositor.surfaces.at(2)->client();
+ QWaylandClient *ca = compositor.surfaces.at(0)->client();
+ QWaylandClient *cb = compositor.surfaces.at(1)->client();
+ QWaylandClient *cc = compositor.surfaces.at(2)->client();
QVERIFY(ca != cb);
QVERIFY(ca != cc);
QVERIFY(cb != cc);
+ QVERIFY(ca != 0);
QCOMPARE(compositor.surfacesForClient(ca).size(), 1);
QCOMPARE(compositor.surfacesForClient(ca).at(0), compositor.surfaces.at(0));
@@ -321,5 +327,74 @@ void tst_WaylandCompositor::inputDeviceCapabilities()
QTRY_COMPARE(k, dev.keyboardDevice());
}
+void tst_WaylandCompositor::inputDeviceCreation()
+{
+ TestCompositor compositor;
+ TestInputDevice dev1(&compositor, QWaylandInputDevice::Pointer | QWaylandInputDevice::Keyboard);
+ TestInputDevice dev2(&compositor, QWaylandInputDevice::Pointer | QWaylandInputDevice::Keyboard);
+
+ compositor.handle()->registerInputDevice(&dev1);
+ compositor.handle()->registerInputDevice(&dev2);
+
+ // The compositor will create the default input device
+ QTRY_COMPARE(compositor.handle()->inputDevices().count(), 3);
+ // Test the order
+ QTRY_COMPARE(compositor.handle()->inputDevices().at(0), &dev2);
+ QTRY_COMPARE(compositor.handle()->inputDevices().at(1), &dev1);
+ QTRY_COMPARE(compositor.handle()->inputDevices().at(2), compositor.defaultInputDevice());
+
+ QList<QMouseEvent *> allEvents;
+ allEvents += dev1.createMouseEvents(2);
+ allEvents += dev2.createMouseEvents(5);
+ foreach (QMouseEvent *me, allEvents) {
+ compositor.inputDeviceFor(me);
+ }
+
+ // The first input device will only get called exatly the number of times it has created
+ // the events
+ QTRY_COMPARE(dev1.queryCount(), 2);
+ // The second will get called the total number of times as it sits as the first item in
+ // the registered input devices list
+ QTRY_COMPARE(dev2.queryCount(), 7);
+}
+
+void tst_WaylandCompositor::inputDeviceKeyboardFocus()
+{
+ TestCompositor compositor;
+
+
+ TestInputDevice dev1(&compositor, QWaylandInputDevice::Keyboard);
+ TestInputDevice dev2(&compositor, QWaylandInputDevice::Keyboard);
+
+ compositor.handle()->registerInputDevice(&dev1);
+ compositor.handle()->registerInputDevice(&dev2);
+
+ // Create client after all the input devices have been set up as the mock client
+ // does not dynamically listen to new seats
+ MockClient client;
+ wl_surface *surface = client.createSurface();
+ QTRY_COMPARE(compositor.surfaces.size(), 1);
+
+ QWaylandSurface *waylandSurface = compositor.surfaces.at(0);
+ QList<QWaylandInputDevice *> devices = compositor.handle()->inputDevices();
+ foreach (QWaylandInputDevice *dev, devices) {
+ dev->setKeyboardFocus(waylandSurface);
+ }
+ QTRY_COMPARE(compositor.defaultInputDevice()->keyboardFocus(), waylandSurface);
+ QTRY_COMPARE(dev1.keyboardFocus(), waylandSurface);
+ QTRY_COMPARE(dev2.keyboardFocus(), waylandSurface);
+
+ wl_surface_destroy(surface);
+ QTRY_VERIFY(compositor.surfaces.size() == 0);
+ // This will normally be called for example in the quick compositor
+ // but here call it manually to get rid of the surface and have it reset
+ // the focus
+ compositor.handle()->cleanupGraphicsResources();
+
+ QTRY_VERIFY(!compositor.defaultInputDevice()->keyboardFocus());
+ QTRY_VERIFY(!dev1.keyboardFocus());
+ QTRY_VERIFY(!dev2.keyboardFocus());
+}
+
#include <tst_compositor.moc>
QTEST_MAIN(tst_WaylandCompositor);