keyboard_interface.cpp 5.71 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/********************************************************************
Copyright 2014  Martin Gräßlin <mgraesslin@kde.org>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) version 3, or any
later version accepted by the membership of KDE e.V. (or its
successor approved by the membership of KDE e.V.), which shall
act as a proxy defined in Section 6 of version 3 of the license.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library.  If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "keyboard_interface.h"
21
#include "keyboard_interface_p.h"
22 23 24 25
#include "display.h"
#include "seat_interface.h"
#include "surface_interface.h"
// Qt
Martin Flöser's avatar
Martin Flöser committed
26
#include <QVector>
27 28 29 30 31 32 33 34 35
// Wayland
#include <wayland-server.h>

namespace KWayland
{

namespace Server
{

36 37 38
KeyboardInterface::Private::Private(SeatInterface *s, wl_resource *parentResource, KeyboardInterface *q)
    : Resource::Private(q, s, parentResource, &wl_keyboard_interface, &s_interface)
    , seat(s)
39 40 41
{
}

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
void KeyboardInterface::Private::focusChildSurface(const QPointer<SurfaceInterface> &childSurface, quint32 serial)
{
    if (focusedChildSurface == childSurface) {
        return;
    }
    sendLeave(focusedChildSurface.data(), serial);
    focusedChildSurface = childSurface;
    sendEnter(focusedChildSurface.data(), serial);
}

void KeyboardInterface::Private::sendLeave(SurfaceInterface *surface, quint32 serial)
{
    if (surface && resource && surface->resource()) {
        wl_keyboard_send_leave(resource, serial, surface->resource());
    }
}

void KeyboardInterface::Private::sendEnter(SurfaceInterface *surface, quint32 serial)
{
    wl_array keys;
    wl_array_init(&keys);
    const auto states = seat->pressedKeys();
Frederik Gladhorn's avatar
Frederik Gladhorn committed
64
    for (auto it = states.constBegin(); it != states.constEnd(); ++it) {
65 66 67 68 69 70 71 72 73
        uint32_t *k = reinterpret_cast<uint32_t*>(wl_array_add(&keys, sizeof(uint32_t)));
        *k = *it;
    }
    wl_keyboard_send_enter(resource, serial, surface->resource(), &keys);
    wl_array_release(&keys);

    sendModifiers();
}

Martin Flöser's avatar
Martin Flöser committed
74
#ifndef DOXYGEN_SHOULD_SKIP_THIS
75
const struct wl_keyboard_interface KeyboardInterface::Private::s_interface {
76
    resourceDestroyedCallback
77
};
Martin Flöser's avatar
Martin Flöser committed
78
#endif
79

80
KeyboardInterface::KeyboardInterface(SeatInterface *parent, wl_resource *parentResource)
81
    : Resource(new Private(parent, parentResource, this))
82 83 84
{
}

85
KeyboardInterface::~KeyboardInterface() = default;
86 87 88

void KeyboardInterface::setKeymap(int fd, quint32 size)
{
89
    Q_D();
Martin Flöser's avatar
Martin Flöser committed
90
    d->sendKeymap(fd, size);
91 92
}

Martin Flöser's avatar
Martin Flöser committed
93
void KeyboardInterface::Private::sendKeymap(int fd, quint32 size)
94
{
95 96 97
    if (!resource) {
        return;
    }
Martin Flöser's avatar
Martin Flöser committed
98
    wl_keyboard_send_keymap(resource, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, size);
99 100
}

Martin Flöser's avatar
Martin Flöser committed
101
void KeyboardInterface::Private::sendModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group, quint32 serial)
102
{
103 104 105
    if (!resource) {
        return;
    }
Martin Flöser's avatar
Martin Flöser committed
106
    wl_keyboard_send_modifiers(resource, serial, depressed, latched, locked, group);
107 108
}

Martin Flöser's avatar
Martin Flöser committed
109
void KeyboardInterface::Private::sendModifiers()
110
{
Martin Flöser's avatar
Martin Flöser committed
111 112 113 114 115
    sendModifiers(seat->depressedModifiers(), seat->latchedModifiers(), seat->lockedModifiers(), seat->groupModifiers(), seat->lastModifiersSerial());
}

void KeyboardInterface::setFocusedSurface(SurfaceInterface *surface, quint32 serial)
{
116
    Q_D();
117 118 119
    d->sendLeave(d->focusedChildSurface, serial);
    disconnect(d->destroyConnection);
    d->focusedChildSurface.clear();
Martin Flöser's avatar
Martin Flöser committed
120 121
    d->focusedSurface = surface;
    if (!d->focusedSurface) {
122 123
        return;
    }
124
    d->destroyConnection = connect(d->focusedSurface, &Resource::aboutToBeUnbound, this,
Martin Flöser's avatar
Martin Flöser committed
125
        [this] {
126
            Q_D();
127 128 129
            if (d->resource) {
                wl_keyboard_send_leave(d->resource, d->global->display()->nextSerial(), d->focusedSurface->resource());
            }
Martin Flöser's avatar
Martin Flöser committed
130
            d->focusedSurface = nullptr;
131
            d->focusedChildSurface.clear();
Martin Flöser's avatar
Martin Flöser committed
132 133
        }
    );
134
    d->focusedChildSurface = QPointer<SurfaceInterface>(surface);
135

136
    d->sendEnter(d->focusedSurface, serial);
137
    d->client->flush();
138 139
}

Martin Flöser's avatar
Martin Flöser committed
140
void KeyboardInterface::keyPressed(quint32 key, quint32 serial)
141
{
142
    Q_D();
143 144 145
    if (!d->resource) {
        return;
    }
Martin Flöser's avatar
Martin Flöser committed
146 147
    Q_ASSERT(d->focusedSurface);
    wl_keyboard_send_key(d->resource, serial, d->seat->timestamp(), key, WL_KEYBOARD_KEY_STATE_PRESSED);
148 149
}

Martin Flöser's avatar
Martin Flöser committed
150
void KeyboardInterface::keyReleased(quint32 key, quint32 serial)
151
{
152
    Q_D();
153 154 155
    if (!d->resource) {
        return;
    }
Martin Flöser's avatar
Martin Flöser committed
156 157
    Q_ASSERT(d->focusedSurface);
    wl_keyboard_send_key(d->resource, serial, d->seat->timestamp(), key, WL_KEYBOARD_KEY_STATE_RELEASED);
158 159
}

Martin Flöser's avatar
Martin Flöser committed
160
void KeyboardInterface::updateModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group, quint32 serial)
161
{
162
    Q_D();
Martin Flöser's avatar
Martin Flöser committed
163 164
    Q_ASSERT(d->focusedSurface);
    d->sendModifiers(depressed, latched, locked, group, serial);
165 166
}

167 168 169
void KeyboardInterface::repeatInfo(qint32 charactersPerSecond, qint32 delay)
{
    Q_D();
170 171 172
    if (!d->resource) {
        return;
    }
173
    if (wl_resource_get_version(d->resource) < WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
174 175 176 177 178 179
        // only supported since version 4
        return;
    }
    wl_keyboard_send_repeat_info(d->resource, charactersPerSecond, delay);
}

Martin Flöser's avatar
Martin Flöser committed
180
SurfaceInterface *KeyboardInterface::focusedSurface() const
181
{
182
    Q_D();
Martin Flöser's avatar
Martin Flöser committed
183
    return d->focusedSurface;
184 185
}

186
KeyboardInterface::Private *KeyboardInterface::d_func() const
187
{
188
    return reinterpret_cast<Private*>(d.data());
189 190 191 192
}

}
}