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 
21 class Q_DECL_HIDDEN Touch::Private
22 {
23 public:
24  Private(Touch *q);
25  void setup(wl_touch *t);
26  WaylandPointer<wl_touch, wl_touch_release> touch;
27  bool active = false;
28  QVector<TouchPoint*> sequence;
29  TouchPoint *getActivePoint(qint32 id) const;
30 
31 private:
32  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);
33  static void upCallback(void *data, wl_touch *touch, uint32_t serial, uint32_t time, int32_t id);
34  static void motionCallback(void *data, wl_touch *touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y);
35  static void frameCallback(void *data, wl_touch *touch);
36  static void cancelCallback(void *data, wl_touch *touch);
37  void down(quint32 serial, quint32 time, qint32 id, const QPointF &position, const QPointer<Surface> &surface);
38  void up(quint32 serial, quint32 time, qint32 id);
39  void motion(quint32 time, qint32 id, const QPointF &position);
40 
41  Touch *q;
42  static const wl_touch_listener s_listener;
43 };
44 
45 class TouchPoint::Private
46 {
47 public:
48  qint32 id = 0;
49  quint32 downSerial = 0;
50  quint32 upSerial = 0;
51  QPointer<Surface> surface;
52  QVector<QPointF> positions;
53  QVector<quint32> timestamps;
54  bool down = true;
55 };
56 
57 TouchPoint::TouchPoint()
58  : d(new Private)
59 {
60 }
61 
62 TouchPoint::~TouchPoint() = default;
63 
64 QPointF TouchPoint::position() const
65 {
66  if (d->positions.isEmpty()) {
67  return QPointF();
68  }
69  return d->positions.last();
70 }
71 
72 QVector< QPointF > TouchPoint::positions() const
73 {
74  return d->positions;
75 }
76 
77 quint32 TouchPoint::downSerial() const
78 {
79  return d->downSerial;
80 }
81 
82 quint32 TouchPoint::upSerial() const
83 {
84  return d->upSerial;
85 }
86 
87 QPointer< Surface > TouchPoint::surface() const
88 {
89  return d->surface;
90 }
91 
92 quint32 TouchPoint::time() const
93 {
94  if (d->timestamps.isEmpty()) {
95  return 0;
96  }
97  return d->timestamps.last();
98 }
99 
100 QVector< quint32 > TouchPoint::timestamps() const
101 {
102  return d->timestamps;
103 }
104 
105 bool TouchPoint::isDown() const
106 {
107  return d->down;
108 }
109 
110 qint32 TouchPoint::id() const
111 {
112  return d->id;
113 }
114 
115 Touch::Private::Private(Touch *q)
116  : q(q)
117 {
118 }
119 
120 void Touch::Private::setup(wl_touch *t)
121 {
122  Q_ASSERT(t);
123  Q_ASSERT(!touch);
124  touch.setup(t);
125  wl_touch_add_listener(touch, &s_listener, this);
126 }
127 
128 const wl_touch_listener Touch::Private::s_listener = {
129  downCallback,
130  upCallback,
131  motionCallback,
132  frameCallback,
133  cancelCallback
134 };
135 
136 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)
137 {
138  auto t = reinterpret_cast<Touch::Private*>(data);
139  Q_ASSERT(t->touch == touch);
140  t->down(serial, time, id, QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y)), QPointer<Surface>(Surface::get(surface)));
141 }
142 
143 void Touch::Private::down(quint32 serial, quint32 time, qint32 id, const QPointF &position, const QPointer< Surface> &surface)
144 {
145  TouchPoint *p = new TouchPoint;
146  p->d->downSerial = serial;
147  p->d->surface = surface;
148  p->d->id = id;
149  p->d->positions << position;
150  p->d->timestamps << time;
151  if (active) {
152  sequence << p;
153  emit q->pointAdded(p);
154  } else {
155  qDeleteAll(sequence);
156  sequence.clear();
157  sequence << p;
158  active = true;
159  emit q->sequenceStarted(p);
160  }
161 }
162 
163 TouchPoint *Touch::Private::getActivePoint(qint32 id) const
164 {
165  auto it = std::find_if(sequence.constBegin(), sequence.constEnd(),
166  [id] (TouchPoint *p) {
167  return p->id() == id && p->isDown();
168  }
169  );
170  if (it == sequence.constEnd()) {
171  return nullptr;
172  }
173  return *it;
174 }
175 
176 void Touch::Private::upCallback(void *data, wl_touch *touch, uint32_t serial, uint32_t time, int32_t id)
177 {
178  auto t = reinterpret_cast<Touch::Private*>(data);
179  Q_ASSERT(t->touch == touch);
180  t->up(serial, time, id);
181 }
182 
183 void Touch::Private::up(quint32 serial, quint32 time, qint32 id)
184 {
185  TouchPoint *p = getActivePoint(id);
186  if (!p) {
187  return;
188  }
189  p->d->timestamps << time;
190  p->d->upSerial = serial;
191  p->d->down = false;
192  emit q->pointRemoved(p);
193  // check whether the sequence ended
194  for (auto it = sequence.constBegin(); it != sequence.constEnd(); ++it) {
195  if ((*it)->isDown()) {
196  return;
197  }
198  }
199  // no touch point is down
200  active = false;
201  emit q->sequenceEnded();
202 }
203 
204 void Touch::Private::motionCallback(void *data, wl_touch *touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
205 {
206  auto t = reinterpret_cast<Touch::Private*>(data);
207  Q_ASSERT(t->touch == touch);
208  t->motion(time, id, QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y)));
209 }
210 
211 void Touch::Private::motion(quint32 time, qint32 id, const QPointF &position)
212 {
213  TouchPoint *p = getActivePoint(id);
214  if (!p) {
215  return;
216  }
217  p->d->positions << position;
218  p->d->timestamps << time;
219  emit q->pointMoved(p);
220 }
221 
222 void Touch::Private::frameCallback(void *data, wl_touch *touch)
223 {
224  auto t = reinterpret_cast<Touch::Private*>(data);
225  Q_ASSERT(t->touch == touch);
226  emit t->q->frameEnded();
227 }
228 
229 void Touch::Private::cancelCallback(void *data, wl_touch *touch)
230 {
231  auto t = reinterpret_cast<Touch::Private*>(data);
232  Q_ASSERT(t->touch == touch);
233  t->active = false;
234  emit t->q->sequenceCanceled();
235 }
236 
237 Touch::Touch(QObject *parent)
238  : QObject(parent)
239  , d(new Private(this))
240 {
241 }
242 
243 Touch::~Touch()
244 {
245  release();
246 }
247 
248 void Touch::destroy()
249 {
250  d->touch.destroy();
251 }
252 
253 void Touch::release()
254 {
255  d->touch.release();
256 }
257 
258 void Touch::setup(wl_touch *touch)
259 {
260  d->setup(touch);
261 }
262 
263 bool Touch::isValid() const
264 {
265  return d->touch.isValid();
266 }
267 
268 Touch::operator wl_touch *() const
269 {
270  return d->touch;
271 }
272 
273 Touch::operator wl_touch *()
274 {
275  return d->touch;
276 }
277 
278 QVector< TouchPoint* > Touch::sequence() const
279 {
280  return d->sequence;
281 }
282 
283 }
284 }
quint32 id() const
Definition: resource.cpp:98
void sequenceStarted(KWayland::Client::TouchPoint *startPoint)
A new touch sequence is started.
QPointer< SurfaceInterface > surface() const
void sequenceEnded()
Emitted once all touch points are no longer down.
Wrapper for the wl_touch interface.
Definition: touch.h:88
void pointAdded(KWayland::Client::TouchPoint *point)
TouchPoint point got added to the sequence.
void pointMoved(KWayland::Client::TouchPoint *point)
TouchPoint point moved.
const QList< QKeySequence > & up()
QObject(QObject *parent)
QObject * parent() const const
void pointRemoved(KWayland::Client::TouchPoint *point)
TouchPoint point is no longer down.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Aug 7 2020 22:48:20 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.