Commit 8a6d17f2 authored by Adrien Faveraux's avatar Adrien Faveraux Committed by Bhushan Shah
Browse files

move keyboard to the new approach and refactor the keyboard_interface

- Get rid of the KF5 deprecated methods related to keymap,
  kwayland-server is not source compatible with kwayland, so we don't
  need to keep the deprecated methods
- Move the key repeat, modifiers and keymap handling fully into the
  KeyboardInterface.
- Get rid of some of the keyboard related code base from the
  seat_interface.

Co-Author: Bhushan Shah <bshah@kde.org>
parent 42246b78
......@@ -77,7 +77,6 @@ private Q_SLOTS:
void testTouch();
void testDisconnect();
void testKeymap();
void testKeymapThroughFd();
private:
KWaylandServer::Display *m_display;
......@@ -1518,7 +1517,9 @@ void TestWaylandSeat::testKeyboard()
m_seatInterface->setFocusedKeyboardSurface(serverSurface);
// no keyboard yet
QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface);
QVERIFY(!m_seatInterface->focusedKeyboard());
QSignalSpy keyboardCreatedSpy(m_seatInterface, &SeatInterface::keyboardCreated);
QVERIFY(keyboardSpy.isValid());
Keyboard *keyboard = m_seat->createKeyboard(m_seat);
QSignalSpy repeatInfoSpy(keyboard, &Keyboard::keyRepeatChanged);
......@@ -1528,9 +1529,11 @@ void TestWaylandSeat::testKeyboard()
QCOMPARE(keyboard->isKeyRepeatEnabled(), false);
QCOMPARE(keyboard->keyRepeatDelay(), 0);
QCOMPARE(keyboard->keyRepeatRate(), 0);
QVERIFY(keyboardCreatedSpy.wait());
QVERIFY(repeatInfoSpy.wait());
wl_display_flush(m_connection->display());
QTest::qWait(100);
auto serverKeyboard = m_seatInterface->focusedKeyboard();
auto serverKeyboard = m_seatInterface->keyboard();
QVERIFY(serverKeyboard);
// we should get the repeat info announced
......@@ -1541,7 +1544,6 @@ void TestWaylandSeat::testKeyboard()
// let's change repeat in server
m_seatInterface->setKeyRepeatInfo(25, 660);
m_seatInterface->focusedKeyboard()->client()->flush();
QVERIFY(repeatInfoSpy.wait());
QCOMPARE(repeatInfoSpy.count(), 2);
QCOMPARE(keyboard->isKeyRepeatEnabled(), true);
......@@ -1562,7 +1564,7 @@ void TestWaylandSeat::testKeyboard()
QVERIFY(enteredSpy.isValid());
m_seatInterface->setFocusedKeyboardSurface(serverSurface);
QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface);
QCOMPARE(m_seatInterface->focusedKeyboard()->focusedSurface(), serverSurface);
QCOMPARE(m_seatInterface->keyboard()->focusedSurface(), serverSurface);
// we get the modifiers sent after the enter
QVERIFY(modifierSpy.wait());
......@@ -1638,7 +1640,6 @@ void TestWaylandSeat::testKeyboard()
QVERIFY(leftSpy.isValid());
m_seatInterface->setFocusedKeyboardSurface(nullptr);
QVERIFY(!m_seatInterface->focusedKeyboardSurface());
QVERIFY(!m_seatInterface->focusedKeyboard());
QVERIFY(leftSpy.wait());
QCOMPARE(leftSpy.count(), 1);
// TODO: get through API
......@@ -1651,7 +1652,7 @@ void TestWaylandSeat::testKeyboard()
m_seatInterface->setFocusedKeyboardSurface(serverSurface);
QVERIFY(modifierSpy.wait());
QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface);
QCOMPARE(m_seatInterface->focusedKeyboard()->focusedSurface(), serverSurface);
QCOMPARE(m_seatInterface->keyboard()->focusedSurface(), serverSurface);
QCOMPARE(enteredSpy.count(), 2);
QCOMPARE(keyboard->enteredSurface(), s);
......@@ -1665,7 +1666,6 @@ void TestWaylandSeat::testKeyboard()
QVERIFY(leftSpy.wait());
QCOMPARE(serverSurfaceDestroyedSpy.count(), 1);
QVERIFY(!m_seatInterface->focusedKeyboardSurface());
QVERIFY(!m_seatInterface->focusedKeyboard());
QVERIFY(!serverKeyboard->focusedSurface());
// let's create a Surface again
......@@ -1676,57 +1676,7 @@ void TestWaylandSeat::testKeyboard()
QVERIFY(serverSurface);
m_seatInterface->setFocusedKeyboardSurface(serverSurface);
QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface);
QCOMPARE(m_seatInterface->focusedKeyboard(), serverKeyboard);
// delete the Keyboard
QSignalSpy unboundSpy(serverKeyboard, &Resource::unbound);
QVERIFY(unboundSpy.isValid());
QSignalSpy destroyedSpy(serverKeyboard, &Resource::destroyed);
QVERIFY(destroyedSpy.isValid());
delete keyboard;
QVERIFY(unboundSpy.wait());
QCOMPARE(unboundSpy.count(), 1);
QCOMPARE(destroyedSpy.count(), 0);
// verify that calling into the Keyboard related functionality doesn't crash
m_seatInterface->setTimestamp(9);
m_seatInterface->keyPressed(KEY_F2);
m_seatInterface->setTimestamp(10);
m_seatInterface->keyReleased(KEY_F2);
m_seatInterface->setKeyRepeatInfo(30, 560);
m_seatInterface->setKeyRepeatInfo(25, 660);
m_seatInterface->updateKeyboardModifiers(5, 6, 7, 8);
m_seatInterface->setFocusedKeyboardSurface(nullptr);
m_seatInterface->setFocusedKeyboardSurface(serverSurface);
QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface);
QVERIFY(!m_seatInterface->focusedKeyboard());
QVERIFY(destroyedSpy.wait());
QCOMPARE(destroyedSpy.count(), 1);
// create a second Keyboard to verify that repeat info is announced properly
Keyboard *keyboard2 = m_seat->createKeyboard(m_seat);
QSignalSpy repeatInfoSpy2(keyboard2, &Keyboard::keyRepeatChanged);
QVERIFY(repeatInfoSpy2.isValid());
QVERIFY(keyboard2->isValid());
QCOMPARE(keyboard2->isKeyRepeatEnabled(), false);
QCOMPARE(keyboard2->keyRepeatDelay(), 0);
QCOMPARE(keyboard2->keyRepeatRate(), 0);
wl_display_flush(m_connection->display());
QVERIFY(repeatInfoSpy2.wait());
QCOMPARE(keyboard2->isKeyRepeatEnabled(), true);
QCOMPARE(keyboard2->keyRepeatRate(), 25);
QCOMPARE(keyboard2->keyRepeatDelay(), 660);
QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface);
serverKeyboard = m_seatInterface->focusedKeyboard();
QVERIFY(serverKeyboard);
QSignalSpy keyboard2DestroyedSpy(serverKeyboard, &QObject::destroyed);
QVERIFY(keyboard2DestroyedSpy.isValid());
delete keyboard2;
QVERIFY(keyboard2DestroyedSpy.wait());
// this should have unset it on the server
QVERIFY(!m_seatInterface->focusedKeyboard());
// but not the surface
QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface);
QCOMPARE(m_seatInterface->keyboard(), serverKeyboard);
}
void TestWaylandSeat::testCast()
......@@ -1817,6 +1767,7 @@ void TestWaylandSeat::testSelection()
Registry registry;
QSignalSpy dataDeviceManagerSpy(&registry, SIGNAL(dataDeviceManagerAnnounced(quint32,quint32)));
QVERIFY(dataDeviceManagerSpy.isValid());
m_seatInterface->setHasKeyboard(true);
registry.setEventQueue(m_queue);
registry.create(m_connection->display());
QVERIFY(registry.isValid());
......@@ -1843,7 +1794,6 @@ void TestWaylandSeat::testSelection()
QVERIFY(!m_seatInterface->selection());
m_seatInterface->setFocusedKeyboardSurface(serverSurface);
QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface);
QVERIFY(!m_seatInterface->focusedKeyboard());
QVERIFY(selectionClearedSpy.wait());
QVERIFY(selectionSpy.isEmpty());
QVERIFY(!selectionClearedSpy.isEmpty());
......@@ -1872,7 +1822,6 @@ void TestWaylandSeat::testSelection()
// unset the keyboard focus
m_seatInterface->setFocusedKeyboardSurface(nullptr);
QVERIFY(!m_seatInterface->focusedKeyboardSurface());
QVERIFY(!m_seatInterface->focusedKeyboard());
serverSurface->client()->flush();
QCoreApplication::processEvents();
QCoreApplication::processEvents();
......@@ -1928,6 +1877,7 @@ void TestWaylandSeat::testDataDeviceForKeyboardSurface()
QScopedPointer<DataDeviceManagerInterface> ddmi(m_display->createDataDeviceManager());
QSignalSpy ddiCreatedSpy(ddmi.data(), &DataDeviceManagerInterface::dataDeviceCreated);
QVERIFY(ddiCreatedSpy.isValid());
m_seatInterface->setHasKeyboard(true);
// create a second Wayland client connection to use it for setSelection
auto c = new ConnectionThread;
......@@ -2273,22 +2223,11 @@ void TestWaylandSeat::testDisconnect()
QVERIFY(pointerDestroyedSpy.isValid());
QSignalSpy touchDestroyedSpy(serverTouch, &QObject::destroyed);
QVERIFY(touchDestroyedSpy.isValid());
QSignalSpy clientDisconnectedSpy(serverKeyboard->client(), &ClientConnection::disconnected);
QVERIFY(clientDisconnectedSpy.isValid());
if (m_connection) {
m_connection->deleteLater();
m_connection = nullptr;
}
QVERIFY(clientDisconnectedSpy.wait());
QCOMPARE(clientDisconnectedSpy.count(), 1);
QCOMPARE(keyboardDestroyedSpy.count(), 0);
QCOMPARE(pointerDestroyedSpy.count(), 0);
QCOMPARE(touchDestroyedSpy.count(), 0);
QVERIFY(keyboardDestroyedSpy.wait());
QCOMPARE(keyboardDestroyedSpy.count(), 1);
QCOMPARE(pointerDestroyedSpy.count(), 1);
QCOMPARE(touchDestroyedSpy.count(), 1);
keyboard->destroy();
pointer->destroy();
......@@ -2313,6 +2252,17 @@ void TestWaylandSeat::testKeymap()
QVERIFY(keyboardChangedSpy.wait());
QScopedPointer<Keyboard> keyboard(m_seat->createKeyboard());
// create surface
QSignalSpy surfaceCreatedSpy(m_compositorInterface, SIGNAL(surfaceCreated(KWaylandServer::SurfaceInterface*)));
QVERIFY(surfaceCreatedSpy.isValid());
QScopedPointer<Surface> surface(m_compositor->createSurface());
QVERIFY(surface->isValid());
QVERIFY(surfaceCreatedSpy.wait());
auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface*>();
QVERIFY(!m_seatInterface->selection());
m_seatInterface->setFocusedKeyboardSurface(serverSurface);
QSignalSpy keymapChangedSpy(keyboard.data(), &Keyboard::keymapChanged);
QVERIFY(keymapChangedSpy.isValid());
......@@ -2340,59 +2290,5 @@ void TestWaylandSeat::testKeymap()
QCOMPARE(qstrcmp(address, "bar"), 0);
}
void TestWaylandSeat::testKeymapThroughFd()
{
#if KWAYLANDSERVER_BUILD_DEPRECATED_SINCE(5, 69)
using namespace KWayland::Client;
using namespace KWaylandServer;
m_seatInterface->setHasKeyboard(true);
QSignalSpy keyboardChangedSpy(m_seat, &Seat::hasKeyboardChanged);
QVERIFY(keyboardChangedSpy.isValid());
QVERIFY(keyboardChangedSpy.wait());
QScopedPointer<Keyboard> keyboard(m_seat->createKeyboard());
QSignalSpy keymapChangedSpy(keyboard.data(), &Keyboard::keymapChanged);
QVERIFY(keymapChangedSpy.isValid());
QTemporaryFile serverFile;
QVERIFY(serverFile.open());
QByteArray data = QByteArrayLiteral("foobar");
QVERIFY(serverFile.resize(data.size() + 1));
uchar *serverAddress = serverFile.map(0, data.size() + 1);
QVERIFY(serverAddress);
QVERIFY(qstrncpy(reinterpret_cast<char *>(serverAddress), data.constData(), data.size() + 1));
m_seatInterface->setKeymap(serverFile.handle(), data.size());
QVERIFY(keymapChangedSpy.wait());
int fd = keymapChangedSpy.first().first().toInt();
QVERIFY(fd != -1);
QCOMPARE(keymapChangedSpy.first().last().value<quint32>(), 6u);
QFile file;
QVERIFY(file.open(fd, QIODevice::ReadOnly));
const char *address = reinterpret_cast<char*>(file.map(0, keymapChangedSpy.first().last().value<quint32>()));
QVERIFY(address);
QCOMPARE(qstrcmp(address, "foobar"), 0);
QScopedPointer<Keyboard> keyboard2(m_seat->createKeyboard());
QSignalSpy keymapChangedSpy2(keyboard2.data(), &Keyboard::keymapChanged);
QVERIFY(keymapChangedSpy2.isValid());
QVERIFY(keymapChangedSpy2.wait());
int fd2 = keymapChangedSpy2.first().first().toInt();
QVERIFY(fd2 != -1);
QCOMPARE(keymapChangedSpy2.first().last().value<quint32>(), 6u);
QFile file2;
QVERIFY(file2.open(fd2, QIODevice::ReadWrite));
char *address2 = reinterpret_cast<char*>(file2.map(0, keymapChangedSpy2.first().last().value<quint32>()));
QVERIFY(address2);
QCOMPARE(qstrcmp(address2, "foobar"), 0);
address2[0] = 'g';
QCOMPARE(qstrcmp(address2, "goobar"), 0);
QCOMPARE(qstrcmp(address, "foobar"), 0);
#endif
}
QTEST_GUILESS_MAIN(TestWaylandSeat)
#include "test_wayland_seat.moc"
......@@ -173,15 +173,16 @@ void TestWaylandServerSeat::testRepeatInfo()
display.setSocketName(s_socketName);
display.start();
SeatInterface *seat = display.createSeat();
QCOMPARE(seat->keyRepeatRate(), 0);
QCOMPARE(seat->keyRepeatDelay(), 0);
seat->setHasKeyboard(true);
QCOMPARE(seat->keyboard()->keyRepeatRate(), 0);
QCOMPARE(seat->keyboard()->keyRepeatDelay(), 0);
seat->setKeyRepeatInfo(25, 660);
QCOMPARE(seat->keyRepeatRate(), 25);
QCOMPARE(seat->keyRepeatDelay(), 660);
QCOMPARE(seat->keyboard()->keyRepeatRate(), 25);
QCOMPARE(seat->keyboard()->keyRepeatDelay(), 660);
// setting negative values should result in 0
seat->setKeyRepeatInfo(-25, -660);
QCOMPARE(seat->keyRepeatRate(), 0);
QCOMPARE(seat->keyRepeatDelay(), 0);
QCOMPARE(seat->keyboard()->keyRepeatRate(), 0);
QCOMPARE(seat->keyboard()->keyRepeatDelay(), 0);
}
void TestWaylandServerSeat::testMultiple()
......
......@@ -3,77 +3,79 @@
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "keyboard_interface.h"
#include "keyboard_interface_p.h"
#include "display.h"
#include "seat_interface.h"
#include "seat_interface_p.h"
#include "surface_interface.h"
#include "compositor_interface.h"
// Qt
#include <QTemporaryFile>
#include <QVector>
// Wayland
#include <wayland-server.h>
#include <unistd.h>
namespace KWaylandServer
{
KeyboardInterface::Private::Private(SeatInterface *s, wl_resource *parentResource, KeyboardInterface *q)
: Resource::Private(q, s, parentResource, &wl_keyboard_interface, &s_interface)
, seat(s)
KeyboardInterfacePrivate::KeyboardInterfacePrivate(SeatInterface *s)
: seat(s)
{
}
void KeyboardInterface::Private::focusChildSurface(const QPointer<SurfaceInterface> &childSurface, quint32 serial)
void KeyboardInterfacePrivate::keyboard_bind_resource(Resource *resource)
{
if (resource->version() >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
send_repeat_info(resource->handle, keyRepeat.charactersPerSecond, keyRepeat.delay);
}
if (!keymap.isNull()) {
send_keymap(resource->handle, keymap_format::keymap_format_xkb_v1, keymap->handle(), keymap->size());
}
}
QList<KeyboardInterfacePrivate::Resource *> KeyboardInterfacePrivate::keyboardsForClient(ClientConnection *client) const
{
return resourceMap().values(client->client());
}
void KeyboardInterfacePrivate::focusChildSurface(SurfaceInterface *childSurface, quint32 serial)
{
if (focusedChildSurface == childSurface) {
return;
}
sendLeave(focusedChildSurface.data(), serial);
focusedChildSurface = childSurface;
focusedChildSurface = QPointer<SurfaceInterface>(childSurface);
sendEnter(focusedChildSurface.data(), serial);
}
void KeyboardInterface::Private::sendLeave(SurfaceInterface *surface, quint32 serial)
void KeyboardInterfacePrivate::sendLeave(SurfaceInterface *surface, quint32 serial)
{
if (surface && resource && surface->resource()) {
wl_keyboard_send_leave(resource, serial, surface->resource());
if (!surface) {
return;
}
}
void KeyboardInterface::Private::sendEnter(SurfaceInterface *surface, quint32 serial)
{
wl_array keys;
wl_array_init(&keys);
const auto states = seat->pressedKeys();
for (auto it = states.constBegin(); it != states.constEnd(); ++it) {
uint32_t *k = reinterpret_cast<uint32_t*>(wl_array_add(&keys, sizeof(uint32_t)));
*k = *it;
const QList<Resource *> keyboards = keyboardsForClient(surface->client());
for (Resource *keyboardResource : keyboards) {
send_leave(keyboardResource->handle, serial, surface->resource());
}
wl_keyboard_send_enter(resource, serial, surface->resource(), &keys);
wl_array_release(&keys);
sendModifiers();
}
#ifndef K_DOXYGEN
const struct wl_keyboard_interface KeyboardInterface::Private::s_interface {
resourceDestroyedCallback
};
#endif
KeyboardInterface::KeyboardInterface(SeatInterface *parent, wl_resource *parentResource)
: Resource(new Private(parent, parentResource, this))
void KeyboardInterfacePrivate::sendEnter(SurfaceInterface *surface, quint32 serial)
{
}
if (!surface) {
return;
}
const auto states = pressedKeys();
QByteArray data = QByteArray::fromRawData(
reinterpret_cast<const char*>(states.constData()),
sizeof(quint32) * states.size()
);
KeyboardInterface::~KeyboardInterface() = default;
const QList<Resource *> keyboards = keyboardsForClient(surface->client());
for (Resource *keyboardResource : keyboards) {
send_enter(keyboardResource->handle, serial, surface->resource(), data);
}
void KeyboardInterface::setKeymap(int fd, quint32 size)
{
Q_D();
d->sendKeymap(fd, size);
sendModifiers();
}
void KeyboardInterface::setKeymap(const QByteArray &content)
......@@ -94,35 +96,58 @@ void KeyboardInterface::setKeymap(const QByteArray &content)
return;
}
tmp->unmap(address);
Q_D();
d->sendKeymap(tmp->handle(), content.size());
d->keymap.swap(tmp);
}
void KeyboardInterface::Private::sendKeymap(int fd, quint32 size)
void KeyboardInterfacePrivate::sendKeymap(int fd, quint32 size)
{
if (!resource) {
return;
const QList<Resource *> keyboards = resourceMap().values();
for (Resource *keyboardResource : keyboards) {
send_keymap(keyboardResource->handle, keymap_format::keymap_format_xkb_v1, fd, size);
}
wl_keyboard_send_keymap(resource, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, size);
}
void KeyboardInterface::Private::sendModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group, quint32 serial)
void KeyboardInterfacePrivate::sendModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group, quint32 serial)
{
if (!resource) {
if (!focusedSurface) {
return;
}
wl_keyboard_send_modifiers(resource, serial, depressed, latched, locked, group);
const QList<Resource *> keyboards = keyboardsForClient(focusedSurface->client());
for (Resource *keyboardResource : keyboards) {
send_modifiers(keyboardResource->handle, serial, depressed, latched, locked, group);
}
}
bool KeyboardInterfacePrivate::updateKey(quint32 key, State state)
{
auto it = states.find(key);
if (it == states.end()) {
states.insert(key, state);
return true;
}
if (it.value() == state) {
return false;
}
it.value() = state;
return true;
}
void KeyboardInterface::Private::sendModifiers()
KeyboardInterface::KeyboardInterface(SeatInterface *seat)
: d(new KeyboardInterfacePrivate(seat))
{
sendModifiers(seat->depressedModifiers(), seat->latchedModifiers(), seat->lockedModifiers(), seat->groupModifiers(), seat->lastModifiersSerial());
}
KeyboardInterface::~KeyboardInterface() = default;
void KeyboardInterfacePrivate::sendModifiers()
{
sendModifiers(modifiers.depressed, modifiers.latched, modifiers.locked, modifiers.group, modifiers.serial);
}
void KeyboardInterface::setFocusedSurface(SurfaceInterface *surface, quint32 serial)
{
Q_D();
d->sendLeave(d->focusedChildSurface, serial);
disconnect(d->destroyConnection);
d->focusedChildSurface.clear();
......@@ -132,10 +157,8 @@ void KeyboardInterface::setFocusedSurface(SurfaceInterface *surface, quint32 ser
}
d->destroyConnection = connect(d->focusedSurface, &SurfaceInterface::aboutToBeDestroyed, this,
[this] {
Q_D();
if (d->resource) {
wl_keyboard_send_leave(d->resource, d->global->display()->nextSerial(), d->focusedSurface->resource());
}
CompositorInterface *compositor = d->focusedChildSurface->compositor();
d->sendLeave(d->focusedChildSurface.data(), compositor->display()->nextSerial());
d->focusedSurface = nullptr;
d->focusedChildSurface.clear();
}
......@@ -143,58 +166,101 @@ void KeyboardInterface::setFocusedSurface(SurfaceInterface *surface, quint32 ser
d->focusedChildSurface = QPointer<SurfaceInterface>(surface);
d->sendEnter(d->focusedSurface, serial);
d->client->flush();
}
void KeyboardInterface::keyPressed(quint32 key, quint32 serial)
QVector<quint32> KeyboardInterfacePrivate::pressedKeys() const
{
Q_D();
if (!d->resource) {
return;
QVector<quint32> keys;
for (auto it = states.constBegin(); it != states.constEnd(); ++it) {
if (it.value() == State::Pressed) {
keys << it.key();
}
}
Q_ASSERT(d->focusedSurface);
wl_keyboard_send_key(d->resource, serial, d->seat->timestamp(), key, WL_KEYBOARD_KEY_STATE_PRESSED);
return keys;
}
void KeyboardInterface::keyReleased(quint32 key, quint32 serial)
void KeyboardInterface::keyPressed(quint32 key)
{
Q_D();
if (!d->resource) {
if (!d->focusedSurface) {
return;
}
Q_ASSERT(d->focusedSurface);
wl_keyboard_send_key(d->resource, serial, d->seat->timestamp(), key, WL_KEYBOARD_KEY_STATE_RELEASED);
if (!d->updateKey(key, KeyboardInterfacePrivate::State::Pressed)) {
return;
}
const QList<KeyboardInterfacePrivate::Resource *> keyboards = d->keyboardsForClient(d->focusedSurface->client());
const quint32 serial = d->seat->d_func()->nextSerial();
for (KeyboardInterfacePrivate::Resource *keyboardResource : keyboards) {
d->send_key(keyboardResource->handle, serial, d->seat->timestamp(), key, KeyboardInterfacePrivate::key_state::key_state_pressed);
}
}
void KeyboardInterface::updateModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group, quint32 serial)
void KeyboardInterface::keyReleased(quint32 key)
{
Q_D();
Q_ASSERT(d->focusedSurface);
d->sendModifiers(depressed, latched, locked, group, serial);
if (!d->focusedSurface) {
return;
}
if (!d->updateKey(key, KeyboardInterfacePrivate::State::Released)) {
return;
}
const QList<KeyboardInterfacePrivate::Resource *> keyboards = d->keyboardsForClient(d->focusedSurface->client());
const quint32 serial = d->seat->d_func()->nextSerial();
for (KeyboardInterfacePrivate::Resource *keyboardResource : keyboards) {
d->send_key(keyboardResource->handle, serial, d->seat->timestamp(), key, KeyboardInterfacePrivate::key_state::key_state_released);
}
}
void KeyboardInterface::repeatInfo(qint32 charactersPerSecond, qint32 delay)
void KeyboardInterface::updateModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group)
{
Q_D();
if (!d->resource) {
if (!d->focusedSurface) {
return;
}
if (wl_resource_get_version(d->resource) < WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
// only supported since version 4
bool changed = false;
#define UPDATE( value ) \
if (d->modifiers.value != value) { \
d->modifiers.value = value; \
changed = true; \
}
UPDATE(depressed)
UPDATE(latched)
UPDATE(locked)
UPDATE(group)
if (!changed) {
return;
}
wl_keyboard_send_repeat_info(d->resource, charactersPerSecond, delay);
d->modifiers.serial = d->seat->d_func()->nextSerial();
d->sendModifiers(depressed, latched, locked, group, d->modifiers.serial);
}
void KeyboardInterface::repeatInfo(qint32 charactersPerSecond, qint32 delay)
{
d->keyRepeat.charactersPerSecond = qMax(charactersPerSecond, 0);
d->keyRepeat.delay = qMax(delay, 0);