File indexing completed on 2024-05-19 16:35:20

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #include "display.h"
0007 #include "keyboard_interface_p.h"
0008 #include "seat_interface.h"
0009 #include "seat_interface_p.h"
0010 #include "surface_interface.h"
0011 #include "utils/common.h"
0012 // Qt
0013 #include <QVector>
0014 
0015 #include <unistd.h>
0016 
0017 namespace KWaylandServer
0018 {
0019 KeyboardInterfacePrivate::KeyboardInterfacePrivate(SeatInterface *s)
0020     : seat(s)
0021 {
0022 }
0023 
0024 void KeyboardInterfacePrivate::keyboard_release(Resource *resource)
0025 {
0026     wl_resource_destroy(resource->handle);
0027 }
0028 
0029 void KeyboardInterfacePrivate::keyboard_bind_resource(Resource *resource)
0030 {
0031     const ClientConnection *focusedClient = focusedSurface ? focusedSurface->client() : nullptr;
0032 
0033     if (resource->version() >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
0034         send_repeat_info(resource->handle, keyRepeat.charactersPerSecond, keyRepeat.delay);
0035     }
0036     if (!keymap.isNull()) {
0037         sendKeymap(resource);
0038     }
0039 
0040     if (focusedClient && focusedClient->client() == resource->client()) {
0041         const QVector<quint32> keys = pressedKeys();
0042         const QByteArray keysData = QByteArray::fromRawData(reinterpret_cast<const char *>(keys.data()), sizeof(quint32) * keys.count());
0043         const quint32 serial = seat->display()->nextSerial();
0044 
0045         send_enter(resource->handle, serial, focusedSurface->resource(), keysData);
0046         send_modifiers(resource->handle, serial, modifiers.depressed, modifiers.latched, modifiers.locked, modifiers.group);
0047     }
0048 }
0049 
0050 QList<KeyboardInterfacePrivate::Resource *> KeyboardInterfacePrivate::keyboardsForClient(ClientConnection *client) const
0051 {
0052     return resourceMap().values(client->client());
0053 }
0054 
0055 void KeyboardInterfacePrivate::sendLeave(SurfaceInterface *surface, quint32 serial)
0056 {
0057     const QList<Resource *> keyboards = keyboardsForClient(surface->client());
0058     for (Resource *keyboardResource : keyboards) {
0059         send_leave(keyboardResource->handle, serial, surface->resource());
0060     }
0061 }
0062 
0063 void KeyboardInterfacePrivate::sendEnter(SurfaceInterface *surface, quint32 serial)
0064 {
0065     const auto states = pressedKeys();
0066     QByteArray data = QByteArray::fromRawData(reinterpret_cast<const char *>(states.constData()), sizeof(quint32) * states.size());
0067 
0068     const QList<Resource *> keyboards = keyboardsForClient(surface->client());
0069     for (Resource *keyboardResource : keyboards) {
0070         send_enter(keyboardResource->handle, serial, surface->resource(), data);
0071     }
0072 }
0073 
0074 void KeyboardInterfacePrivate::sendKeymap(Resource *resource)
0075 {
0076     // From version 7 on, keymaps must be mapped privately, so that
0077     // we can seal the fd and reuse it between clients.
0078     if (resource->version() >= 7 && sharedKeymapFile.effectiveFlags().testFlag(KWin::RamFile::Flag::SealWrite)) {
0079         send_keymap(resource->handle, keymap_format::keymap_format_xkb_v1, sharedKeymapFile.fd(), sharedKeymapFile.size());
0080         // otherwise give each client its own unsealed copy.
0081     } else {
0082         KWin::RamFile keymapFile("kwin-xkb-keymap", keymap.constData(), keymap.size() + 1); // Include QByteArray null-terminator.
0083         send_keymap(resource->handle, keymap_format::keymap_format_xkb_v1, keymapFile.fd(), keymapFile.size());
0084     }
0085 }
0086 
0087 void KeyboardInterface::setKeymap(const QByteArray &content)
0088 {
0089     if (content.isNull()) {
0090         return;
0091     }
0092 
0093     d->keymap = content;
0094     // +1 to include QByteArray null terminator.
0095     d->sharedKeymapFile = KWin::RamFile("kwin-xkb-keymap-shared", content.constData(), content.size() + 1, KWin::RamFile::Flag::SealWrite);
0096 
0097     const auto keyboardResources = d->resourceMap();
0098     for (KeyboardInterfacePrivate::Resource *resource : keyboardResources) {
0099         d->sendKeymap(resource);
0100     }
0101 }
0102 
0103 void KeyboardInterfacePrivate::sendModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group, quint32 serial)
0104 {
0105     const QList<Resource *> keyboards = keyboardsForClient(focusedSurface->client());
0106     for (Resource *keyboardResource : keyboards) {
0107         send_modifiers(keyboardResource->handle, serial, depressed, latched, locked, group);
0108     }
0109 }
0110 
0111 bool KeyboardInterfacePrivate::updateKey(quint32 key, KeyboardKeyState state)
0112 {
0113     auto it = states.find(key);
0114     if (it == states.end()) {
0115         states.insert(key, state);
0116         return true;
0117     }
0118     if (it.value() == state) {
0119         return false;
0120     }
0121     it.value() = state;
0122     return true;
0123 }
0124 
0125 KeyboardInterface::KeyboardInterface(SeatInterface *seat)
0126     : d(new KeyboardInterfacePrivate(seat))
0127 {
0128 }
0129 
0130 KeyboardInterface::~KeyboardInterface() = default;
0131 
0132 void KeyboardInterfacePrivate::sendModifiers()
0133 {
0134     sendModifiers(modifiers.depressed, modifiers.latched, modifiers.locked, modifiers.group, modifiers.serial);
0135 }
0136 
0137 void KeyboardInterface::setFocusedSurface(SurfaceInterface *surface, quint32 serial)
0138 {
0139     if (d->focusedSurface == surface) {
0140         return;
0141     }
0142 
0143     if (d->focusedSurface) {
0144         d->sendLeave(d->focusedSurface, serial);
0145         disconnect(d->destroyConnection);
0146     }
0147 
0148     d->focusedSurface = surface;
0149     if (!d->focusedSurface) {
0150         return;
0151     }
0152     d->destroyConnection = connect(d->focusedSurface, &SurfaceInterface::aboutToBeDestroyed, this, [this] {
0153         d->sendLeave(d->focusedSurface, d->seat->display()->nextSerial());
0154         d->focusedSurface = nullptr;
0155     });
0156 
0157     d->sendEnter(d->focusedSurface, serial);
0158     d->sendModifiers();
0159 }
0160 
0161 QVector<quint32> KeyboardInterfacePrivate::pressedKeys() const
0162 {
0163     QVector<quint32> keys;
0164     for (auto it = states.constBegin(); it != states.constEnd(); ++it) {
0165         if (it.value() == KeyboardKeyState::Pressed) {
0166             keys << it.key();
0167         }
0168     }
0169     return keys;
0170 }
0171 
0172 void KeyboardInterface::sendKey(quint32 key, KeyboardKeyState state, ClientConnection *client)
0173 {
0174     const QList<KeyboardInterfacePrivate::Resource *> keyboards = d->keyboardsForClient(client);
0175     const quint32 serial = d->seat->display()->nextSerial();
0176     for (KeyboardInterfacePrivate::Resource *keyboardResource : keyboards) {
0177         d->send_key(keyboardResource->handle, serial, d->seat->timestamp().count(), key, quint32(state));
0178     }
0179 }
0180 
0181 void KeyboardInterface::sendKey(quint32 key, KeyboardKeyState state)
0182 {
0183     if (!d->updateKey(key, state)) {
0184         return;
0185     }
0186 
0187     if (!d->focusedSurface) {
0188         return;
0189     }
0190 
0191     sendKey(key, state, d->focusedSurface->client());
0192 }
0193 
0194 void KeyboardInterface::sendModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group)
0195 {
0196     bool changed = false;
0197     if (d->modifiers.depressed != depressed) {
0198         d->modifiers.depressed = depressed;
0199         changed = true;
0200     }
0201     if (d->modifiers.latched != latched) {
0202         d->modifiers.latched = latched;
0203         changed = true;
0204     }
0205     if (d->modifiers.locked != locked) {
0206         d->modifiers.locked = locked;
0207         changed = true;
0208     }
0209     if (d->modifiers.group != group) {
0210         d->modifiers.group = group;
0211         changed = true;
0212     }
0213     if (!changed || !d->focusedSurface) {
0214         return;
0215     }
0216 
0217     d->modifiers.serial = d->seat->display()->nextSerial();
0218     d->sendModifiers(depressed, latched, locked, group, d->modifiers.serial);
0219 }
0220 
0221 void KeyboardInterface::setRepeatInfo(qint32 charactersPerSecond, qint32 delay)
0222 {
0223     d->keyRepeat.charactersPerSecond = std::max(charactersPerSecond, 0);
0224     d->keyRepeat.delay = std::max(delay, 0);
0225     const auto keyboards = d->resourceMap();
0226     for (KeyboardInterfacePrivate::Resource *keyboardResource : keyboards) {
0227         if (keyboardResource->version() >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
0228             d->send_repeat_info(keyboardResource->handle, d->keyRepeat.charactersPerSecond, d->keyRepeat.delay);
0229         }
0230     }
0231 }
0232 
0233 SurfaceInterface *KeyboardInterface::focusedSurface() const
0234 {
0235     return d->focusedSurface;
0236 }
0237 
0238 qint32 KeyboardInterface::keyRepeatDelay() const
0239 {
0240     return d->keyRepeat.delay;
0241 }
0242 
0243 qint32 KeyboardInterface::keyRepeatRate() const
0244 {
0245     return d->keyRepeat.charactersPerSecond;
0246 }
0247 
0248 }