KWayland

touch.cpp
1 /*
2  SPDX-FileCopyrightText: 2015 Martin Gräßlin <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "touch.h"
7 #include "surface.h"
8 #include "wayland_pointer_p.h"
9 // Qt
10 #include <QPointF>
11 #include <QPointer>
12 #include <QVector>
13 // wayland
14 #include <wayland-client-protocol.h>
15 
16 namespace KWayland
17 {
18 namespace Client
19 {
20 class Q_DECL_HIDDEN Touch::Private
21 {
22 public:
23  Private(Touch *q);
24  void setup(wl_touch *t);
25  WaylandPointer<wl_touch, wl_touch_release> touch;
26  bool active = false;
27  QVector<TouchPoint *> sequence;
28  TouchPoint *getActivePoint(qint32 id) const;
29 
30 private:
31  static void downCallback(void *data, wl_touch *touch, uint32_t serial, uint32_t time, wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y);
32  static void upCallback(void *data, wl_touch *touch, uint32_t serial, uint32_t time, int32_t id);
33  static void motionCallback(void *data, wl_touch *touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y);
34  static void frameCallback(void *data, wl_touch *touch);
35  static void cancelCallback(void *data, wl_touch *touch);
36  void down(quint32 serial, quint32 time, qint32 id, const QPointF &position, const QPointer<Surface> &surface);
37  void up(quint32 serial, quint32 time, qint32 id);
38  void motion(quint32 time, qint32 id, const QPointF &position);
39 
40  Touch *q;
41  static const wl_touch_listener s_listener;
42 };
43 
44 class TouchPoint::Private
45 {
46 public:
47  qint32 id = 0;
48  quint32 downSerial = 0;
49  quint32 upSerial = 0;
53  bool down = true;
54 };
55 
56 TouchPoint::TouchPoint()
57  : d(new Private)
58 {
59 }
60 
61 TouchPoint::~TouchPoint() = default;
62 
63 QPointF TouchPoint::position() const
64 {
65  if (d->positions.isEmpty()) {
66  return QPointF();
67  }
68  return d->positions.last();
69 }
70 
71 QVector<QPointF> TouchPoint::positions() const
72 {
73  return d->positions;
74 }
75 
76 quint32 TouchPoint::downSerial() const
77 {
78  return d->downSerial;
79 }
80 
81 quint32 TouchPoint::upSerial() const
82 {
83  return d->upSerial;
84 }
85 
86 QPointer<Surface> TouchPoint::surface() const
87 {
88  return d->surface;
89 }
90 
91 quint32 TouchPoint::time() const
92 {
93  if (d->timestamps.isEmpty()) {
94  return 0;
95  }
96  return d->timestamps.last();
97 }
98 
99 QVector<quint32> TouchPoint::timestamps() const
100 {
101  return d->timestamps;
102 }
103 
104 bool TouchPoint::isDown() const
105 {
106  return d->down;
107 }
108 
109 qint32 TouchPoint::id() const
110 {
111  return d->id;
112 }
113 
114 Touch::Private::Private(Touch *q)
115  : q(q)
116 {
117 }
118 
119 void Touch::Private::setup(wl_touch *t)
120 {
121  Q_ASSERT(t);
122  Q_ASSERT(!touch);
123  touch.setup(t);
124  wl_touch_add_listener(touch, &s_listener, this);
125 }
126 
127 const wl_touch_listener Touch::Private::s_listener = {downCallback, upCallback, motionCallback, frameCallback, cancelCallback};
128 
129 void Touch::Private::downCallback(void *data, wl_touch *touch, uint32_t serial, uint32_t time, wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y)
130 {
131  auto t = reinterpret_cast<Touch::Private *>(data);
132  Q_ASSERT(t->touch == touch);
133  t->down(serial, time, id, QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y)), QPointer<Surface>(Surface::get(surface)));
134 }
135 
136 void Touch::Private::down(quint32 serial, quint32 time, qint32 id, const QPointF &position, const QPointer<Surface> &surface)
137 {
138  TouchPoint *p = new TouchPoint;
139  p->d->downSerial = serial;
140  p->d->surface = surface;
141  p->d->id = id;
142  p->d->positions << position;
143  p->d->timestamps << time;
144  if (active) {
145  sequence << p;
146  Q_EMIT q->pointAdded(p);
147  } else {
148  qDeleteAll(sequence);
149  sequence.clear();
150  sequence << p;
151  active = true;
152  Q_EMIT q->sequenceStarted(p);
153  }
154 }
155 
156 TouchPoint *Touch::Private::getActivePoint(qint32 id) const
157 {
158  auto it = std::find_if(sequence.constBegin(), sequence.constEnd(), [id](TouchPoint *p) {
159  return p->id() == id && p->isDown();
160  });
161  if (it == sequence.constEnd()) {
162  return nullptr;
163  }
164  return *it;
165 }
166 
167 void Touch::Private::upCallback(void *data, wl_touch *touch, uint32_t serial, uint32_t time, int32_t id)
168 {
169  auto t = reinterpret_cast<Touch::Private *>(data);
170  Q_ASSERT(t->touch == touch);
171  t->up(serial, time, id);
172 }
173 
174 void Touch::Private::up(quint32 serial, quint32 time, qint32 id)
175 {
176  TouchPoint *p = getActivePoint(id);
177  if (!p) {
178  return;
179  }
180  p->d->timestamps << time;
181  p->d->upSerial = serial;
182  p->d->down = false;
183  Q_EMIT q->pointRemoved(p);
184  // check whether the sequence ended
185  for (auto it = sequence.constBegin(); it != sequence.constEnd(); ++it) {
186  if ((*it)->isDown()) {
187  return;
188  }
189  }
190  // no touch point is down
191  active = false;
192  Q_EMIT q->sequenceEnded();
193 }
194 
195 void Touch::Private::motionCallback(void *data, wl_touch *touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
196 {
197  auto t = reinterpret_cast<Touch::Private *>(data);
198  Q_ASSERT(t->touch == touch);
199  t->motion(time, id, QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y)));
200 }
201 
202 void Touch::Private::motion(quint32 time, qint32 id, const QPointF &position)
203 {
204  TouchPoint *p = getActivePoint(id);
205  if (!p) {
206  return;
207  }
208  p->d->positions << position;
209  p->d->timestamps << time;
210  Q_EMIT q->pointMoved(p);
211 }
212 
213 void Touch::Private::frameCallback(void *data, wl_touch *touch)
214 {
215  auto t = reinterpret_cast<Touch::Private *>(data);
216  Q_ASSERT(t->touch == touch);
217  Q_EMIT t->q->frameEnded();
218 }
219 
220 void Touch::Private::cancelCallback(void *data, wl_touch *touch)
221 {
222  auto t = reinterpret_cast<Touch::Private *>(data);
223  Q_ASSERT(t->touch == touch);
224  t->active = false;
225  Q_EMIT t->q->sequenceCanceled();
226 }
227 
228 Touch::Touch(QObject *parent)
229  : QObject(parent)
230  , d(new Private(this))
231 {
232 }
233 
234 Touch::~Touch()
235 {
236  release();
237 }
238 
240 {
241  d->touch.destroy();
242 }
243 
245 {
246  d->touch.release();
247 }
248 
249 void Touch::setup(wl_touch *touch)
250 {
251  d->setup(touch);
252 }
253 
254 bool Touch::isValid() const
255 {
256  return d->touch.isValid();
257 }
258 
259 Touch::operator wl_touch *() const
260 {
261  return d->touch;
262 }
263 
264 Touch::operator wl_touch *()
265 {
266  return d->touch;
267 }
268 
270 {
271  return d->sequence;
272 }
273 
274 }
275 }
QVector< quint32 > timestamps() const
All timestamps, references the positions.
Definition: touch.cpp:99
static Surface * get(wl_surface *native)
Definition: surface.cpp:212
void setup(wl_touch *touch)
Setup this Touch to manage the touch.
Definition: touch.cpp:249
bool isValid() const
Definition: touch.cpp:254
quint32 upSerial() const
The serial when the up event happened.
Definition: touch.cpp:81
QPointer< Surface > surface() const
The Surface this TouchPoint happened on.
Definition: touch.cpp:86
QVector< QPointF > positions() const
All positions this TouchPoint had, updated with each move.
Definition: touch.cpp:71
quint32 downSerial() const
The serial when the down event happened.
Definition: touch.cpp:76
void destroy()
Destroys the data held by this Touch.
Definition: touch.cpp:239
void release()
Releases the wl_touch interface.
Definition: touch.cpp:244
QVector< TouchPoint * > sequence() const
The TouchPoints of the latest touch event sequence.
Definition: touch.cpp:269
const QList< QKeySequence > & up()
Wrapper for the wl_touch interface.
Definition: touch.h:87
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Jan 30 2023 03:56:25 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.