17 #include "TouchGate.h"
19 #include <QCoreApplication>
21 #include <QQuickWindow>
23 #include <TouchOwnershipEvent.h>
24 #include <TouchRegistry.h>
27 #define ugDebug(params) qDebug().nospace() << "[TouchGate(" << (void*)this << ")] " << params
28 #include <DebugHelpers.h>
29 #else // TOUCHGATE_DEBUG
30 #define ugDebug(params) ((void)0)
31 #endif // TOUCHGATE_DEBUG
33 TouchGate::TouchGate(QQuickItem *parent)
36 connect(
this, &QQuickItem::enabledChanged,
37 this, &TouchGate::onEnabledChanged);
40 bool TouchGate::event(QEvent *e)
42 if (e->type() == TouchOwnershipEvent::touchOwnershipEventType()) {
43 touchOwnershipEvent(static_cast<TouchOwnershipEvent *>(e));
46 return QQuickItem::event(e);
50 void TouchGate::touchEvent(QTouchEvent *event)
52 ugDebug(
"got touch event" << qPrintable(touchEventToString(event)));
55 const QList<QTouchEvent::TouchPoint> &touchPoints =
event->touchPoints();
56 QList<QTouchEvent::TouchPoint> validTouchPoints;
57 bool ownsAllTouches =
true;
58 for (
int i = 0; i < touchPoints.count(); ++i) {
59 const QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
61 if (touchPoint.state() == Qt::TouchPointPressed) {
62 Q_ASSERT(!m_touchInfoMap.contains(touchPoint.id()));
63 m_touchInfoMap[touchPoint.id()].ownership = OwnershipRequested;
64 m_touchInfoMap[touchPoint.id()].ended =
false;
65 TouchRegistry::instance()->requestTouchOwnership(touchPoint.id(),
this);
68 if (m_touchInfoMap.contains(touchPoint.id())) {
69 validTouchPoints.append(touchPoint);
71 ownsAllTouches &= m_touchInfoMap[touchPoint.id()].ownership == OwnershipGranted;
73 if (touchPoint.state() == Qt::TouchPointReleased) {
74 m_touchInfoMap[touchPoint.id()].ended =
true;
80 if (validTouchPoints.isEmpty()) {
86 if (m_storedEvents.isEmpty()) {
88 removeTouchInfoForEndedTouches(validTouchPoints);
89 m_dispatcher.dispatch(event->device(),
event->modifiers(), validTouchPoints,
90 event->window(),
event->timestamp());
94 ugDebug(
"Storing event because thouches " << qPrintable(oldestPendingTouchIdsString())
95 <<
" are still pending ownership.");
96 storeTouchEvent(event->device(),
event->modifiers(), validTouchPoints,
97 event->window(),
event->timestamp());
101 storeTouchEvent(event->device(),
event->modifiers(), validTouchPoints,
102 event->window(),
event->timestamp());
106 void TouchGate::itemChange(ItemChange change,
const ItemChangeData &value)
108 if (change == QQuickItem::ItemSceneChange) {
109 if (value.window !=
nullptr) {
110 value.window->installEventFilter(TouchRegistry::instance());
115 void TouchGate::touchOwnershipEvent(TouchOwnershipEvent *event)
120 if (m_touchInfoMap.contains(event->touchId())) {
121 TouchInfo &touchInfo = m_touchInfoMap[
event->touchId()];
123 if (event->gained()) {
124 ugDebug(
"Got ownership of touch " << event->touchId());
125 touchInfo.ownership = OwnershipGranted;
127 ugDebug(
"Lost ownership of touch " << event->touchId());
128 m_touchInfoMap.remove(event->touchId());
129 removeTouchFromStoredEvents(event->touchId());
132 dispatchFullyOwnedEvents();
139 bool TouchGate::isTouchPointOwned(
int touchId)
const
141 return m_touchInfoMap[touchId].ownership == OwnershipGranted;
144 void TouchGate::storeTouchEvent(QTouchDevice *device,
145 Qt::KeyboardModifiers modifiers,
146 const QList<QTouchEvent::TouchPoint> &touchPoints,
150 ugDebug(
"Storing" << touchPoints);
151 TouchEvent event(device, modifiers, touchPoints, window, timestamp);
152 m_storedEvents.append(std::move(event));
155 void TouchGate::removeTouchFromStoredEvents(
int touchId)
158 while (i < m_storedEvents.count()) {
159 TouchEvent &
event = m_storedEvents[i];
160 bool removed =
event.removeTouch(touchId);
162 if (removed && event.touchPoints.isEmpty()) {
163 m_storedEvents.removeAt(i);
170 void TouchGate::dispatchFullyOwnedEvents()
172 while (!m_storedEvents.isEmpty() && eventIsFullyOwned(m_storedEvents.first())) {
173 TouchEvent
event = m_storedEvents.takeFirst();
174 dispatchTouchEventToTarget(event);
179 QString TouchGate::oldestPendingTouchIdsString()
181 Q_ASSERT(!m_storedEvents.isEmpty());
185 const auto &touchPoints = m_storedEvents.first().touchPoints;
186 for (
int i = 0; i < touchPoints.count(); ++i) {
187 if (!isTouchPointOwned(touchPoints[i].
id())) {
188 if (!str.isEmpty()) {
191 str.append(QString::number(touchPoints[i].
id()));
199 bool TouchGate::eventIsFullyOwned(
const TouchGate::TouchEvent &event)
const
201 for (
int i = 0; i <
event.touchPoints.count(); ++i) {
202 if (!isTouchPointOwned(event.touchPoints[i].id())) {
210 void TouchGate::setTargetItem(QQuickItem *item)
215 if (item == m_dispatcher.targetItem())
218 m_dispatcher.setTargetItem(item);
219 Q_EMIT targetItemChanged(item);
222 void TouchGate::dispatchTouchEventToTarget(
const TouchEvent &event)
224 removeTouchInfoForEndedTouches(event.touchPoints);
225 m_dispatcher.dispatch(event.device,
232 void TouchGate::removeTouchInfoForEndedTouches(
const QList<QTouchEvent::TouchPoint> &touchPoints)
234 for (
int i = 0; i < touchPoints.size(); ++i) {\
235 const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
237 if (touchPoint.state() == Qt::TouchPointReleased) {
238 Q_ASSERT(m_touchInfoMap.contains(touchPoint.id()));
239 Q_ASSERT(m_touchInfoMap[touchPoint.id()].ended);
240 Q_ASSERT(m_touchInfoMap[touchPoint.id()].ownership == OwnershipGranted);
241 m_touchInfoMap.remove(touchPoint.id());
246 void TouchGate::onEnabledChanged()
248 ugDebug(
" enabled = " << isEnabled());
254 void TouchGate::reset()
256 m_storedEvents.clear();
257 m_touchInfoMap.clear();
258 m_dispatcher.reset();
261 TouchGate::TouchEvent::TouchEvent(QTouchDevice *device,
262 Qt::KeyboardModifiers modifiers,
263 const QList<QTouchEvent::TouchPoint> &touchPoints,
267 , modifiers(modifiers)
268 , touchPoints(touchPoints)
270 , timestamp(timestamp)
274 bool TouchGate::TouchEvent::removeTouch(
int touchId)
276 bool removed =
false;
277 for (
int i = 0; i < touchPoints.count() && !removed; ++i) {
278 if (touchPoints[i].
id() == touchId) {
279 touchPoints.removeAt(i);