1 | /* |
2 | SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL |
5 | */ |
6 | #include "pointer.h" |
7 | #include "surface.h" |
8 | #include "wayland_pointer_p.h" |
9 | // Qt |
10 | #include <QPointF> |
11 | #include <QPointer> |
12 | // wayland |
13 | #include <wayland-client-protocol.h> |
14 | |
15 | namespace KWayland |
16 | { |
17 | namespace Client |
18 | { |
19 | static Pointer::Axis wlAxisToPointerAxis(uint32_t axis) |
20 | { |
21 | switch (axis) { |
22 | case WL_POINTER_AXIS_VERTICAL_SCROLL: |
23 | return Pointer::Axis::Vertical; |
24 | case WL_POINTER_AXIS_HORIZONTAL_SCROLL: |
25 | return Pointer::Axis::Horizontal; |
26 | } |
27 | |
28 | Q_UNREACHABLE(); |
29 | } |
30 | |
31 | class Q_DECL_HIDDEN Pointer::Private |
32 | { |
33 | public: |
34 | Private(Pointer *q); |
35 | void setup(wl_pointer *p); |
36 | |
37 | WaylandPointer<wl_pointer, wl_pointer_release> pointer; |
38 | QPointer<Surface> enteredSurface; |
39 | quint32 enteredSerial = 0; |
40 | |
41 | private: |
42 | void enter(uint32_t serial, wl_surface *surface, const QPointF &relativeToSurface); |
43 | void leave(uint32_t serial); |
44 | static void enterCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy); |
45 | static void leaveCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface); |
46 | static void motionCallback(void *data, wl_pointer *pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy); |
47 | static void buttonCallback(void *data, wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state); |
48 | static void axisCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value); |
49 | static void frameCallback(void *data, wl_pointer *pointer); |
50 | static void axisSourceCallback(void *data, wl_pointer *pointer, uint32_t axis_source); |
51 | static void axisStopCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis); |
52 | static void axisDiscreteCallback(void *data, wl_pointer *pointer, uint32_t axis, int32_t discrete); |
53 | |
54 | Pointer *q; |
55 | static const wl_pointer_listener s_listener; |
56 | }; |
57 | |
58 | Pointer::Private::Private(Pointer *q) |
59 | : q(q) |
60 | { |
61 | } |
62 | |
63 | void Pointer::Private::setup(wl_pointer *p) |
64 | { |
65 | Q_ASSERT(p); |
66 | Q_ASSERT(!pointer); |
67 | pointer.setup(pointer: p); |
68 | wl_pointer_add_listener(wl_pointer: pointer, listener: &s_listener, data: this); |
69 | } |
70 | |
71 | const wl_pointer_listener Pointer::Private::s_listener = |
72 | {.enter: enterCallback, .leave: leaveCallback, .motion: motionCallback, .button: buttonCallback, .axis: axisCallback, .frame: frameCallback, .axis_source: axisSourceCallback, .axis_stop: axisStopCallback, .axis_discrete: axisDiscreteCallback}; |
73 | |
74 | Pointer::Pointer(QObject *parent) |
75 | : QObject(parent) |
76 | , d(new Private(this)) |
77 | { |
78 | } |
79 | |
80 | Pointer::~Pointer() |
81 | { |
82 | release(); |
83 | } |
84 | |
85 | void Pointer::release() |
86 | { |
87 | d->pointer.release(); |
88 | } |
89 | |
90 | void Pointer::destroy() |
91 | { |
92 | d->pointer.destroy(); |
93 | } |
94 | |
95 | void Pointer::setup(wl_pointer *pointer) |
96 | { |
97 | d->setup(pointer); |
98 | } |
99 | |
100 | void Pointer::Private::enterCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy) |
101 | { |
102 | auto p = reinterpret_cast<Pointer::Private *>(data); |
103 | Q_ASSERT(p->pointer == pointer); |
104 | p->enter(serial, surface, relativeToSurface: QPointF(wl_fixed_to_double(f: sx), wl_fixed_to_double(f: sy))); |
105 | } |
106 | |
107 | void Pointer::Private::enter(uint32_t serial, wl_surface *surface, const QPointF &relativeToSurface) |
108 | { |
109 | enteredSurface = QPointer<Surface>(Surface::get(native: surface)); |
110 | enteredSerial = serial; |
111 | Q_EMIT q->entered(serial, relativeToSurface); |
112 | } |
113 | |
114 | void Pointer::Private::leaveCallback(void *data, wl_pointer *pointer, uint32_t serial, wl_surface *surface) |
115 | { |
116 | auto p = reinterpret_cast<Pointer::Private *>(data); |
117 | Q_ASSERT(p->pointer == pointer); |
118 | Q_UNUSED(surface) |
119 | p->leave(serial); |
120 | } |
121 | |
122 | void Pointer::Private::leave(uint32_t serial) |
123 | { |
124 | enteredSurface.clear(); |
125 | Q_EMIT q->left(serial); |
126 | } |
127 | |
128 | void Pointer::Private::motionCallback(void *data, wl_pointer *pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy) |
129 | { |
130 | auto p = reinterpret_cast<Pointer::Private *>(data); |
131 | Q_ASSERT(p->pointer == pointer); |
132 | Q_EMIT p->q->motion(relativeToSurface: QPointF(wl_fixed_to_double(f: sx), wl_fixed_to_double(f: sy)), time); |
133 | } |
134 | |
135 | void Pointer::Private::buttonCallback(void *data, wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) |
136 | { |
137 | auto p = reinterpret_cast<Pointer::Private *>(data); |
138 | Q_ASSERT(p->pointer == pointer); |
139 | auto toState = [state] { |
140 | if (state == WL_POINTER_BUTTON_STATE_RELEASED) { |
141 | return ButtonState::Released; |
142 | } else { |
143 | return ButtonState::Pressed; |
144 | } |
145 | }; |
146 | Q_EMIT p->q->buttonStateChanged(serial, time, button, state: toState()); |
147 | } |
148 | |
149 | void Pointer::Private::axisCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value) |
150 | { |
151 | auto p = reinterpret_cast<Pointer::Private *>(data); |
152 | Q_ASSERT(p->pointer == pointer); |
153 | Q_EMIT p->q->axisChanged(time, axis: wlAxisToPointerAxis(axis), delta: wl_fixed_to_double(f: value)); |
154 | } |
155 | |
156 | void Pointer::Private::frameCallback(void *data, wl_pointer *pointer) |
157 | { |
158 | auto p = reinterpret_cast<Pointer::Private *>(data); |
159 | Q_ASSERT(p->pointer == pointer); |
160 | Q_EMIT p->q->frame(); |
161 | } |
162 | |
163 | void Pointer::Private::axisSourceCallback(void *data, wl_pointer *pointer, uint32_t axis_source) |
164 | { |
165 | auto p = reinterpret_cast<Pointer::Private *>(data); |
166 | Q_ASSERT(p->pointer == pointer); |
167 | AxisSource source; |
168 | switch (axis_source) { |
169 | case WL_POINTER_AXIS_SOURCE_WHEEL: |
170 | source = AxisSource::Wheel; |
171 | break; |
172 | case WL_POINTER_AXIS_SOURCE_FINGER: |
173 | source = AxisSource::Finger; |
174 | break; |
175 | case WL_POINTER_AXIS_SOURCE_CONTINUOUS: |
176 | source = AxisSource::Continuous; |
177 | break; |
178 | case WL_POINTER_AXIS_SOURCE_WHEEL_TILT: |
179 | source = AxisSource::WheelTilt; |
180 | break; |
181 | default: |
182 | Q_UNREACHABLE(); |
183 | break; |
184 | } |
185 | Q_EMIT p->q->axisSourceChanged(source); |
186 | } |
187 | |
188 | void Pointer::Private::axisStopCallback(void *data, wl_pointer *pointer, uint32_t time, uint32_t axis) |
189 | { |
190 | auto p = reinterpret_cast<Pointer::Private *>(data); |
191 | Q_ASSERT(p->pointer == pointer); |
192 | Q_EMIT p->q->axisStopped(time, axis: wlAxisToPointerAxis(axis)); |
193 | } |
194 | |
195 | void Pointer::Private::axisDiscreteCallback(void *data, wl_pointer *pointer, uint32_t axis, int32_t discrete) |
196 | { |
197 | auto p = reinterpret_cast<Pointer::Private *>(data); |
198 | Q_ASSERT(p->pointer == pointer); |
199 | Q_EMIT p->q->axisDiscreteChanged(axis: wlAxisToPointerAxis(axis), discreteDelta: discrete); |
200 | } |
201 | |
202 | void Pointer::setCursor(Surface *surface, const QPoint &hotspot) |
203 | { |
204 | Q_ASSERT(isValid()); |
205 | wl_surface *s = nullptr; |
206 | if (surface) { |
207 | s = *surface; |
208 | } |
209 | wl_pointer_set_cursor(wl_pointer: d->pointer, serial: d->enteredSerial, surface: s, hotspot_x: hotspot.x(), hotspot_y: hotspot.y()); |
210 | } |
211 | |
212 | void Pointer::hideCursor() |
213 | { |
214 | setCursor(surface: nullptr); |
215 | } |
216 | |
217 | Surface *Pointer::enteredSurface() |
218 | { |
219 | return d->enteredSurface.data(); |
220 | } |
221 | |
222 | Surface *Pointer::enteredSurface() const |
223 | { |
224 | return d->enteredSurface.data(); |
225 | } |
226 | |
227 | bool Pointer::isValid() const |
228 | { |
229 | return d->pointer.isValid(); |
230 | } |
231 | |
232 | Pointer::operator wl_pointer *() const |
233 | { |
234 | return d->pointer; |
235 | } |
236 | |
237 | Pointer::operator wl_pointer *() |
238 | { |
239 | return d->pointer; |
240 | } |
241 | |
242 | } |
243 | } |
244 | |
245 | #include "moc_pointer.cpp" |
246 | |