diff options
author | Mikko Levonmaa <mikko.levonmaa@lge.com> | 2014-03-28 15:25:21 -0700 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-05-06 18:05:01 +0200 |
commit | cbc690145af96e32f1b1cbdc42bc6b1e2d4c3bd2 (patch) | |
tree | 2365b123034becbe52d54d83b767746f24edc2f1 | |
parent | 9fbaf51eccf668a938f4c9a466cc4595195920f3 (diff) |
Add grab support for QtWayland::Keyboard
Adds the possibility to grab the wl_keyboard interface, similar to
pointer and touch grabs. Also includes basic unit tests
Change-Id: I665df2ab5adfe16abd6b55f2d00cd9e6dc89d039
Reviewed-by: Giulio Camuffo <giulio.camuffo@jollamobile.com>
Reviewed-by: Mikko Levonmaa <mikko.levonmaa@lge.com>
-rw-r--r-- | src/compositor/wayland_wrapper/qwlkeyboard.cpp | 70 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/qwlkeyboard_p.h | 25 | ||||
-rw-r--r-- | tests/auto/compositor/compositor.pro | 10 | ||||
-rw-r--r-- | tests/auto/compositor/testcompositor.cpp | 4 | ||||
-rw-r--r-- | tests/auto/compositor/testcompositor.h | 2 | ||||
-rw-r--r-- | tests/auto/compositor/testkeyboardgrabber.cpp | 74 | ||||
-rw-r--r-- | tests/auto/compositor/testkeyboardgrabber.h | 66 | ||||
-rw-r--r-- | tests/auto/compositor/tst_compositor.cpp | 52 |
8 files changed, 285 insertions, 18 deletions
diff --git a/src/compositor/wayland_wrapper/qwlkeyboard.cpp b/src/compositor/wayland_wrapper/qwlkeyboard.cpp index 25e7155b0..2642480f5 100644 --- a/src/compositor/wayland_wrapper/qwlkeyboard.cpp +++ b/src/compositor/wayland_wrapper/qwlkeyboard.cpp @@ -60,6 +60,7 @@ Keyboard::Keyboard(Compositor *compositor, InputDevice *seat) : QtWaylandServer::wl_keyboard() , m_compositor(compositor) , m_seat(seat) + , m_grab(this) , m_focus() , m_focusResource() , m_keys() @@ -89,7 +90,28 @@ Keyboard::~Keyboard() #endif } -void Keyboard::setFocus(Surface *surface) +KeyboardGrabber::~KeyboardGrabber() +{ +} + +void Keyboard::startGrab(KeyboardGrabber *grab) +{ + m_grab = grab; + m_grab->m_keyboard = this; + m_grab->focused(m_focus); +} + +void Keyboard::endGrab() +{ + m_grab = this; +} + +KeyboardGrabber *Keyboard::currentGrab() const +{ + return m_grab; +} + +void Keyboard::focused(Surface *surface) { if (m_focusResource && m_focus != surface) { uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); @@ -111,6 +133,11 @@ void Keyboard::setFocus(Surface *surface) Q_EMIT focusChanged(m_focus); } +void Keyboard::setFocus(Surface* surface) +{ + m_grab->focused(surface); +} + void Keyboard::setKeymap(const QWaylandKeymap &keymap) { m_keymap = keymap; @@ -170,30 +197,44 @@ void Keyboard::keyboard_destroy_resource(wl_keyboard::Resource *resource) m_focusResource = 0; } +void Keyboard::key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state) +{ + if (m_focusResource) { + send_key(m_focusResource->handle, serial, time, key, state); + } +} + void Keyboard::sendKeyEvent(uint code, uint32_t state) { // There must be no keys pressed when changing the keymap, // see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html if (m_pendingKeymap && m_keys.isEmpty()) updateKeymap(); - if (m_focusResource) { - uint32_t time = m_compositor->currentTimeMsecs(); - uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); - uint key = code - 8; - send_key(m_focusResource->handle, serial, time, key, state); - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - m_keys << key; - } else { - for (int i = 0; i < m_keys.size(); ++i) { - if (m_keys.at(i) == key) { - m_keys.remove(i); - } + + uint32_t time = m_compositor->currentTimeMsecs(); + uint32_t serial = wl_display_next_serial(m_compositor->wl_display()); + uint key = code - 8; + m_grab->key(serial, time, key, state); + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { + m_keys << key; + } else { + for (int i = 0; i < m_keys.size(); ++i) { + if (m_keys.at(i) == key) { + m_keys.remove(i); } } } updateModifierState(code, state); } +void Keyboard::modifiers(uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, uint32_t group) +{ + if (m_focusResource) { + send_modifiers(m_focusResource->handle, serial, mods_depressed, mods_latched, mods_locked, group); + } +} + void Keyboard::updateModifierState(uint code, uint32_t state) { #ifndef QT_NO_WAYLAND_XKB @@ -215,8 +256,7 @@ void Keyboard::updateModifierState(uint code, uint32_t state) m_modsLocked = modsLocked; m_group = group; - if (m_focusResource) - sendKeyModifiers(m_focusResource, wl_display_next_serial(m_compositor->wl_display())); + m_grab->modifiers(wl_display_next_serial(m_compositor->wl_display()), m_modsDepressed, m_modsLatched, m_modsLocked, m_group); #else Q_UNUSED(code); Q_UNUSED(state); diff --git a/src/compositor/wayland_wrapper/qwlkeyboard_p.h b/src/compositor/wayland_wrapper/qwlkeyboard_p.h index 6faf6ace2..fff6e3e04 100644 --- a/src/compositor/wayland_wrapper/qwlkeyboard_p.h +++ b/src/compositor/wayland_wrapper/qwlkeyboard_p.h @@ -63,8 +63,20 @@ namespace QtWayland { class Compositor; class InputDevice; class Surface; +class Keyboard; -class Q_COMPOSITOR_EXPORT Keyboard : public QObject, public QtWaylandServer::wl_keyboard +class Q_COMPOSITOR_EXPORT KeyboardGrabber { + public: + virtual ~KeyboardGrabber(); + virtual void focused(Surface *surface) = 0; + virtual void key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state) = 0; + virtual void modifiers(uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, uint32_t group) = 0; + + Keyboard *m_keyboard; +}; + +class Q_COMPOSITOR_EXPORT Keyboard : public QObject, public QtWaylandServer::wl_keyboard, public KeyboardGrabber { Q_OBJECT @@ -82,6 +94,16 @@ public: Surface *focus() const; Resource *focusResource() const; + void focused(Surface* surface); + void key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state); + void modifiers(uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, uint32_t group); + + void startGrab(KeyboardGrabber *grab); + void endGrab(); + KeyboardGrabber *currentGrab() const; + + Q_SIGNALS: void focusChanged(Surface *surface); @@ -103,6 +125,7 @@ private: Compositor *m_compositor; InputDevice *m_seat; + KeyboardGrabber* m_grab; Surface *m_focus; Resource *m_focusResource; WlListener m_focusDestroyListener; diff --git a/tests/auto/compositor/compositor.pro b/tests/auto/compositor/compositor.pro index d049b17a0..d173d2ed6 100644 --- a/tests/auto/compositor/compositor.pro +++ b/tests/auto/compositor/compositor.pro @@ -20,5 +20,11 @@ config_xkbcommon { DEFINES += QT_NO_WAYLAND_XKB } -SOURCES += tst_compositor.cpp testcompositor.cpp mockclient.cpp -HEADERS += testcompositor.h mockclient.h +SOURCES += tst_compositor.cpp \ + testcompositor.cpp \ + testkeyboardgrabber.cpp \ + mockclient.cpp \ + +HEADERS += testcompositor.h \ + testkeyboardgrabber.h \ + mockclient.h \ diff --git a/tests/auto/compositor/testcompositor.cpp b/tests/auto/compositor/testcompositor.cpp index aa15a6ab5..420c88c0d 100644 --- a/tests/auto/compositor/testcompositor.cpp +++ b/tests/auto/compositor/testcompositor.cpp @@ -41,6 +41,10 @@ #include "testcompositor.h" +TestCompositor::TestCompositor(QWaylandCompositor::ExtensionFlag flags) : QWaylandCompositor(0, 0, flags) +{ +} + void TestCompositor::surfaceCreated(QWaylandSurface *surface) { surfaces << surface; diff --git a/tests/auto/compositor/testcompositor.h b/tests/auto/compositor/testcompositor.h index 4cb77aabc..e504cd47b 100644 --- a/tests/auto/compositor/testcompositor.h +++ b/tests/auto/compositor/testcompositor.h @@ -45,6 +45,8 @@ class TestCompositor : public QWaylandCompositor { public: + TestCompositor(QWaylandCompositor::ExtensionFlag flags = QWaylandCompositor::DefaultExtensions); + void surfaceCreated(QWaylandSurface *surface); void surfaceAboutToBeDestroyed(QWaylandSurface *surface); diff --git a/tests/auto/compositor/testkeyboardgrabber.cpp b/tests/auto/compositor/testkeyboardgrabber.cpp new file mode 100644 index 000000000..ecd3a98dd --- /dev/null +++ b/tests/auto/compositor/testkeyboardgrabber.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 "testkeyboardgrabber.h" + +namespace QtWayland { + KeyboardGrabber::~KeyboardGrabber() {} +} + +void TestKeyboardGrabber::focused(QtWayland::Surface *surface) +{ + Q_UNUSED(surface); + Q_EMIT focusedCalled(); +} + +void TestKeyboardGrabber::key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state) +{ + Q_UNUSED(serial); + Q_UNUSED(time); + Q_UNUSED(key); + Q_UNUSED(state); + Q_EMIT keyCalled(); +} + +void TestKeyboardGrabber::modifiers(uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, uint32_t group) +{ + Q_UNUSED(serial); + Q_UNUSED(mods_depressed); + Q_UNUSED(mods_latched); + Q_UNUSED(mods_locked); + Q_UNUSED(group); + Q_EMIT modifiersCalled(); +} + diff --git a/tests/auto/compositor/testkeyboardgrabber.h b/tests/auto/compositor/testkeyboardgrabber.h new file mode 100644 index 000000000..75ea1a18f --- /dev/null +++ b/tests/auto/compositor/testkeyboardgrabber.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** 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 "QtCompositor/private/qwlkeyboard_p.h" +#include "QtCompositor/private/qwlsurface_p.h" + +class TestKeyboardGrabber : public QObject, public QtWayland::KeyboardGrabber +{ + Q_OBJECT + +public: + + TestKeyboardGrabber() {} + ~TestKeyboardGrabber() {} + + void focused(QtWayland::Surface *surface); + void key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state); + void modifiers(uint32_t serial, uint32_t mods_depressed, + uint32_t mods_latched, uint32_t mods_locked, uint32_t group); + +signals: + void focusedCalled(); + void keyCalled(); + void modifiersCalled(); +}; + + diff --git a/tests/auto/compositor/tst_compositor.cpp b/tests/auto/compositor/tst_compositor.cpp index 803f280bc..eae3f2943 100644 --- a/tests/auto/compositor/tst_compositor.cpp +++ b/tests/auto/compositor/tst_compositor.cpp @@ -41,6 +41,10 @@ #include "mockclient.h" #include "testcompositor.h" +#include "testkeyboardgrabber.h" + +#include "QtCompositor/private/qwlkeyboard_p.h" +#include "QtCompositor/private/qwlinputdevice_p.h" #include "qwaylandbufferref.h" @@ -59,6 +63,7 @@ public: private slots: void inputDeviceCapabilities(); + void keyboardGrab(); void singleClient(); void multipleClients(); void geometry(); @@ -133,6 +138,53 @@ void tst_WaylandCompositor::multipleClients() QTRY_COMPARE(compositor.surfaces.size(), 0); } +void tst_WaylandCompositor::keyboardGrab() +{ + TestCompositor compositor((QWaylandCompositor::ExtensionFlag)0); + MockClient mc; + + mc.createSurface(); + // This is needed for timing purposes, otherwise the query for the + // compositor surfaces will return null + QTRY_COMPARE(compositor.surfaces.size(), 1); + + // Set the focused surface so that key event will flow through + QWaylandSurface *waylandSurface = compositor.surfaces.at(0); + QWaylandInputDevice* inputDevice = compositor.defaultInputDevice(); + inputDevice->handle()->keyboardDevice()->setFocus(waylandSurface->handle()); + + TestKeyboardGrabber grab; + QSignalSpy grabFocusSpy(&grab, SIGNAL(focusedCalled())); + QSignalSpy grabKeySpy(&grab, SIGNAL(keyCalled())); + QSignalSpy grabModifierSpy(&grab, SIGNAL(modifiersCalled())); + + QtWayland::Keyboard *keyboard = inputDevice->handle()->keyboardDevice(); + keyboard->startGrab(&grab); + + QTRY_COMPARE(grabFocusSpy.count(), 1); + QCOMPARE(grab.m_keyboard, inputDevice->handle()->keyboardDevice()); + + QKeyEvent ke(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, 30, 0, 0); + QKeyEvent ke1(QEvent::KeyRelease, Qt::Key_A, Qt::NoModifier, 30, 0, 0); + inputDevice->sendFullKeyEvent(&ke); + inputDevice->sendFullKeyEvent(&ke1); + QTRY_COMPARE(grabKeySpy.count(), 2); + + QKeyEvent ke2(QEvent::KeyPress, Qt::Key_Shift, Qt::NoModifier, 50, 0, 0); + QKeyEvent ke3(QEvent::KeyRelease, Qt::Key_Shift, Qt::NoModifier, 50, 0, 0); + inputDevice->sendFullKeyEvent(&ke2); + inputDevice->sendFullKeyEvent(&ke3); + QTRY_COMPARE(grabModifierSpy.count(), 2); + // Modifiers are also keys + QTRY_COMPARE(grabKeySpy.count(), 4); + + // Stop grabbing + keyboard->endGrab(); + inputDevice->sendFullKeyEvent(&ke); + inputDevice->sendFullKeyEvent(&ke1); + QTRY_COMPARE(grabKeySpy.count(), 4); +} + void tst_WaylandCompositor::geometry() { TestCompositor compositor; |