keyboard_interface.cpp 5.92 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
36
37
38
// System
#include <fcntl.h>
#include <unistd.h>
// Wayland
#include <wayland-server.h>

namespace KWayland
{

namespace Server
{

39
40
41
KeyboardInterface::Private::Private(SeatInterface *s, wl_resource *parentResource, KeyboardInterface *q)
    : Resource::Private(q, s, parentResource, &wl_keyboard_interface, &s_interface)
    , seat(s)
42
43
44
{
}

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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();
    for (auto it = states.begin(); it != states.end(); ++it) {
        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
77
#ifndef DOXYGEN_SHOULD_SKIP_THIS
78
79
80
const struct wl_keyboard_interface KeyboardInterface::Private::s_interface {
    releaseCallback
};
Martin Flöser's avatar
Martin Flöser committed
81
#endif
82

83
84
KeyboardInterface::KeyboardInterface(SeatInterface *parent, wl_resource *parentResource)
    : Resource(new Private(parent, parentResource, this), parent)
85
86
87
{
}

88
KeyboardInterface::~KeyboardInterface() = default;
89
90
91
92
93
94
95
96
97

void KeyboardInterface::Private::releaseCallback(wl_client *client, wl_resource *resource)
{
    Q_UNUSED(client)
    unbind(resource);
}

void KeyboardInterface::setKeymap(int fd, quint32 size)
{
98
    Q_D();
Martin Flöser's avatar
Martin Flöser committed
99
    d->sendKeymap(fd, size);
100
101
}

Martin Flöser's avatar
Martin Flöser committed
102
void KeyboardInterface::Private::sendKeymap()
103
{
Martin Flöser's avatar
Martin Flöser committed
104
105
106
    Q_ASSERT(resource);
    if (seat->isKeymapXkbCompatible()) {
        sendKeymap(seat->keymapFileDescriptor(), seat->keymapSize());
107
    } else {
108
        int nullFd = open("/dev/null", O_RDONLY); // krazy:exclude=syscalls
Martin Flöser's avatar
Martin Flöser committed
109
        wl_keyboard_send_keymap(resource, WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP, nullFd, 0);
110
111
112
113
        close(nullFd);
    }
}

Martin Flöser's avatar
Martin Flöser committed
114
void KeyboardInterface::Private::sendKeymap(int fd, quint32 size)
115
{
Martin Flöser's avatar
Martin Flöser committed
116
117
    Q_ASSERT(resource);
    wl_keyboard_send_keymap(resource, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, size);
118
119
}

Martin Flöser's avatar
Martin Flöser committed
120
void KeyboardInterface::Private::sendModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group, quint32 serial)
121
{
Martin Flöser's avatar
Martin Flöser committed
122
123
    Q_ASSERT(resource);
    wl_keyboard_send_modifiers(resource, serial, depressed, latched, locked, group);
124
125
}

Martin Flöser's avatar
Martin Flöser committed
126
void KeyboardInterface::Private::sendModifiers()
127
{
Martin Flöser's avatar
Martin Flöser committed
128
129
130
131
132
    sendModifiers(seat->depressedModifiers(), seat->latchedModifiers(), seat->lockedModifiers(), seat->groupModifiers(), seat->lastModifiersSerial());
}

void KeyboardInterface::setFocusedSurface(SurfaceInterface *surface, quint32 serial)
{
133
    Q_D();
134
135
136
    d->sendLeave(d->focusedChildSurface, serial);
    disconnect(d->destroyConnection);
    d->focusedChildSurface.clear();
Martin Flöser's avatar
Martin Flöser committed
137
138
    d->focusedSurface = surface;
    if (!d->focusedSurface) {
139
140
        return;
    }
Martin Flöser's avatar
Martin Flöser committed
141
142
    d->destroyConnection = connect(d->focusedSurface, &QObject::destroyed, this,
        [this] {
143
            Q_D();
Martin Flöser's avatar
Martin Flöser committed
144
            d->focusedSurface = nullptr;
145
            d->focusedChildSurface.clear();
Martin Flöser's avatar
Martin Flöser committed
146
147
        }
    );
148
    d->focusedChildSurface = QPointer<SurfaceInterface>(surface);
149

150
    d->sendEnter(d->focusedSurface, serial);
151
    d->client->flush();
152
153
}

Martin Flöser's avatar
Martin Flöser committed
154
void KeyboardInterface::keyPressed(quint32 key, quint32 serial)
155
{
156
    Q_D();
Martin Flöser's avatar
Martin Flöser committed
157
158
    Q_ASSERT(d->focusedSurface);
    wl_keyboard_send_key(d->resource, serial, d->seat->timestamp(), key, WL_KEYBOARD_KEY_STATE_PRESSED);
159
160
}

Martin Flöser's avatar
Martin Flöser committed
161
void KeyboardInterface::keyReleased(quint32 key, quint32 serial)
162
{
163
    Q_D();
Martin Flöser's avatar
Martin Flöser committed
164
165
    Q_ASSERT(d->focusedSurface);
    wl_keyboard_send_key(d->resource, serial, d->seat->timestamp(), key, WL_KEYBOARD_KEY_STATE_RELEASED);
166
167
}

Martin Flöser's avatar
Martin Flöser committed
168
void KeyboardInterface::updateModifiers(quint32 depressed, quint32 latched, quint32 locked, quint32 group, quint32 serial)
169
{
170
    Q_D();
Martin Flöser's avatar
Martin Flöser committed
171
172
    Q_ASSERT(d->focusedSurface);
    d->sendModifiers(depressed, latched, locked, group, serial);
173
174
}

175
176
177
void KeyboardInterface::repeatInfo(qint32 charactersPerSecond, qint32 delay)
{
    Q_D();
178
    if (wl_resource_get_version(d->resource) < WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) {
179
180
181
182
183
184
        // only supported since version 4
        return;
    }
    wl_keyboard_send_repeat_info(d->resource, charactersPerSecond, delay);
}

Martin Flöser's avatar
Martin Flöser committed
185
SurfaceInterface *KeyboardInterface::focusedSurface() const
186
{
187
    Q_D();
Martin Flöser's avatar
Martin Flöser committed
188
    return d->focusedSurface;
189
190
}

191
KeyboardInterface::Private *KeyboardInterface::d_func() const
192
{
193
    return reinterpret_cast<Private*>(d.data());
194
195
196
197
}

}
}