From 04c05e9a53f4fe59c58967809b91ea792b6cffbd Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Wed, 7 Sep 2016 16:32:05 +0200 Subject: Make QWaylandKeymap a QObject This makes it possible to use defaultSeat declaratively by allowing it to be uninitialized until the QWaylandCompositor::create has been called. Change-Id: I962cc7cc82a0bbc9240abb50cf92dee77e4a0ba6 Reviewed-by: Pier Luigi Fiorini Reviewed-by: Paul Olav Tvete --- src/compositor/compositor_api/compositor_api.pri | 3 + .../compositor_api/qwaylandcompositor.cpp | 27 +++-- .../compositor_api/qwaylandcompositor_p.h | 4 +- src/compositor/compositor_api/qwaylandkeyboard.cpp | 65 ++++++----- src/compositor/compositor_api/qwaylandkeyboard.h | 25 +--- src/compositor/compositor_api/qwaylandkeyboard_p.h | 3 +- src/compositor/compositor_api/qwaylandkeymap.cpp | 129 +++++++++++++++++++++ src/compositor/compositor_api/qwaylandkeymap.h | 81 +++++++++++++ src/compositor/compositor_api/qwaylandkeymap_p.h | 72 ++++++++++++ .../compositor_api/qwaylandquickcompositor.cpp | 1 + src/compositor/compositor_api/qwaylandseat.cpp | 57 +++++---- src/compositor/compositor_api/qwaylandseat.h | 5 +- src/compositor/compositor_api/qwaylandseat_p.h | 4 +- .../compositor/qwaylandquickcompositorplugin.cpp | 2 + tests/auto/compositor/compositor/testseat.h | 2 +- .../auto/compositor/compositor/tst_compositor.cpp | 9 +- tests/manual/keymap/keymapcompositor.qml | 87 ++++++++++++++ 17 files changed, 485 insertions(+), 91 deletions(-) create mode 100644 src/compositor/compositor_api/qwaylandkeymap.cpp create mode 100644 src/compositor/compositor_api/qwaylandkeymap.h create mode 100644 src/compositor/compositor_api/qwaylandkeymap_p.h create mode 100644 tests/manual/keymap/keymapcompositor.qml diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri index e803d14c0..0f70773cb 100644 --- a/src/compositor/compositor_api/compositor_api.pri +++ b/src/compositor/compositor_api/compositor_api.pri @@ -10,6 +10,8 @@ HEADERS += \ compositor_api/qwaylandseat_p.h \ compositor_api/qwaylandkeyboard.h \ compositor_api/qwaylandkeyboard_p.h \ + compositor_api/qwaylandkeymap.h \ + compositor_api/qwaylandkeymap_p.h \ compositor_api/qwaylandpointer.h \ compositor_api/qwaylandpointer_p.h \ compositor_api/qwaylandtouch.h \ @@ -32,6 +34,7 @@ SOURCES += \ compositor_api/qwaylandsurface.cpp \ compositor_api/qwaylandseat.cpp \ compositor_api/qwaylandkeyboard.cpp \ + compositor_api/qwaylandkeymap.cpp \ compositor_api/qwaylandpointer.cpp \ compositor_api/qwaylandtouch.cpp \ compositor_api/qwaylandoutput.cpp \ diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 732e607bc..0d4e30df7 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -125,7 +125,7 @@ public: QWindowSystemEventHandler::sendEvent(e); if (!ke->repeat) { - keyb->updateKeymap(); + keyb->maybeUpdateKeymap(); keyb->updateModifierState(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED); } } else { @@ -147,6 +147,7 @@ QWaylandCompositorPrivate::QWaylandCompositorPrivate(QWaylandCompositor *composi , server_buffer_integration(0) #endif , retainSelection(false) + , preInitialized(false) , initialized(false) { if (QGuiApplication::platformNativeInterface()) @@ -200,7 +201,7 @@ void QWaylandCompositorPrivate::init() QObject::connect(dispatcher, SIGNAL(aboutToBlock()), q, SLOT(processWaylandEvents())); initializeHardwareIntegration(); - initializeDefaultSeat(); + initializeSeats(); initialized = true; @@ -225,6 +226,19 @@ QWaylandCompositorPrivate::~QWaylandCompositorPrivate() wl_display_destroy(display); } +void QWaylandCompositorPrivate::preInit() +{ + Q_Q(QWaylandCompositor); + + if (preInitialized) + return; + + if (seats.empty()) + seats.append(q->createSeat()); + + preInitialized = true; +} + void QWaylandCompositorPrivate::destroySurface(QWaylandSurface *surface) { Q_Q(QWaylandCompositor); @@ -352,12 +366,10 @@ void QWaylandCompositorPrivate::initializeHardwareIntegration() #endif } -void QWaylandCompositorPrivate::initializeDefaultSeat() +void QWaylandCompositorPrivate::initializeSeats() { - Q_Q(QWaylandCompositor); - QWaylandSeat *device = q->createSeat(); - seats.append(device); - q->defaultSeatChanged(device, nullptr); + for (QWaylandSeat *seat : qAsConst(seats)) + seat->initialize(); } void QWaylandCompositorPrivate::loadClientBufferIntegration() @@ -469,6 +481,7 @@ QWaylandCompositor::~QWaylandCompositor() void QWaylandCompositor::create() { Q_D(QWaylandCompositor); + d->preInit(); d->init(); } diff --git a/src/compositor/compositor_api/qwaylandcompositor_p.h b/src/compositor/compositor_api/qwaylandcompositor_p.h index 708d0113d..9942331e4 100644 --- a/src/compositor/compositor_api/qwaylandcompositor_p.h +++ b/src/compositor/compositor_api/qwaylandcompositor_p.h @@ -77,6 +77,7 @@ public: QWaylandCompositorPrivate(QWaylandCompositor *compositor); ~QWaylandCompositorPrivate(); + void preInit(); void init(); void destroySurface(QWaylandSurface *surface); @@ -114,7 +115,7 @@ protected: protected: void initializeHardwareIntegration(); void initializeExtensions(); - void initializeDefaultSeat(); + void initializeSeats(); void loadClientBufferIntegration(); void loadServerBufferIntegration(); @@ -145,6 +146,7 @@ protected: QScopedPointer eventHandler; bool retainSelection; + bool preInitialized; bool initialized; QList > polish_objects; diff --git a/src/compositor/compositor_api/qwaylandkeyboard.cpp b/src/compositor/compositor_api/qwaylandkeyboard.cpp index 42349fb24..780c13144 100644 --- a/src/compositor/compositor_api/qwaylandkeyboard.cpp +++ b/src/compositor/compositor_api/qwaylandkeyboard.cpp @@ -37,6 +37,7 @@ #include "qwaylandkeyboard.h" #include "qwaylandkeyboard_p.h" +#include #include #include #include @@ -71,9 +72,6 @@ QWaylandKeyboardPrivate::QWaylandKeyboardPrivate(QWaylandSeat *seat) , repeatRate(40) , repeatDelay(400) { -#ifndef QT_NO_WAYLAND_XKB - initXKB(); -#endif } QWaylandKeyboardPrivate::~QWaylandKeyboardPrivate() @@ -232,7 +230,10 @@ void QWaylandKeyboardPrivate::updateModifierState(uint code, uint32_t state) #endif } -void QWaylandKeyboardPrivate::updateKeymap() +// If there is no key currently pressed, update the keymap right away. +// Otherwise, delay the update when keys are released +// see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html +void QWaylandKeyboardPrivate::maybeUpdateKeymap() { // There must be no keys pressed when changing the keymap, // see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html @@ -348,18 +349,19 @@ void QWaylandKeyboardPrivate::createXKBKeymap() if (!xkb_context) return; - struct xkb_rule_names rule_names = { strdup(qPrintable(keymap.rules())), - strdup(qPrintable(keymap.model())), - strdup(qPrintable(keymap.layout())), - strdup(qPrintable(keymap.variant())), - strdup(qPrintable(keymap.options())) }; - struct xkb_keymap *keymap = xkb_keymap_new_from_names(xkb_context, &rule_names, static_cast(0)); - - if (keymap) { - createXKBState(keymap); - xkb_keymap_unref(keymap); + auto keymap = seat->keymap(); + struct xkb_rule_names rule_names = { strdup(qPrintable(keymap->rules())), + strdup(qPrintable(keymap->model())), + strdup(qPrintable(keymap->layout())), + strdup(qPrintable(keymap->variant())), + strdup(qPrintable(keymap->options())) }; + struct xkb_keymap *xkbKeymap = xkb_keymap_new_from_names(xkb_context, &rule_names, static_cast(0)); + + if (xkbKeymap) { + createXKBState(xkbKeymap); + xkb_keymap_unref(xkbKeymap); } else { - qWarning("Failed to load the '%s' XKB keymap.", qPrintable(this->keymap.layout())); + qWarning("Failed to load the '%s' XKB keymap.", qPrintable(keymap->layout())); } free((char *)rule_names.rules); @@ -396,6 +398,15 @@ QWaylandKeyboard::QWaylandKeyboard(QWaylandSeat *seat, QObject *parent) { Q_D(QWaylandKeyboard); connect(&d->focusDestroyListener, &QWaylandDestroyListener::fired, this, &QWaylandKeyboard::focusDestroyed); + auto keymap = seat->keymap(); + connect(keymap, &QWaylandKeymap::layoutChanged, this, &QWaylandKeyboard::updateKeymap); + connect(keymap, &QWaylandKeymap::variantChanged, this, &QWaylandKeyboard::updateKeymap); + connect(keymap, &QWaylandKeymap::optionsChanged, this, &QWaylandKeyboard::updateKeymap); + connect(keymap, &QWaylandKeymap::rulesChanged, this, &QWaylandKeyboard::updateKeymap); + connect(keymap, &QWaylandKeymap::modelChanged, this, &QWaylandKeyboard::updateKeymap); +#ifndef QT_NO_WAYLAND_XKB + d->initXKB(); +#endif } /*! @@ -429,6 +440,13 @@ void QWaylandKeyboard::focusDestroyed(void *data) d->focusResource = 0; } +void QWaylandKeyboard::updateKeymap() +{ + Q_D(QWaylandKeyboard); + d->pendingKeymap = true; + d->maybeUpdateKeymap(); +} + /*! * Returns the client that currently has keyboard focus. */ @@ -537,23 +555,6 @@ void QWaylandKeyboard::setFocus(QWaylandSurface *surface) d->focused(surface); } -/*! - * Sets the keyboard's keymap to \a keymap. - */ -void QWaylandKeyboard::setKeymap(const QWaylandKeymap &keymap) -{ - Q_D(QWaylandKeyboard); - d->keymap = keymap; - d->pendingKeymap = true; - - // If there is no key currently pressed, update right away the keymap - // Otherwise, delay the update when keys are released - // see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html - if (d->keys.isEmpty()) { - d->updateKeymap(); - } -} - /*! * \internal */ diff --git a/src/compositor/compositor_api/qwaylandkeyboard.h b/src/compositor/compositor_api/qwaylandkeyboard.h index 1348f5cd9..685134ff7 100644 --- a/src/compositor/compositor_api/qwaylandkeyboard.h +++ b/src/compositor/compositor_api/qwaylandkeyboard.h @@ -48,26 +48,7 @@ QT_BEGIN_NAMESPACE class QWaylandKeyboard; class QWaylandKeyboardPrivate; class QWaylandSeat; - -class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandKeymap -{ -public: - QWaylandKeymap(const QString &layout = QString(), const QString &variant = QString(), const QString &options = QString(), - const QString &model = QString(), const QString &rules = QString()); - - inline QString layout() const { return m_layout; } - inline QString variant() const { return m_variant; } - inline QString options() const { return m_options; } - inline QString rules() const { return m_rules; } - inline QString model() const { return m_model; } - -private: - QString m_layout; - QString m_variant; - QString m_options; - QString m_rules; - QString m_model; -}; +class QWaylandKeymap; class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandKeyboard : public QWaylandObject { @@ -88,7 +69,6 @@ public: void setRepeatDelay(quint32 delay); virtual void setFocus(QWaylandSurface *surface); - virtual void setKeymap(const QWaylandKeymap &keymap); virtual void sendKeyModifiers(QWaylandClient *client, uint32_t serial); virtual void sendKeyPressEvent(uint code); @@ -106,6 +86,9 @@ Q_SIGNALS: private: void focusDestroyed(void *data); + +private Q_SLOTS: + void updateKeymap(); }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandkeyboard_p.h b/src/compositor/compositor_api/qwaylandkeyboard_p.h index ac306282e..fc43853cc 100644 --- a/src/compositor/compositor_api/qwaylandkeyboard_p.h +++ b/src/compositor/compositor_api/qwaylandkeyboard_p.h @@ -91,7 +91,7 @@ public: void keyEvent(uint code, uint32_t state); void sendKeyEvent(uint code, uint32_t state); void updateModifierState(uint code, uint32_t state); - void updateKeymap(); + void maybeUpdateKeymap(); void checkFocusResource(Resource *resource); void sendEnter(QWaylandSurface *surface, Resource *resource); @@ -123,7 +123,6 @@ private: uint32_t modsLocked; uint32_t group; - QWaylandKeymap keymap; bool pendingKeymap; #ifndef QT_NO_WAYLAND_XKB size_t keymap_size; diff --git a/src/compositor/compositor_api/qwaylandkeymap.cpp b/src/compositor/compositor_api/qwaylandkeymap.cpp new file mode 100644 index 000000000..d11070f26 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandkeymap.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandkeymap.h" +#include "qwaylandkeymap_p.h" + +QT_BEGIN_NAMESPACE + +QWaylandKeymap::QWaylandKeymap(const QString &layout, const QString &variant, const QString &options, const QString &model, const QString &rules, QObject *parent) + : QObject(*new QWaylandKeymapPrivate(layout, variant, options, model, rules), parent) +{ +} + +QString QWaylandKeymap::layout() const { + Q_D(const QWaylandKeymap); + return d->m_layout; +} + +void QWaylandKeymap::setLayout(const QString &layout) +{ + Q_D(QWaylandKeymap); + if (d->m_layout == layout) + return; + d->m_layout = layout; + emit layoutChanged(); +} + +QString QWaylandKeymap::variant() const +{ + Q_D(const QWaylandKeymap); + return d->m_variant; +} + +void QWaylandKeymap::setVariant(const QString &variant) +{ + Q_D(QWaylandKeymap); + if (d->m_variant == variant) + return; + d->m_variant = variant; + emit variantChanged(); +} + +QString QWaylandKeymap::options() const { + Q_D(const QWaylandKeymap); + return d->m_options; +} + +void QWaylandKeymap::setOptions(const QString &options) +{ + Q_D(QWaylandKeymap); + if (d->m_options == options) + return; + d->m_options = options; + emit optionsChanged(); +} + +QString QWaylandKeymap::rules() const { + Q_D(const QWaylandKeymap); + return d->m_rules; +} + +void QWaylandKeymap::setRules(const QString &rules) +{ + Q_D(QWaylandKeymap); + if (d->m_rules == rules) + return; + d->m_rules = rules; + emit rulesChanged(); +} + +QString QWaylandKeymap::model() const { + Q_D(const QWaylandKeymap); + return d->m_model; +} + +void QWaylandKeymap::setModel(const QString &model) +{ + Q_D(QWaylandKeymap); + if (d->m_model == model) + return; + d->m_model = model; + emit modelChanged(); +} + +QWaylandKeymapPrivate::QWaylandKeymapPrivate(const QString &layout, const QString &variant, + const QString &options, const QString &model, + const QString &rules) + : m_layout(layout) + , m_variant(variant) + , m_options(options) + , m_rules(rules) + , m_model(model) +{ +} + +QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandkeymap.h b/src/compositor/compositor_api/qwaylandkeymap.h new file mode 100644 index 000000000..c543691df --- /dev/null +++ b/src/compositor/compositor_api/qwaylandkeymap.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDKEYMAP_H +#define QWAYLANDKEYMAP_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QWaylandKeymapPrivate; + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandKeymap : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandKeymap) + Q_PROPERTY(QString layout READ layout WRITE setLayout NOTIFY layoutChanged) + Q_PROPERTY(QString variant READ variant WRITE setVariant NOTIFY variantChanged) + Q_PROPERTY(QString options READ options WRITE setOptions NOTIFY optionsChanged) + Q_PROPERTY(QString rules READ rules WRITE setRules NOTIFY rulesChanged) + Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged) +public: + QWaylandKeymap(const QString &layout = QString(), const QString &variant = QString(), const QString &options = QString(), + const QString &model = QString(), const QString &rules = QString(), QObject *parent = nullptr); + + QString layout() const; + void setLayout(const QString &layout); + QString variant() const; + void setVariant(const QString &variant); + QString options() const; + void setOptions(const QString &options); + QString rules() const; + void setRules(const QString &rules); + QString model() const; + void setModel(const QString &model); + +Q_SIGNALS: + void layoutChanged(); + void variantChanged(); + void optionsChanged(); + void rulesChanged(); + void modelChanged(); +}; + +QT_END_NAMESPACE + +#endif //QWAYLANDKEYMAP_H diff --git a/src/compositor/compositor_api/qwaylandkeymap_p.h b/src/compositor/compositor_api/qwaylandkeymap_p.h new file mode 100644 index 000000000..2c968ef38 --- /dev/null +++ b/src/compositor/compositor_api/qwaylandkeymap_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWaylandCompositor module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDKEYMAP_P_H +#define QWAYLANDKEYMAP_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandKeymapPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QWaylandKeymap) +public: + QWaylandKeymapPrivate(const QString &layout, const QString &variant, const QString &options, + const QString &model, const QString &rules); + + QString m_layout; + QString m_variant; + QString m_options; + QString m_rules; + QString m_model; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDKEYMAP_P_H diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp index 07ea381b4..21e32573e 100644 --- a/src/compositor/compositor_api/qwaylandquickcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp @@ -101,6 +101,7 @@ void QWaylandQuickCompositor::create() void QWaylandQuickCompositor::classBegin() { + QWaylandCompositorPrivate::get(this)->preInit(); } void QWaylandQuickCompositor::componentComplete() diff --git a/src/compositor/compositor_api/qwaylandseat.cpp b/src/compositor/compositor_api/qwaylandseat.cpp index 182f95ca3..017cc89cc 100644 --- a/src/compositor/compositor_api/qwaylandseat.cpp +++ b/src/compositor/compositor_api/qwaylandseat.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -52,15 +53,17 @@ QT_BEGIN_NAMESPACE -QWaylandSeatPrivate::QWaylandSeatPrivate(QWaylandSeat *seat, QWaylandCompositor *compositor) +QWaylandSeatPrivate::QWaylandSeatPrivate(QWaylandSeat *seat) : QObjectPrivate() - , QtWaylandServer::wl_seat(compositor->display(), 4) - , compositor(compositor) + , QtWaylandServer::wl_seat() + , isInitialized(false) + , compositor(nullptr) , mouseFocus(Q_NULLPTR) , keyboardFocus(nullptr) , capabilities() , data_device() , drag_handle(new QWaylandDrag(seat)) + , keymap(new QWaylandKeymap()) { } @@ -137,16 +140,6 @@ void QWaylandSeatPrivate::seat_get_touch(wl_seat::Resource *resource, uint32_t i } } -QWaylandKeymap::QWaylandKeymap(const QString &layout, const QString &variant, const QString &options, const QString &model, const QString &rules) - : m_layout(layout) - , m_variant(variant) - , m_options(options) - , m_rules(rules) - , m_model(model) -{ -} - - /*! * \class QWaylandSeat * \inmodule QtWaylandCompositor @@ -171,9 +164,13 @@ QWaylandKeymap::QWaylandKeymap(const QString &layout, const QString &variant, co * Constructs a QWaylandSeat for the given \a compositor and with the given \a capabilityFlags. */ QWaylandSeat::QWaylandSeat(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags) - : QWaylandObject(*new QWaylandSeatPrivate(this,compositor)) + : QWaylandObject(*new QWaylandSeatPrivate(this)) { - d_func()->setCapabilities(capabilityFlags); + Q_D(QWaylandSeat); + d->compositor = compositor; + d->capabilities = capabilityFlags; + if (compositor->isCreated()) + initialize(); } /*! @@ -183,6 +180,27 @@ QWaylandSeat::~QWaylandSeat() { } +void QWaylandSeat::initialize() +{ + Q_D(QWaylandSeat); + d->init(d->compositor->display(), 4); + + if (d->capabilities & QWaylandSeat::Pointer) + d->pointer.reset(QWaylandCompositorPrivate::get(d->compositor)->callCreatePointerDevice(this)); + if (d->capabilities & QWaylandSeat::Touch) + d->touch.reset(QWaylandCompositorPrivate::get(d->compositor)->callCreateTouchDevice(this)); + if (d->capabilities & QWaylandSeat::Keyboard) + d->keyboard.reset(QWaylandCompositorPrivate::get(d->compositor)->callCreateKeyboardDevice(this)); + + d->isInitialized = true; +} + +bool QWaylandSeat::isInitialized() const +{ + Q_D(const QWaylandSeat); + return d->isInitialized; +} + /*! * Sends a mouse press event for \a button to the QWaylandSeat's pointer device. */ @@ -368,13 +386,10 @@ bool QWaylandSeat::setKeyboardFocus(QWaylandSurface *surface) return true; } -/*! - * Sets the key map of this QWaylandSeat to \a keymap. - */ -void QWaylandSeat::setKeymap(const QWaylandKeymap &keymap) +QWaylandKeymap *QWaylandSeat::keymap() { - if (keyboard()) - keyboard()->setKeymap(keymap); + Q_D(const QWaylandSeat); + return d->keymap.data(); } /*! diff --git a/src/compositor/compositor_api/qwaylandseat.h b/src/compositor/compositor_api/qwaylandseat.h index 5501d9202..d6ea276f4 100644 --- a/src/compositor/compositor_api/qwaylandseat.h +++ b/src/compositor/compositor_api/qwaylandseat.h @@ -65,6 +65,7 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandSeat : public QWaylandObject Q_DECLARE_PRIVATE(QWaylandSeat) Q_PROPERTY(QWaylandDrag *drag READ drag CONSTANT) + Q_PROPERTY(QWaylandKeymap *keymap READ keymap CONSTANT) public: enum CapabilityFlag { // The order should match the enum WL_SEAT_CAPABILITY_* @@ -79,6 +80,8 @@ public: QWaylandSeat(QWaylandCompositor *compositor, CapabilityFlags capabilityFlags = DefaultCapabilities); virtual ~QWaylandSeat(); + virtual void initialize(); + bool isInitialized() const; void sendMousePressEvent(Qt::MouseButton button); void sendMouseReleaseEvent(Qt::MouseButton button); @@ -106,7 +109,7 @@ public: QWaylandKeyboard *keyboard() const; QWaylandSurface *keyboardFocus() const; bool setKeyboardFocus(QWaylandSurface *surface); - void setKeymap(const QWaylandKeymap &keymap); + QWaylandKeymap *keymap(); QWaylandTouch *touch() const; diff --git a/src/compositor/compositor_api/qwaylandseat_p.h b/src/compositor/compositor_api/qwaylandseat_p.h index 6588600cf..eb86aec37 100644 --- a/src/compositor/compositor_api/qwaylandseat_p.h +++ b/src/compositor/compositor_api/qwaylandseat_p.h @@ -90,7 +90,7 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandSeatPrivate : public QObjectPrivate, p public: Q_DECLARE_PUBLIC(QWaylandSeat) - QWaylandSeatPrivate(QWaylandSeat *seat, QWaylandCompositor *compositor); + QWaylandSeatPrivate(QWaylandSeat *seat); ~QWaylandSeatPrivate(); void clientRequestedDataDevice(QtWayland::DataDeviceManager *dndSelection, struct wl_client *client, uint32_t id); @@ -113,6 +113,7 @@ protected: void seat_destroy_resource(wl_seat::Resource *resource) Q_DECL_OVERRIDE; private: + bool isInitialized; QWaylandCompositor *compositor; QWaylandView *mouseFocus; QWaylandSurface *keyboardFocus; @@ -123,6 +124,7 @@ private: QScopedPointer touch; QScopedPointer data_device; QScopedPointer drag_handle; + QScopedPointer keymap; }; diff --git a/src/imports/compositor/qwaylandquickcompositorplugin.cpp b/src/imports/compositor/qwaylandquickcompositorplugin.cpp index 037d9ccba..e8204f7f2 100644 --- a/src/imports/compositor/qwaylandquickcompositorplugin.cpp +++ b/src/imports/compositor/qwaylandquickcompositorplugin.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -117,6 +118,7 @@ public: qmlRegisterType(uri, 1, 0, "WaylandMouseTracker"); qmlRegisterType(uri, 1, 0, "WaylandOutput"); qmlRegisterType(uri, 1, 0, "WaylandSurface"); + qmlRegisterType(uri, 1, 0, "WaylandKeymap"); qmlRegisterUncreatableType(uri, 1, 0, "WaylandExtension", QObject::tr("Cannot create instance of WaylandExtension")); qmlRegisterUncreatableType(uri, 1, 0, "WaylandClient", QObject::tr("Cannot create instance of WaylandClient")); diff --git a/tests/auto/compositor/compositor/testseat.h b/tests/auto/compositor/compositor/testseat.h index 54641c07d..7fa7030fa 100644 --- a/tests/auto/compositor/compositor/testseat.h +++ b/tests/auto/compositor/compositor/testseat.h @@ -36,7 +36,7 @@ QT_END_NAMESPACE class TestSeat : public QWaylandSeat { - + Q_OBJECT public: TestSeat(QWaylandCompositor *compositor, QWaylandSeat::CapabilityFlags caps); diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp index 3052b7b45..16aedd8ec 100644 --- a/tests/auto/compositor/compositor/tst_compositor.cpp +++ b/tests/auto/compositor/compositor/tst_compositor.cpp @@ -347,20 +347,21 @@ void tst_WaylandCompositor::seatCreation() MockClient client; Q_UNUSED(client); - TestSeat* dev = static_cast(compositor.defaultSeat()); + TestSeat* seat = qobject_cast(compositor.defaultSeat()); + QTRY_VERIFY(seat); // The compositor will create the default input device - QTRY_COMPARE(compositor.defaultSeat(), dev); + QTRY_VERIFY(seat->isInitialized()); QList allEvents; - allEvents += dev->createMouseEvents(5); + allEvents += seat->createMouseEvents(5); foreach (QMouseEvent *me, allEvents) { compositor.seatFor(me); } // The default input device will get called exatly the number of times it has created // the events - QTRY_COMPARE(dev->queryCount(), 5); + QTRY_COMPARE(seat->queryCount(), 5); } void tst_WaylandCompositor::seatKeyboardFocus() diff --git a/tests/manual/keymap/keymapcompositor.qml b/tests/manual/keymap/keymapcompositor.qml new file mode 100644 index 000000000..7f8982636 --- /dev/null +++ b/tests/manual/keymap/keymapcompositor.qml @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $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 The Qt Company Ltd 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$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtWayland.Compositor 1.0 +import QtQuick.Window 2.2 + +WaylandCompositor { + id: wlcompositor + property string layout: "no" + + defaultSeat.keymap { + layout: layout + options: "ctrl:swapcaps" + } + + WaylandOutput { + compositor: wlcompositor + window: Window { + width: 1024 + height: 768 + visible: true + color: "#c17711" + Text { + anchors.centerIn: parent + text: "Click the background to change layout: " + layout + } + MouseArea { + anchors.fill: parent + onClicked: layout = layout === "us" ? "no" : "us" + } + Item { + id: surfaceArea + anchors.fill: parent + } + } + } + Component { + id: chromeComponent + ShellSurfaceItem { + onSurfaceDestroyed: destroy() + } + } + WlShell { + onWlShellSurfaceCreated: chromeComponent.createObject(surfaceArea, { "shellSurface": shellSurface } ); + } + XdgShellV5 { + onXdgSurfaceCreated: chromeComponent.createObject(surfaceArea, { "shellSurface": xdgSurface } ); + } +} -- cgit v1.2.3