Implement zwp_input_method_context_v1::grab_keyboard
Offers a new InputKeyboardV1Interface instance that wraps the wl_keyboard and allows the compositor to forward the keyboard events.
This commit is contained in:
parent
ecda92e023
commit
7dd092e910
3 changed files with 138 additions and 6 deletions
|
@ -20,11 +20,14 @@
|
||||||
#include "KWayland/Client/registry.h"
|
#include "KWayland/Client/registry.h"
|
||||||
#include "KWayland/Client/seat.h"
|
#include "KWayland/Client/seat.h"
|
||||||
#include "KWayland/Client/surface.h"
|
#include "KWayland/Client/surface.h"
|
||||||
|
#include "KWayland/Client/keyboard.h"
|
||||||
#include "KWayland/Client/output.h"
|
#include "KWayland/Client/output.h"
|
||||||
|
|
||||||
#include "qwayland-input-method-unstable-v1.h"
|
#include "qwayland-input-method-unstable-v1.h"
|
||||||
#include "qwayland-server-text-input-unstable-v1.h"
|
#include "qwayland-server-text-input-unstable-v1.h"
|
||||||
|
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
|
||||||
using namespace KWaylandServer;
|
using namespace KWaylandServer;
|
||||||
|
|
||||||
class InputPanelSurface : public QObject, public QtWayland::zwp_input_panel_surface_v1
|
class InputPanelSurface : public QObject, public QtWayland::zwp_input_panel_surface_v1
|
||||||
|
@ -147,7 +150,7 @@ private Q_SLOTS:
|
||||||
void testContentHints();
|
void testContentHints();
|
||||||
void testContentPurpose_data();
|
void testContentPurpose_data();
|
||||||
void testContentPurpose();
|
void testContentPurpose();
|
||||||
|
void testKeyboardGrab();
|
||||||
private:
|
private:
|
||||||
KWayland::Client::ConnectionThread *m_connection;
|
KWayland::Client::ConnectionThread *m_connection;
|
||||||
KWayland::Client::EventQueue *m_queue;
|
KWayland::Client::EventQueue *m_queue;
|
||||||
|
@ -593,6 +596,30 @@ void TestInputMethodInterface::testContentPurpose()
|
||||||
QVERIFY(!m_inputMethod->context());
|
QVERIFY(!m_inputMethod->context());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestInputMethodInterface::testKeyboardGrab()
|
||||||
|
{
|
||||||
|
QVERIFY(m_inputMethodIface);
|
||||||
|
QSignalSpy inputMethodActivateSpy(m_inputMethod, &InputMethodV1::activated);
|
||||||
|
|
||||||
|
m_inputMethodIface->sendActivate();
|
||||||
|
QVERIFY(inputMethodActivateSpy.wait());
|
||||||
|
|
||||||
|
QSignalSpy keyboardGrabSpy(m_inputMethodIface->context(), &InputMethodContextV1Interface::keyboardGrabRequested);
|
||||||
|
InputMethodV1Context *imContext = m_inputMethod->context();
|
||||||
|
QVERIFY(imContext);
|
||||||
|
KWayland::Client::Keyboard *keyboard = new KWayland::Client::Keyboard(this);
|
||||||
|
keyboard->setup(imContext->grab_keyboard());
|
||||||
|
QVERIFY(keyboard->isValid());
|
||||||
|
QVERIFY(keyboardGrabSpy.count() || keyboardGrabSpy.wait());
|
||||||
|
|
||||||
|
QSignalSpy keyboardSpy(keyboard, &KWayland::Client::Keyboard::keyChanged);
|
||||||
|
m_inputMethodIface->context()->keyboardGrab()->sendKey(0, 0, KEY_F1, KeyboardKeyState::Pressed);
|
||||||
|
m_inputMethodIface->context()->keyboardGrab()->sendKey(0, 0, KEY_F1, KeyboardKeyState::Released);
|
||||||
|
keyboardSpy.wait();
|
||||||
|
QCOMPARE(keyboardSpy.count(), 2);
|
||||||
|
|
||||||
|
m_inputMethodIface->sendDeactivate();
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(TestInputMethodInterface)
|
QTEST_GUILESS_MAIN(TestInputMethodInterface)
|
||||||
#include "test_inputmethod_interface.moc"
|
#include "test_inputmethod_interface.moc"
|
||||||
|
|
|
@ -7,20 +7,88 @@
|
||||||
#include "inputmethod_v1_interface.h"
|
#include "inputmethod_v1_interface.h"
|
||||||
#include "seat_interface.h"
|
#include "seat_interface.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
#include "keyboard_interface.h"
|
||||||
|
#include "keyboard_interface_p.h"
|
||||||
#include "surface_interface.h"
|
#include "surface_interface.h"
|
||||||
#include "output_interface.h"
|
#include "output_interface.h"
|
||||||
#include "surfacerole_p.h"
|
#include "surfacerole_p.h"
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QTemporaryFile>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "qwayland-server-input-method-unstable-v1.h"
|
#include "qwayland-server-input-method-unstable-v1.h"
|
||||||
#include "qwayland-server-text-input-unstable-v1.h"
|
#include "qwayland-server-text-input-unstable-v1.h"
|
||||||
|
#include "qwayland-server-wayland.h"
|
||||||
|
|
||||||
namespace KWaylandServer
|
namespace KWaylandServer
|
||||||
{
|
{
|
||||||
|
|
||||||
static int s_version = 1;
|
static int s_version = 1;
|
||||||
|
|
||||||
|
class InputKeyboardV1InterfacePrivate : public QtWaylandServer::wl_keyboard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InputKeyboardV1InterfacePrivate()
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
InputMethodGrabV1::InputMethodGrabV1(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, d(new InputKeyboardV1InterfacePrivate)
|
||||||
|
{}
|
||||||
|
|
||||||
|
InputMethodGrabV1::~InputMethodGrabV1()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputMethodGrabV1::sendKeymap(const QByteArray &keymap)
|
||||||
|
{
|
||||||
|
QScopedPointer<QTemporaryFile> tmp(new QTemporaryFile());
|
||||||
|
if (!tmp->open()) {
|
||||||
|
qCWarning(KWAYLAND_SERVER) << "Failed to create keymap file:" << tmp->errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink(tmp->fileName().toUtf8().constData());
|
||||||
|
if (!tmp->resize(keymap.size())) {
|
||||||
|
qCWarning(KWAYLAND_SERVER) << "Failed to resize keymap file:" << tmp->errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar *address = tmp->map(0, keymap.size());
|
||||||
|
if (!address) {
|
||||||
|
qCWarning(KWAYLAND_SERVER) << "Failed to map keymap file:" << tmp->errorString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qstrncpy(reinterpret_cast<char *>(address), keymap.constData(), keymap.size() + 1);
|
||||||
|
tmp->unmap(address);
|
||||||
|
|
||||||
|
const auto resources = d->resourceMap();
|
||||||
|
for (auto r : resources) {
|
||||||
|
d->send_keymap(r->handle, QtWaylandServer::wl_keyboard::keymap_format::keymap_format_xkb_v1, tmp->handle(), tmp->size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputMethodGrabV1::sendKey(quint32 serial, quint32 timestamp, quint32 key, KeyboardKeyState state)
|
||||||
|
{
|
||||||
|
const auto resources = d->resourceMap();
|
||||||
|
for (auto r : resources) {
|
||||||
|
d->send_key(r->handle, serial, timestamp, key, quint32(state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputMethodGrabV1::sendModifiers(quint32 serial, quint32 depressed, quint32 latched, quint32 locked, quint32 group)
|
||||||
|
{
|
||||||
|
const auto resources = d->resourceMap();
|
||||||
|
for (auto r : resources) {
|
||||||
|
d->send_modifiers(r->handle, depressed, latched, locked, group, serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class InputMethodContextV1InterfacePrivate : public QtWaylandServer::zwp_input_method_context_v1
|
class InputMethodContextV1InterfacePrivate : public QtWaylandServer::zwp_input_method_context_v1
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -30,6 +98,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~InputMethodContextV1InterfacePrivate() {}
|
||||||
|
|
||||||
void zwp_input_method_context_v1_commit_string(Resource *, uint32_t serial, const QString &text) override
|
void zwp_input_method_context_v1_commit_string(Resource *, uint32_t serial, const QString &text) override
|
||||||
{
|
{
|
||||||
Q_EMIT q->commitString(serial, text);
|
Q_EMIT q->commitString(serial, text);
|
||||||
|
@ -80,9 +150,11 @@ public:
|
||||||
{
|
{
|
||||||
Q_EMIT q->keysym(serial, time, sym, state == WL_KEYBOARD_KEY_STATE_PRESSED, toQtModifiers(modifiers));
|
Q_EMIT q->keysym(serial, time, sym, state == WL_KEYBOARD_KEY_STATE_PRESSED, toQtModifiers(modifiers));
|
||||||
}
|
}
|
||||||
void zwp_input_method_context_v1_grab_keyboard(Resource *, uint32_t keyboard) override
|
void zwp_input_method_context_v1_grab_keyboard(Resource *resource, uint32_t id) override
|
||||||
{
|
{
|
||||||
Q_EMIT q->grabKeyboard(keyboard);
|
m_keyboardGrab.reset(new InputMethodGrabV1(q));
|
||||||
|
m_keyboardGrab->d->add(resource->client(), id, 1);
|
||||||
|
Q_EMIT q->keyboardGrabRequested(m_keyboardGrab.data());
|
||||||
}
|
}
|
||||||
void zwp_input_method_context_v1_key(Resource *, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) override
|
void zwp_input_method_context_v1_key(Resource *, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) override
|
||||||
{
|
{
|
||||||
|
@ -131,8 +203,8 @@ public:
|
||||||
wl_resource_destroy(resource->handle);
|
wl_resource_destroy(resource->handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
InputMethodContextV1Interface *const q;
|
InputMethodContextV1Interface *const q;
|
||||||
|
QScopedPointer<InputMethodGrabV1> m_keyboardGrab;
|
||||||
QVector<Qt::KeyboardModifiers> mods;
|
QVector<Qt::KeyboardModifiers> mods;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -265,6 +337,11 @@ void InputMethodContextV1Interface::sendSurroundingText(const QString &text, uin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InputMethodGrabV1 *InputMethodContextV1Interface::keyboardGrab() const
|
||||||
|
{
|
||||||
|
return d->m_keyboardGrab.get();
|
||||||
|
}
|
||||||
|
|
||||||
class InputPanelSurfaceV1InterfacePrivate : public QtWaylandServer::zwp_input_panel_surface_v1, public SurfaceRole
|
class InputPanelSurfaceV1InterfacePrivate : public QtWaylandServer::zwp_input_panel_surface_v1, public SurfaceRole
|
||||||
{
|
{
|
||||||
friend class InputPanelSurfaceV1Interface;
|
friend class InputPanelSurfaceV1Interface;
|
||||||
|
@ -417,3 +494,4 @@ InputMethodContextV1Interface *InputMethodV1Interface::context() const
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace KWaylandServer
|
||||||
class OutputInterface;
|
class OutputInterface;
|
||||||
class SurfaceInterface;
|
class SurfaceInterface;
|
||||||
class Display;
|
class Display;
|
||||||
|
class KeyboardInterface;
|
||||||
class InputPanelSurfaceV1Interface;
|
class InputPanelSurfaceV1Interface;
|
||||||
class InputMethodContextV1Interface;
|
class InputMethodContextV1Interface;
|
||||||
|
|
||||||
|
@ -25,6 +26,10 @@ class InputMethodV1InterfacePrivate;
|
||||||
class InputMethodContextV1InterfacePrivate;
|
class InputMethodContextV1InterfacePrivate;
|
||||||
class InputPanelV1InterfacePrivate;
|
class InputPanelV1InterfacePrivate;
|
||||||
class InputPanelSurfaceV1InterfacePrivate;
|
class InputPanelSurfaceV1InterfacePrivate;
|
||||||
|
class InputMethodGrabV1;
|
||||||
|
class InputKeyboardV1InterfacePrivate;
|
||||||
|
|
||||||
|
enum class KeyboardKeyState : quint32;
|
||||||
|
|
||||||
//This file's classes implment input_method_unstable_v1
|
//This file's classes implment input_method_unstable_v1
|
||||||
|
|
||||||
|
@ -73,6 +78,8 @@ public:
|
||||||
void sendCommitState(quint32 serial);
|
void sendCommitState(quint32 serial);
|
||||||
void sendPreferredLanguage(const QString &language);
|
void sendPreferredLanguage(const QString &language);
|
||||||
|
|
||||||
|
InputMethodGrabV1 *keyboardGrab() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void commitString(quint32 serial, const QString &text);
|
void commitString(quint32 serial, const QString &text);
|
||||||
void preeditString(quint32 serial, const QString &text, const QString &commit);
|
void preeditString(quint32 serial, const QString &text, const QString &commit);
|
||||||
|
@ -81,11 +88,11 @@ Q_SIGNALS:
|
||||||
void deleteSurroundingText(qint32 index, quint32 length);
|
void deleteSurroundingText(qint32 index, quint32 length);
|
||||||
void cursorPosition(qint32 index, qint32 anchor);
|
void cursorPosition(qint32 index, qint32 anchor);
|
||||||
void keysym(quint32 serial, quint32 time, quint32 sym, bool pressed, Qt::KeyboardModifiers modifiers);
|
void keysym(quint32 serial, quint32 time, quint32 sym, bool pressed, Qt::KeyboardModifiers modifiers);
|
||||||
void grabKeyboard(quint32 keyboard);
|
|
||||||
void key(quint32 serial, quint32 time, quint32 key, bool pressed);
|
void key(quint32 serial, quint32 time, quint32 key, bool pressed);
|
||||||
void modifiers(quint32 serial, quint32 mods_depressed, quint32 mods_latched, quint32 mods_locked, quint32 group);
|
void modifiers(quint32 serial, quint32 mods_depressed, quint32 mods_latched, quint32 mods_locked, quint32 group);
|
||||||
void language(quint32 serial, const QString &language);
|
void language(quint32 serial, const QString &language);
|
||||||
void textDirection(quint32 serial, Qt::LayoutDirection direction);
|
void textDirection(quint32 serial, Qt::LayoutDirection direction);
|
||||||
|
void keyboardGrabRequested(InputMethodGrabV1 *keyboardGrab);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class InputMethodV1Interface;
|
friend class InputMethodV1Interface;
|
||||||
|
@ -125,7 +132,6 @@ public:
|
||||||
};
|
};
|
||||||
Q_ENUM(Position)
|
Q_ENUM(Position)
|
||||||
|
|
||||||
quint32 id() const;
|
|
||||||
SurfaceInterface *surface() const;
|
SurfaceInterface *surface() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
@ -138,6 +144,27 @@ private:
|
||||||
QScopedPointer<InputPanelSurfaceV1InterfacePrivate> d;
|
QScopedPointer<InputPanelSurfaceV1InterfacePrivate> d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a wl_keyboard tailored for zwp_input_method_v1 use-cases
|
||||||
|
*/
|
||||||
|
class KWAYLANDSERVER_EXPORT InputMethodGrabV1 : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
~InputMethodGrabV1() override;
|
||||||
|
|
||||||
|
void sendKeymap(const QByteArray &content);
|
||||||
|
void sendKey(quint32 serial, quint32 timestamp, quint32 key, KeyboardKeyState state);
|
||||||
|
void sendModifiers(quint32 serial, quint32 depressed, quint32 latched, quint32 locked, quint32 group);
|
||||||
|
|
||||||
|
private:
|
||||||
|
InputMethodGrabV1(QObject *parent);
|
||||||
|
friend class InputPanelV1InterfacePrivate;
|
||||||
|
friend class InputMethodContextV1InterfacePrivate;
|
||||||
|
QScopedPointer<InputKeyboardV1InterfacePrivate> d;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(KWaylandServer::InputMethodV1Interface *)
|
Q_DECLARE_METATYPE(KWaylandServer::InputMethodV1Interface *)
|
||||||
|
Q_DECLARE_METATYPE(KWaylandServer::InputMethodGrabV1 *)
|
||||||
|
|
Loading…
Reference in a new issue