diff options
author | Mikko Levonmaa <mikko.levonmaa@lge.com> | 2014-09-18 12:32:57 +0300 |
---|---|---|
committer | Mikko Levonmaa <mikko.levonmaa@lge.com> | 2014-10-06 07:53:53 +0200 |
commit | 0febf7c52f5cc4bc5c7767f7572ff87a5aa8a7af (patch) | |
tree | 4a7c5c0bea43b00722c3bd1c4dca6c0ac53fff04 /src | |
parent | b62ae0fd804633de07d68f2f5654d2373a83f8d7 (diff) | |
download | qtwayland-0febf7c52f5cc4bc5c7767f7572ff87a5aa8a7af.tar.gz qtwayland-0febf7c52f5cc4bc5c7767f7572ff87a5aa8a7af.tar.bz2 qtwayland-0febf7c52f5cc4bc5c7767f7572ff87a5aa8a7af.zip |
Allow client side input device customization
Introduces QWaylandInputDeviceIntegration plugins to allow customization
of input device related behavior. The plugin can be activated via the
environment variable QT_WAYLAND_INPUTDEVICE_INTEGRATION
Change-Id: If5629737752afacb29161f51c1b7c6e171fb2758
Reviewed-by: Mikko Levonmaa <mikko.levonmaa@lge.com>
Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
Reviewed-by: Giulio Camuffo <giulio.camuffo@jollamobile.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/client/client.pro | 5 | ||||
-rw-r--r-- | src/client/inputdeviceintegration/inputdeviceintegration.pri | 11 | ||||
-rw-r--r-- | src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h | 64 | ||||
-rw-r--r-- | src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp | 96 | ||||
-rw-r--r-- | src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory_p.h | 61 | ||||
-rw-r--r-- | src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin.cpp | 55 | ||||
-rw-r--r-- | src/client/inputdeviceintegration/qwaylandinputdeviceintegrationplugin_p.h | 69 | ||||
-rw-r--r-- | src/client/qwaylanddisplay.cpp | 2 | ||||
-rw-r--r-- | src/client/qwaylandinputdevice.cpp | 285 | ||||
-rw-r--r-- | src/client/qwaylandinputdevice_p.h | 143 | ||||
-rw-r--r-- | src/client/qwaylandintegration.cpp | 32 | ||||
-rw-r--r-- | src/client/qwaylandintegration_p.h | 9 |
12 files changed, 654 insertions, 178 deletions
diff --git a/src/client/client.pro b/src/client/client.pro index 6aaa2541..22271ee4 100644 --- a/src/client/client.pro +++ b/src/client/client.pro @@ -3,7 +3,9 @@ QT += core-private gui-private QT_FOR_PRIVATE += platformsupport-private MODULE=waylandclient -MODULE_PLUGIN_TYPES = wayland-graphics-integration-client +MODULE_PLUGIN_TYPES = \ + wayland-graphics-integration-client \ + wayland-inputdevice-integration load(qt_module) @@ -108,3 +110,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 00000000..f16dfc3c --- /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 00000000..255a6685 --- /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, 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 00000000..58a82fb2 --- /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 00000000..13cddc24 --- /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 00000000..71a93325 --- /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 00000000..a0a062f4 --- /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 ¶mList) = 0; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDINPUTDEVICEINTEGRATIONPLUGIN_H diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index edaac8fe..c4a702d7 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -241,7 +241,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, id); + QWaylandInputDevice *inputDevice = mWaylandIntegration->createInputDevice(this, id); mInputDevices.append(inputDevice); } else if (interface == QStringLiteral("wl_data_device_manager")) { mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id)); diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index 5198a9e3..4f72d614 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, uint32_t id) : QObject() @@ -246,7 +175,6 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, uint32_t id) 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,26 +760,26 @@ 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::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 23e1fc74..0c6ecfb6 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, 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 d9bf82e4..ad99c67b 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); @@ -361,4 +367,30 @@ void QWaylandIntegration::initializeShellIntegration() } } +QWaylandInputDevice *QWaylandIntegration::createInputDevice(QWaylandDisplay *display, uint32_t id) +{ + if (mInputDeviceIntegration) { + return mInputDeviceIntegration->createInputDevice(display, id); + } + return new QWaylandInputDevice(display, 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 bbe98285..9741b1a7 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 { @@ -89,17 +91,24 @@ public: QPlatformTheme *createPlatformTheme(const QString &name) const; + QWaylandInputDevice *createInputDevice(QWaylandDisplay *display, 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; |