on xenial help sign in
TouchGate can no longer leak stored QTouchEvents
2719567Daniel d'Andrada
plugins/Ubuntu/Gestures/TouchGate.cpp+82−56
@@ -125,23 +125,18 @@ void TouchGate::storeTouchEvent(const QTouchEvent *event)
125 qDebug() << "[TouchGate] Storing" << qPrintable(touchEventToString(event));
125 qDebug() << "[TouchGate] Storing" << qPrintable(touchEventToString(event));
126 #endif
126 #endif
127
127
128− QTouchEvent *clonedEvent = new QTouchEvent(event->type(),
128+ TouchEvent clonedEvent(event);
129− event->device(),
130− event->modifiers(),
131− event->touchPointStates(),
132− event->touchPoints());
133−
134− m_storedEvents.append(clonedEvent);
129+ m_storedEvents.append(std::move(clonedEvent));
135}
130}
136
131
137void TouchGate::removeTouchFromStoredEvents(int touchId)
132void TouchGate::removeTouchFromStoredEvents(int touchId)
138{
133{
139 int i = 0;
134 int i = 0;
140 while (i < m_storedEvents.count()) {
135 while (i < m_storedEvents.count()) {
141− QTouchEvent *event = m_storedEvents[i];
136+ TouchEvent &event = m_storedEvents[i];
142− bool removed = removeTouchFromEvent(touchId, event);
137+ bool removed = event.removeTouch(touchId);
143
138
144− if (removed && event->touchPoints().isEmpty()) {
139+ if (removed && event.touchPoints.isEmpty()) {
145 m_storedEvents.removeAt(i);
140 m_storedEvents.removeAt(i);
146 } else {
141 } else {
147 ++i;
142 ++i;
@@ -149,33 +144,11 @@ void TouchGate::removeTouchFromStoredEvents(int touchId)
149 }
144 }
150}
145}
151
146
152−bool TouchGate::removeTouchFromEvent(int touchId, QTouchEvent *event)
153−{
154− const QList<QTouchEvent::TouchPoint> &eventTouchPoints = event->touchPoints();
155−
156− int indexToRemove = -1;
157− for (int i = 0; i < eventTouchPoints.count() && indexToRemove < 0; ++i) {
158− if (eventTouchPoints[i].id() == touchId) {
159− indexToRemove = i;
160− }
161− }
162−
163− if (indexToRemove >= 0) {
164− QList<QTouchEvent::TouchPoint> newTouchPointsList = eventTouchPoints;
165− newTouchPointsList.removeAt(indexToRemove);
166− event->setTouchPoints(newTouchPointsList);
167− return true;
168− } else {
169− return false;
170− }
171−}
172−
173void TouchGate::dispatchFullyOwnedEvents()
147void TouchGate::dispatchFullyOwnedEvents()
174{
148{
175 while (!m_storedEvents.isEmpty() && eventIsFullyOwned(m_storedEvents.first())) {
149 while (!m_storedEvents.isEmpty() && eventIsFullyOwned(m_storedEvents.first())) {
176− QTouchEvent *event = m_storedEvents.takeFirst();
150+ TouchEvent event = m_storedEvents.takeFirst();
177 dispatchTouchEventToTarget(event);
151 dispatchTouchEventToTarget(event);
178− delete event;
179 }
152 }
180}
153}
181
154
@@ -200,11 +173,10 @@ QString TouchGate::oldestPendingTouchIdsString()
200}
173}
201#endif
174#endif
202
175
203−bool TouchGate::eventIsFullyOwned(const QTouchEvent *event) const
176+bool TouchGate::eventIsFullyOwned(const TouchGate::TouchEvent &event) const
204{
177{
205− auto touchPoints = event->touchPoints();
206− for (int i = 0; i < touchPoints.count(); ++i) {
178+ for (int i = 0; i < event.touchPoints.count(); ++i) {
207− if (!isTouchPointOwned(touchPoints[i].id())) {
179+ if (!isTouchPointOwned(event.touchPoints[i].id())) {
208 return false;
180 return false;
209 }
181 }
210 }
182 }
@@ -224,9 +196,37 @@ void TouchGate::setTargetItem(QQuickItem *item)
224 Q_EMIT targetItemChanged(item);
196 Q_EMIT targetItemChanged(item);
225}
197}
226
198
199+void TouchGate::dispatchTouchEventToTarget(const TouchEvent &event)
200+{
201+ dispatchTouchEventToTarget(event.eventType,
202+ event.device,
203+ event.modifiers,
204+ event.touchPoints,
205+ event.target,
206+ event.window,
207+ event.timestamp);
208+}
209+
227void TouchGate::dispatchTouchEventToTarget(QTouchEvent* event)
210void TouchGate::dispatchTouchEventToTarget(QTouchEvent* event)
228{
211{
212+ dispatchTouchEventToTarget(event->type(),
213+ event->device(),
214+ event->modifiers(),
215+ event->touchPoints(),
216+ event->target(),
217+ event->window(),
218+ event->timestamp());
219+}
220+
221+void TouchGate::dispatchTouchEventToTarget(QEvent::Type eventType,
222+ QTouchDevice *device,
223+ Qt::KeyboardModifiers modifiers,
224+ const QList<QTouchEvent::TouchPoint> &touchPoints,
225+ QObject *target,
226+ QWindow *window,
227+ ulong timestamp)
228+{
229− removeTouchInfoForEndedTouches(event);
229+ removeTouchInfoForEndedTouches(touchPoints);
230
230
231 if (m_targetItem.isNull()) {
231 if (m_targetItem.isNull()) {
232 qWarning("[TouchGate] Cannot dispatch touch event because target item is null");
232 qWarning("[TouchGate] Cannot dispatch touch event because target item is null");
@@ -244,9 +244,10 @@ void TouchGate::dispatchTouchEventToTarget(QTouchEvent* event)
244 }
244 }
245
245
246 // Map touch points to targetItem coordinates
246 // Map touch points to targetItem coordinates
247− QList<QTouchEvent::TouchPoint> touchPoints = event->touchPoints();
247+ QList<QTouchEvent::TouchPoint> targetTouchPoints = touchPoints;
248− transformTouchPoints(touchPoints, QQuickItemPrivate::get(targetItem)->windowToItemTransform());
248+ transformTouchPoints(targetTouchPoints, QQuickItemPrivate::get(targetItem)->windowToItemTransform());
249− QTouchEvent *eventForTargetItem = touchEventWithPoints(*event, touchPoints);
249+ QTouchEvent *eventForTargetItem = createQTouchEvent(eventType, device, modifiers, targetTouchPoints,
250+ target, window, timestamp);
250
251
251 #if TOUCHGATE_DEBUG
252 #if TOUCHGATE_DEBUG
252 qDebug() << "[TouchGate] dispatching" << qPrintable(touchEventToString(eventForTargetItem))
253 qDebug() << "[TouchGate] dispatching" << qPrintable(touchEventToString(eventForTargetItem))
@@ -271,15 +272,18 @@ void TouchGate::transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints
271 }
272 }
272}
273}
273
274
274−// NB: From QQuickWindow
275+QTouchEvent *TouchGate::createQTouchEvent(QEvent::Type eventType,
275−QTouchEvent *TouchGate::touchEventWithPoints(const QTouchEvent &event,
276+ QTouchDevice *device,
277+ Qt::KeyboardModifiers modifiers,
276− const QList<QTouchEvent::TouchPoint> &newPoints)
278+ const QList<QTouchEvent::TouchPoint> &touchPoints,
279+ QObject *target,
280+ QWindow *window,
281+ ulong timestamp)
277{
282{
278 Qt::TouchPointStates eventStates = 0;
283 Qt::TouchPointStates eventStates = 0;
279− for (int i=0; i<newPoints.count(); i++)
284+ for (int i = 0; i < touchPoints.count(); i++)
280− eventStates |= newPoints[i].state();
285+ eventStates |= touchPoints[i].state();
281 // if all points have the same state, set the event type accordingly
286 // if all points have the same state, set the event type accordingly
282− QEvent::Type eventType = event.type();
283 switch (eventStates) {
287 switch (eventStates) {
284 case Qt::TouchPointPressed:
288 case Qt::TouchPointPressed:
285 eventType = QEvent::TouchBegin;
289 eventType = QEvent::TouchBegin;
@@ -293,21 +297,19 @@ QTouchEvent *TouchGate::touchEventWithPoints(const QTouchEvent &event,
293 }
297 }
294
298
295 QTouchEvent *touchEvent = new QTouchEvent(eventType);
299 QTouchEvent *touchEvent = new QTouchEvent(eventType);
296− touchEvent->setWindow(event.window());
300+ touchEvent->setWindow(window);
297− touchEvent->setTarget(event.target());
301+ touchEvent->setTarget(target);
298− touchEvent->setDevice(event.device());
302+ touchEvent->setDevice(device);
299− touchEvent->setModifiers(event.modifiers());
303+ touchEvent->setModifiers(modifiers);
300− touchEvent->setTouchPoints(newPoints);
304+ touchEvent->setTouchPoints(touchPoints);
301 touchEvent->setTouchPointStates(eventStates);
305 touchEvent->setTouchPointStates(eventStates);
302− touchEvent->setTimestamp(event.timestamp());
306+ touchEvent->setTimestamp(timestamp);
303 touchEvent->accept();
307 touchEvent->accept();
304 return touchEvent;
308 return touchEvent;
305}
309}
306
310
307−void TouchGate::removeTouchInfoForEndedTouches(QTouchEvent *event)
311+void TouchGate::removeTouchInfoForEndedTouches(const QList<QTouchEvent::TouchPoint> &touchPoints)
308{
312{
309− const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
310−
311 for (int i = 0; i < touchPoints.size(); ++i) {\
313 for (int i = 0; i < touchPoints.size(); ++i) {\
312 const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
314 const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
313
315
@@ -319,3 +321,27 @@ void TouchGate::removeTouchInfoForEndedTouches(QTouchEvent *event)
319 }
321 }
320 }
322 }
321}
323}
324+
325+TouchGate::TouchEvent::TouchEvent(const QTouchEvent *event)
326+ : eventType(event->type())
327+ , device(event->device())
328+ , modifiers(event->modifiers())
329+ , touchPoints(event->touchPoints())
330+ , target(event->target())
331+ , window(event->window())
332+ , timestamp(event->timestamp())
333+{
334+}
335+
336+bool TouchGate::TouchEvent::removeTouch(int touchId)
337+{
338+ bool removed = false;
339+ for (int i = 0; i < touchPoints.count() && !removed; ++i) {
340+ if (touchPoints[i].id() == touchId) {
341+ touchPoints.removeAt(i);
342+ removed = true;
343+ }
344+ }
345+
346+ return removed;
347+}
plugins/Ubuntu/Gestures/TouchGate.h+37−7
@@ -56,25 +56,55 @@ Q_SIGNALS:
56protected:
56protected:
57 void touchEvent(QTouchEvent *event) override;
57 void touchEvent(QTouchEvent *event) override;
58private:
58private:
59+ class TouchEvent {
60+ public:
61+ TouchEvent(const QTouchEvent *event);
62+
63+ bool removeTouch(int touchId);
64+
65+ QEvent::Type eventType;
66+ QTouchDevice *device;
67+ Qt::KeyboardModifiers modifiers;
68+ Qt::TouchPointStates touchPointStates;
69+ QList<QTouchEvent::TouchPoint> touchPoints;
70+ QObject *target;
71+ QWindow *window;
72+ ulong timestamp;
73+ };
74+
59 void touchOwnershipEvent(TouchOwnershipEvent *event);
75 void touchOwnershipEvent(TouchOwnershipEvent *event);
60 bool isTouchPointOwned(int touchId) const;
76 bool isTouchPointOwned(int touchId) const;
61 void storeTouchEvent(const QTouchEvent *event);
77 void storeTouchEvent(const QTouchEvent *event);
62 void removeTouchFromStoredEvents(int touchId);
78 void removeTouchFromStoredEvents(int touchId);
63 void dispatchFullyOwnedEvents();
79 void dispatchFullyOwnedEvents();
64− bool removeTouchFromEvent(int touchId, QTouchEvent *event);
65− bool eventIsFullyOwned(const QTouchEvent *event) const;
80+ bool eventIsFullyOwned(const TouchEvent &event) const;
81+
82+ void dispatchTouchEventToTarget(const TouchEvent &event);
66 void dispatchTouchEventToTarget(QTouchEvent* event);
83 void dispatchTouchEventToTarget(QTouchEvent* event);
84+ void dispatchTouchEventToTarget(
85+ QEvent::Type eventType,
86+ QTouchDevice *device,
87+ Qt::KeyboardModifiers modifiers,
88+ const QList<QTouchEvent::TouchPoint> &touchPoints,
89+ QObject *target,
90+ QWindow *window,
91+ ulong timestamp);
92+
67 void transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform);
93 void transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform);
68− QTouchEvent *touchEventWithPoints(const QTouchEvent &event,
94+ static QTouchEvent *createQTouchEvent(QEvent::Type eventType,
95+ QTouchDevice *device,
96+ Qt::KeyboardModifiers modifiers,
69− const QList<QTouchEvent::TouchPoint> &newPoints);
97+ const QList<QTouchEvent::TouchPoint> &touchPoints,
98+ QObject *target,
99+ QWindow *window,
100+ ulong timestamp);
70− void removeTouchInfoForEndedTouches(QTouchEvent *event);
101+ void removeTouchInfoForEndedTouches(const QList<QTouchEvent::TouchPoint> &touchPoints);
71
102
72 #if TOUCHGATE_DEBUG
103 #if TOUCHGATE_DEBUG
73 QString oldestPendingTouchIdsString();
104 QString oldestPendingTouchIdsString();
74 #endif
105 #endif
75
106
76− // TODO: Optimize storage of buffered events
77− QList<QTouchEvent*> m_storedEvents;
107+ QList<TouchEvent> m_storedEvents;
78
108
79 enum {
109 enum {
80 OwnershipUndefined,
110 OwnershipUndefined,