summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikko Levonmaa <mikko.levonmaa@lge.com>2014-03-28 15:25:21 -0700
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-05-06 18:05:01 +0200
commitcbc690145af96e32f1b1cbdc42bc6b1e2d4c3bd2 (patch)
tree2365b123034becbe52d54d83b767746f24edc2f1
parent9fbaf51eccf668a938f4c9a466cc4595195920f3 (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.cpp70
-rw-r--r--src/compositor/wayland_wrapper/qwlkeyboard_p.h25
-rw-r--r--tests/auto/compositor/compositor.pro10
-rw-r--r--tests/auto/compositor/testcompositor.cpp4
-rw-r--r--tests/auto/compositor/testcompositor.h2
-rw-r--r--tests/auto/compositor/testkeyboardgrabber.cpp74
-rw-r--r--tests/auto/compositor/testkeyboardgrabber.h66
-rw-r--r--tests/auto/compositor/tst_compositor.cpp52
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;