[server] Send key events to all wl_keyboard resources of a client

Summary:
This is what Weston does. With this change clients can create multiple
wl_keyboard instances and thus get events reported to all of them. This
will be needed to e.g. support KModifierKeyInfo on Wayland.

Similar changes are probably also needed for pointer and touch.

Test Plan:
Auto test for seat still passes. A custom change to kscreenlocker
is able to report whether caps lock is on with this change.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D2963
This commit is contained in:
Martin Gräßlin 2016-10-06 14:47:39 +02:00
parent 9e8f123513
commit 25dbc84dbc
2 changed files with 49 additions and 29 deletions

View file

@ -190,6 +190,23 @@ T *interfaceForSurface(SurfaceInterface *surface, const QVector<T*> &interfaces)
}
return nullptr;
}
template <typename T>
static
QVector<T *> interfacesForSurface(SurfaceInterface *surface, const QVector<T*> &interfaces)
{
QVector<T *> ret;
if (!surface) {
return ret;
}
for (auto it = interfaces.begin(); it != interfaces.end(); ++it) {
if ((*it)->client() == surface->client() && (*it)->resource()) {
ret << *it;
}
}
return ret;
}
}
PointerInterface *SeatInterface::Private::pointerForSurface(SurfaceInterface *surface) const
@ -197,9 +214,9 @@ PointerInterface *SeatInterface::Private::pointerForSurface(SurfaceInterface *su
return interfaceForSurface(surface, pointers);
}
KeyboardInterface *SeatInterface::Private::keyboardForSurface(SurfaceInterface *surface) const
QVector<KeyboardInterface *> SeatInterface::Private::keyboardsForSurface(SurfaceInterface *surface) const
{
return interfaceForSurface(surface, keyboards);
return interfacesForSurface(surface, keyboards);
}
TouchInterface *SeatInterface::Private::touchForSurface(SurfaceInterface *surface) const
@ -451,17 +468,13 @@ void SeatInterface::Private::getKeyboard(wl_client *client, wl_resource *resourc
keyboards << keyboard;
if (keys.focus.surface && keys.focus.surface->client() == clientConnection) {
// this is a keyboard for the currently focused keyboard surface
if (!keys.focus.keyboard) {
keys.focus.keyboard = keyboard;
keyboard->setFocusedSurface(keys.focus.surface, keys.focus.serial);
}
keys.focus.keyboards << keyboard;
keyboard->setFocusedSurface(keys.focus.surface, keys.focus.serial);
}
QObject::connect(keyboard, &QObject::destroyed, q,
[keyboard,this] {
keyboards.removeAt(keyboards.indexOf(keyboard));
if (keys.focus.keyboard == keyboard) {
keys.focus.keyboard = nullptr;
}
keys.focus.keyboards.removeOne(keyboard);
}
);
emit q->keyboardCreated(keyboard);
@ -774,9 +787,11 @@ void SeatInterface::pointerButtonPressed(quint32 button)
}
if (d->globalPointer.focus.pointer && d->globalPointer.focus.surface) {
d->globalPointer.focus.pointer->buttonPressed(button, serial);
if (d->globalPointer.focus.surface == d->keys.focus.surface && d->keys.focus.keyboard) {
if (d->globalPointer.focus.surface == d->keys.focus.surface) {
// update the focused child surface
d->keys.focus.keyboard->d_func()->focusChildSurface(d->globalPointer.focus.pointer->d_func()->focusedChildSurface, serial);
for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
(*it)->d_func()->focusChildSurface(d->globalPointer.focus.pointer->d_func()->focusedChildSurface, serial);
}
}
}
}
@ -832,8 +847,10 @@ void SeatInterface::keyPressed(quint32 key)
if (!d->updateKey(key, Private::Keyboard::State::Pressed)) {
return;
}
if (d->keys.focus.keyboard && d->keys.focus.surface) {
d->keys.focus.keyboard->keyPressed(key, d->keys.lastStateSerial);
if (d->keys.focus.surface) {
for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
(*it)->keyPressed(key, d->keys.lastStateSerial);
}
}
}
@ -844,8 +861,10 @@ void SeatInterface::keyReleased(quint32 key)
if (!d->updateKey(key, Private::Keyboard::State::Released)) {
return;
}
if (d->keys.focus.keyboard && d->keys.focus.surface) {
d->keys.focus.keyboard->keyReleased(key, d->keys.lastStateSerial);
if (d->keys.focus.surface) {
for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
(*it)->keyReleased(key, d->keys.lastStateSerial);
}
}
}
@ -859,19 +878,15 @@ void SeatInterface::setFocusedKeyboardSurface(SurfaceInterface *surface)
{
Q_D();
const quint32 serial = d->display->nextSerial();
if (d->keys.focus.keyboard) {
d->keys.focus.keyboard->setFocusedSurface(nullptr, serial);
for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
(*it)->setFocusedSurface(nullptr, serial);
}
if (d->keys.focus.surface) {
disconnect(d->keys.focus.destroyConnection);
}
d->keys.focus = Private::Keyboard::Focus();
d->keys.focus.surface = surface;
KeyboardInterface *k = d->keyboardForSurface(surface);
if (k && !k->resource()) {
k = nullptr;
}
d->keys.focus.keyboard = k;
d->keys.focus.keyboards = d->keyboardsForSurface(surface);
if (d->keys.focus.surface) {
d->keys.focus.destroyConnection = connect(surface, &QObject::destroyed, this,
[this] {
@ -890,8 +905,8 @@ void SeatInterface::setFocusedKeyboardSurface(SurfaceInterface *surface)
}
}
}
if (k) {
k->setFocusedSurface(surface, serial);
for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
(*it)->setFocusedSurface(surface, serial);
}
// focused text input surface follows keyboard
if (hasKeyboard()) {
@ -928,8 +943,10 @@ void SeatInterface::updateKeyboardModifiers(quint32 depressed, quint32 latched,
}
const quint32 serial = d->display->nextSerial();
d->keys.modifiers.serial = serial;
if (d->keys.focus.keyboard && d->keys.focus.surface) {
d->keys.focus.keyboard->updateModifiers(depressed, latched, locked, group, serial);
if (d->keys.focus.surface) {
for (auto it = d->keys.focus.keyboards.constBegin(), end = d->keys.focus.keyboards.constEnd(); it != end; ++it) {
(*it)->updateModifiers(depressed, latched, locked, group, serial);
}
}
}
@ -1018,7 +1035,10 @@ QVector< quint32 > SeatInterface::pressedKeys() const
KeyboardInterface *SeatInterface::focusedKeyboard() const
{
Q_D();
return d->keys.focus.keyboard;
if (d->keys.focus.keyboards.isEmpty()) {
return nullptr;
}
return d->keys.focus.keyboards.first();
}
void SeatInterface::cancelTouchSequence()

View file

@ -44,7 +44,7 @@ public:
void sendCapabilities(wl_resource *r);
void sendName(wl_resource *r);
PointerInterface *pointerForSurface(SurfaceInterface *surface) const;
KeyboardInterface *keyboardForSurface(SurfaceInterface *surface) const;
QVector<KeyboardInterface *> keyboardsForSurface(SurfaceInterface *surface) const;
TouchInterface *touchForSurface(SurfaceInterface *surface) const;
DataDeviceInterface *dataDeviceForSurface(SurfaceInterface *surface) const;
TextInputInterface *textInputForSurface(SurfaceInterface *surface) const;
@ -111,7 +111,7 @@ public:
Modifiers modifiers;
struct Focus {
SurfaceInterface *surface = nullptr;
KeyboardInterface *keyboard = nullptr;
QVector<KeyboardInterface*> keyboards;
QMetaObject::Connection destroyConnection;
quint32 serial = 0;
DataDeviceInterface *selection = nullptr;