File indexing completed on 2024-12-22 05:09:25
0001 /* 0002 SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 #include "touch.h" 0007 #include "surface.h" 0008 #include "wayland_pointer_p.h" 0009 // Qt 0010 #include <QList> 0011 #include <QPointF> 0012 #include <QPointer> 0013 // wayland 0014 #include <wayland-client-protocol.h> 0015 0016 namespace KWayland 0017 { 0018 namespace Client 0019 { 0020 class Q_DECL_HIDDEN Touch::Private 0021 { 0022 public: 0023 Private(Touch *q); 0024 void setup(wl_touch *t); 0025 WaylandPointer<wl_touch, wl_touch_release> touch; 0026 bool active = false; 0027 QList<TouchPoint *> sequence; 0028 TouchPoint *getActivePoint(qint32 id) const; 0029 0030 private: 0031 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); 0032 static void upCallback(void *data, wl_touch *touch, uint32_t serial, uint32_t time, int32_t id); 0033 static void motionCallback(void *data, wl_touch *touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y); 0034 static void frameCallback(void *data, wl_touch *touch); 0035 static void cancelCallback(void *data, wl_touch *touch); 0036 void down(quint32 serial, quint32 time, qint32 id, const QPointF &position, const QPointer<Surface> &surface); 0037 void up(quint32 serial, quint32 time, qint32 id); 0038 void motion(quint32 time, qint32 id, const QPointF &position); 0039 0040 Touch *q; 0041 static const wl_touch_listener s_listener; 0042 }; 0043 0044 class TouchPoint::Private 0045 { 0046 public: 0047 qint32 id = 0; 0048 quint32 downSerial = 0; 0049 quint32 upSerial = 0; 0050 QPointer<Surface> surface; 0051 QList<QPointF> positions; 0052 QList<quint32> timestamps; 0053 bool down = true; 0054 }; 0055 0056 TouchPoint::TouchPoint() 0057 : d(new Private) 0058 { 0059 } 0060 0061 TouchPoint::~TouchPoint() = default; 0062 0063 QPointF TouchPoint::position() const 0064 { 0065 if (d->positions.isEmpty()) { 0066 return QPointF(); 0067 } 0068 return d->positions.last(); 0069 } 0070 0071 QList<QPointF> TouchPoint::positions() const 0072 { 0073 return d->positions; 0074 } 0075 0076 quint32 TouchPoint::downSerial() const 0077 { 0078 return d->downSerial; 0079 } 0080 0081 quint32 TouchPoint::upSerial() const 0082 { 0083 return d->upSerial; 0084 } 0085 0086 QPointer<Surface> TouchPoint::surface() const 0087 { 0088 return d->surface; 0089 } 0090 0091 quint32 TouchPoint::time() const 0092 { 0093 if (d->timestamps.isEmpty()) { 0094 return 0; 0095 } 0096 return d->timestamps.last(); 0097 } 0098 0099 QList<quint32> TouchPoint::timestamps() const 0100 { 0101 return d->timestamps; 0102 } 0103 0104 bool TouchPoint::isDown() const 0105 { 0106 return d->down; 0107 } 0108 0109 qint32 TouchPoint::id() const 0110 { 0111 return d->id; 0112 } 0113 0114 Touch::Private::Private(Touch *q) 0115 : q(q) 0116 { 0117 } 0118 0119 void Touch::Private::setup(wl_touch *t) 0120 { 0121 Q_ASSERT(t); 0122 Q_ASSERT(!touch); 0123 touch.setup(t); 0124 wl_touch_add_listener(touch, &s_listener, this); 0125 } 0126 0127 const wl_touch_listener Touch::Private::s_listener = {downCallback, upCallback, motionCallback, frameCallback, cancelCallback}; 0128 0129 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) 0130 { 0131 auto t = reinterpret_cast<Touch::Private *>(data); 0132 Q_ASSERT(t->touch == touch); 0133 t->down(serial, time, id, QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y)), QPointer<Surface>(Surface::get(surface))); 0134 } 0135 0136 void Touch::Private::down(quint32 serial, quint32 time, qint32 id, const QPointF &position, const QPointer<Surface> &surface) 0137 { 0138 TouchPoint *p = new TouchPoint; 0139 p->d->downSerial = serial; 0140 p->d->surface = surface; 0141 p->d->id = id; 0142 p->d->positions << position; 0143 p->d->timestamps << time; 0144 if (active) { 0145 sequence << p; 0146 Q_EMIT q->pointAdded(p); 0147 } else { 0148 qDeleteAll(sequence); 0149 sequence.clear(); 0150 sequence << p; 0151 active = true; 0152 Q_EMIT q->sequenceStarted(p); 0153 } 0154 } 0155 0156 TouchPoint *Touch::Private::getActivePoint(qint32 id) const 0157 { 0158 auto it = std::find_if(sequence.constBegin(), sequence.constEnd(), [id](TouchPoint *p) { 0159 return p->id() == id && p->isDown(); 0160 }); 0161 if (it == sequence.constEnd()) { 0162 return nullptr; 0163 } 0164 return *it; 0165 } 0166 0167 void Touch::Private::upCallback(void *data, wl_touch *touch, uint32_t serial, uint32_t time, int32_t id) 0168 { 0169 auto t = reinterpret_cast<Touch::Private *>(data); 0170 Q_ASSERT(t->touch == touch); 0171 t->up(serial, time, id); 0172 } 0173 0174 void Touch::Private::up(quint32 serial, quint32 time, qint32 id) 0175 { 0176 TouchPoint *p = getActivePoint(id); 0177 if (!p) { 0178 return; 0179 } 0180 p->d->timestamps << time; 0181 p->d->upSerial = serial; 0182 p->d->down = false; 0183 Q_EMIT q->pointRemoved(p); 0184 // check whether the sequence ended 0185 for (auto it = sequence.constBegin(); it != sequence.constEnd(); ++it) { 0186 if ((*it)->isDown()) { 0187 return; 0188 } 0189 } 0190 // no touch point is down 0191 active = false; 0192 Q_EMIT q->sequenceEnded(); 0193 } 0194 0195 void Touch::Private::motionCallback(void *data, wl_touch *touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) 0196 { 0197 auto t = reinterpret_cast<Touch::Private *>(data); 0198 Q_ASSERT(t->touch == touch); 0199 t->motion(time, id, QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y))); 0200 } 0201 0202 void Touch::Private::motion(quint32 time, qint32 id, const QPointF &position) 0203 { 0204 TouchPoint *p = getActivePoint(id); 0205 if (!p) { 0206 return; 0207 } 0208 p->d->positions << position; 0209 p->d->timestamps << time; 0210 Q_EMIT q->pointMoved(p); 0211 } 0212 0213 void Touch::Private::frameCallback(void *data, wl_touch *touch) 0214 { 0215 auto t = reinterpret_cast<Touch::Private *>(data); 0216 Q_ASSERT(t->touch == touch); 0217 Q_EMIT t->q->frameEnded(); 0218 } 0219 0220 void Touch::Private::cancelCallback(void *data, wl_touch *touch) 0221 { 0222 auto t = reinterpret_cast<Touch::Private *>(data); 0223 Q_ASSERT(t->touch == touch); 0224 t->active = false; 0225 Q_EMIT t->q->sequenceCanceled(); 0226 } 0227 0228 Touch::Touch(QObject *parent) 0229 : QObject(parent) 0230 , d(new Private(this)) 0231 { 0232 } 0233 0234 Touch::~Touch() 0235 { 0236 release(); 0237 } 0238 0239 void Touch::destroy() 0240 { 0241 d->touch.destroy(); 0242 } 0243 0244 void Touch::release() 0245 { 0246 d->touch.release(); 0247 } 0248 0249 void Touch::setup(wl_touch *touch) 0250 { 0251 d->setup(touch); 0252 } 0253 0254 bool Touch::isValid() const 0255 { 0256 return d->touch.isValid(); 0257 } 0258 0259 Touch::operator wl_touch *() const 0260 { 0261 return d->touch; 0262 } 0263 0264 Touch::operator wl_touch *() 0265 { 0266 return d->touch; 0267 } 0268 0269 QList<TouchPoint *> Touch::sequence() const 0270 { 0271 return d->sequence; 0272 } 0273 0274 } 0275 } 0276 0277 #include "moc_touch.cpp"