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/seat.h"
|
||||
#include "KWayland/Client/surface.h"
|
||||
#include "KWayland/Client/keyboard.h"
|
||||
#include "KWayland/Client/output.h"
|
||||
|
||||
#include "qwayland-input-method-unstable-v1.h"
|
||||
#include "qwayland-server-text-input-unstable-v1.h"
|
||||
|
||||
#include <linux/input-event-codes.h>
|
||||
|
||||
using namespace KWaylandServer;
|
||||
|
||||
class InputPanelSurface : public QObject, public QtWayland::zwp_input_panel_surface_v1
|
||||
|
@ -147,7 +150,7 @@ private Q_SLOTS:
|
|||
void testContentHints();
|
||||
void testContentPurpose_data();
|
||||
void testContentPurpose();
|
||||
|
||||
void testKeyboardGrab();
|
||||
private:
|
||||
KWayland::Client::ConnectionThread *m_connection;
|
||||
KWayland::Client::EventQueue *m_queue;
|
||||
|
@ -593,6 +596,30 @@ void TestInputMethodInterface::testContentPurpose()
|
|||
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)
|
||||
#include "test_inputmethod_interface.moc"
|
||||
|
|
|
@ -7,20 +7,88 @@
|
|||
#include "inputmethod_v1_interface.h"
|
||||
#include "seat_interface.h"
|
||||
#include "display.h"
|
||||
#include "keyboard_interface.h"
|
||||
#include "keyboard_interface_p.h"
|
||||
#include "surface_interface.h"
|
||||
#include "output_interface.h"
|
||||
#include "surfacerole_p.h"
|
||||
#include "logging.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "qwayland-server-input-method-unstable-v1.h"
|
||||
#include "qwayland-server-text-input-unstable-v1.h"
|
||||
#include "qwayland-server-wayland.h"
|
||||
|
||||
namespace KWaylandServer
|
||||
{
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
@ -30,6 +98,8 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
~InputMethodContextV1InterfacePrivate() {}
|
||||
|
||||
void zwp_input_method_context_v1_commit_string(Resource *, uint32_t serial, const QString &text) override
|
||||
{
|
||||
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));
|
||||
}
|
||||
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
|
||||
{
|
||||
|
@ -131,8 +203,8 @@ public:
|
|||
wl_resource_destroy(resource->handle);
|
||||
}
|
||||
|
||||
private:
|
||||
InputMethodContextV1Interface *const q;
|
||||
QScopedPointer<InputMethodGrabV1> m_keyboardGrab;
|
||||
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
|
||||
{
|
||||
friend class InputPanelSurfaceV1Interface;
|
||||
|
@ -417,3 +494,4 @@ InputMethodContextV1Interface *InputMethodV1Interface::context() const
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace KWaylandServer
|
|||
class OutputInterface;
|
||||
class SurfaceInterface;
|
||||
class Display;
|
||||
class KeyboardInterface;
|
||||
class InputPanelSurfaceV1Interface;
|
||||
class InputMethodContextV1Interface;
|
||||
|
||||
|
@ -25,6 +26,10 @@ class InputMethodV1InterfacePrivate;
|
|||
class InputMethodContextV1InterfacePrivate;
|
||||
class InputPanelV1InterfacePrivate;
|
||||
class InputPanelSurfaceV1InterfacePrivate;
|
||||
class InputMethodGrabV1;
|
||||
class InputKeyboardV1InterfacePrivate;
|
||||
|
||||
enum class KeyboardKeyState : quint32;
|
||||
|
||||
//This file's classes implment input_method_unstable_v1
|
||||
|
||||
|
@ -73,6 +78,8 @@ public:
|
|||
void sendCommitState(quint32 serial);
|
||||
void sendPreferredLanguage(const QString &language);
|
||||
|
||||
InputMethodGrabV1 *keyboardGrab() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void commitString(quint32 serial, const QString &text);
|
||||
void preeditString(quint32 serial, const QString &text, const QString &commit);
|
||||
|
@ -81,11 +88,11 @@ Q_SIGNALS:
|
|||
void deleteSurroundingText(qint32 index, quint32 length);
|
||||
void cursorPosition(qint32 index, qint32 anchor);
|
||||
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 modifiers(quint32 serial, quint32 mods_depressed, quint32 mods_latched, quint32 mods_locked, quint32 group);
|
||||
void language(quint32 serial, const QString &language);
|
||||
void textDirection(quint32 serial, Qt::LayoutDirection direction);
|
||||
void keyboardGrabRequested(InputMethodGrabV1 *keyboardGrab);
|
||||
|
||||
private:
|
||||
friend class InputMethodV1Interface;
|
||||
|
@ -125,7 +132,6 @@ public:
|
|||
};
|
||||
Q_ENUM(Position)
|
||||
|
||||
quint32 id() const;
|
||||
SurfaceInterface *surface() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -138,6 +144,27 @@ private:
|
|||
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::InputMethodGrabV1 *)
|
||||
|
|
Loading…
Reference in a new issue