17 #include "TouchGate.h" 19 #include <QCoreApplication> 21 #include <QQuickWindow> 23 #include <UbuntuGestures/private/touchownershipevent_p.h> 24 #include <UbuntuGestures/private/touchregistry_p.h> 27 #define ugDebug(params) qDebug().nospace() << "[TouchGate(" << (void*)this << ")] " << params 28 #include <UbuntuGestures/private/debughelpers_p.h> 29 #else // TOUCHGATE_DEBUG 30 #define ugDebug(params) ((void)0) 31 #endif // TOUCHGATE_DEBUG 35 TouchGate::TouchGate(QQuickItem *parent)
38 connect(
this, &QQuickItem::enabledChanged,
39 this, &TouchGate::onEnabledChanged);
42 bool TouchGate::event(QEvent *e)
44 if (e->type() == TouchOwnershipEvent::touchOwnershipEventType()) {
45 touchOwnershipEvent(static_cast<TouchOwnershipEvent*>(e));
48 return QQuickItem::event(e);
52 void TouchGate::touchEvent(QTouchEvent *event)
54 ugDebug(
"got touch event" << qPrintable(touchEventToString(event)));
57 const QList<QTouchEvent::TouchPoint> &touchPoints =
event->touchPoints();
58 QList<QTouchEvent::TouchPoint> validTouchPoints;
59 bool ownsAllTouches =
true;
60 for (
int i = 0; i < touchPoints.count(); ++i) {
61 const QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
63 if (touchPoint.state() == Qt::TouchPointPressed) {
64 Q_ASSERT(!m_touchInfoMap.contains(touchPoint.id()));
65 m_touchInfoMap[touchPoint.id()].ownership = OwnershipRequested;
66 m_touchInfoMap[touchPoint.id()].ended =
false;
67 TouchRegistry::instance()->requestTouchOwnership(touchPoint.id(),
this);
70 if (m_touchInfoMap.contains(touchPoint.id())) {
71 validTouchPoints.append(touchPoint);
73 ownsAllTouches &= m_touchInfoMap[touchPoint.id()].ownership == OwnershipGranted;
75 if (touchPoint.state() == Qt::TouchPointReleased) {
76 m_touchInfoMap[touchPoint.id()].ended =
true;
82 if (validTouchPoints.isEmpty()) {
88 if (m_storedEvents.isEmpty()) {
90 removeTouchInfoForEndedTouches(validTouchPoints);
91 m_dispatcher.dispatch(event->device(),
event->modifiers(), validTouchPoints,
92 event->window(),
event->timestamp());
96 ugDebug(
"Storing event because thouches " << qPrintable(oldestPendingTouchIdsString())
97 <<
" are still pending ownership.");
98 storeTouchEvent(event->device(),
event->modifiers(), validTouchPoints,
99 event->window(),
event->timestamp());
103 storeTouchEvent(event->device(),
event->modifiers(), validTouchPoints,
104 event->window(),
event->timestamp());
108 void TouchGate::itemChange(ItemChange change,
const ItemChangeData &value)
110 if (change == QQuickItem::ItemSceneChange) {
111 if (value.window !=
nullptr) {
112 value.window->installEventFilter(TouchRegistry::instance());
117 void TouchGate::touchOwnershipEvent(TouchOwnershipEvent *event)
122 if (m_touchInfoMap.contains(event->touchId())) {
123 TouchInfo &touchInfo = m_touchInfoMap[
event->touchId()];
125 if (event->gained()) {
126 ugDebug(
"Got ownership of touch " << event->touchId());
127 touchInfo.ownership = OwnershipGranted;
129 ugDebug(
"Lost ownership of touch " << event->touchId());
130 m_touchInfoMap.remove(event->touchId());
131 removeTouchFromStoredEvents(event->touchId());
134 dispatchFullyOwnedEvents();
141 bool TouchGate::isTouchPointOwned(
int touchId)
const 143 return m_touchInfoMap[touchId].ownership == OwnershipGranted;
146 void TouchGate::storeTouchEvent(QTouchDevice *device,
147 Qt::KeyboardModifiers modifiers,
148 const QList<QTouchEvent::TouchPoint> &touchPoints,
152 ugDebug(
"Storing" << touchPoints);
153 TouchEvent event(device, modifiers, touchPoints, window, timestamp);
154 m_storedEvents.append(std::move(event));
157 void TouchGate::removeTouchFromStoredEvents(
int touchId)
160 while (i < m_storedEvents.count()) {
161 TouchEvent &
event = m_storedEvents[i];
162 bool removed =
event.removeTouch(touchId);
164 if (removed && event.touchPoints.isEmpty()) {
165 m_storedEvents.removeAt(i);
172 void TouchGate::dispatchFullyOwnedEvents()
174 while (!m_storedEvents.isEmpty() && eventIsFullyOwned(m_storedEvents.first())) {
175 TouchEvent
event = m_storedEvents.takeFirst();
176 dispatchTouchEventToTarget(event);
181 QString TouchGate::oldestPendingTouchIdsString()
183 Q_ASSERT(!m_storedEvents.isEmpty());
187 const auto &touchPoints = m_storedEvents.first().touchPoints;
188 for (
int i = 0; i < touchPoints.count(); ++i) {
189 if (!isTouchPointOwned(touchPoints[i].
id())) {
190 if (!str.isEmpty()) {
193 str.append(QString::number(touchPoints[i].
id()));
201 bool TouchGate::eventIsFullyOwned(
const TouchGate::TouchEvent &event)
const 203 for (
int i = 0; i <
event.touchPoints.count(); ++i) {
204 if (!isTouchPointOwned(event.touchPoints[i].id())) {
212 void TouchGate::setTargetItem(QQuickItem *item)
217 if (item == m_dispatcher.targetItem())
220 m_dispatcher.setTargetItem(item);
221 Q_EMIT targetItemChanged(item);
224 void TouchGate::dispatchTouchEventToTarget(
const TouchEvent &event)
226 removeTouchInfoForEndedTouches(event.touchPoints);
227 m_dispatcher.dispatch(event.device,
234 void TouchGate::removeTouchInfoForEndedTouches(
const QList<QTouchEvent::TouchPoint> &touchPoints)
236 for (
int i = 0; i < touchPoints.size(); ++i) {\
237 const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i);
239 if (touchPoint.state() == Qt::TouchPointReleased) {
240 Q_ASSERT(m_touchInfoMap.contains(touchPoint.id()));
241 Q_ASSERT(m_touchInfoMap[touchPoint.id()].ended);
242 Q_ASSERT(m_touchInfoMap[touchPoint.id()].ownership == OwnershipGranted);
243 m_touchInfoMap.remove(touchPoint.id());
248 void TouchGate::onEnabledChanged()
250 ugDebug(
" enabled = " << isEnabled());
256 void TouchGate::reset()
258 m_storedEvents.clear();
259 m_touchInfoMap.clear();
260 m_dispatcher.reset();
263 TouchGate::TouchEvent::TouchEvent(QTouchDevice *device,
264 Qt::KeyboardModifiers modifiers,
265 const QList<QTouchEvent::TouchPoint> &touchPoints,
269 , modifiers(modifiers)
270 , touchPoints(touchPoints)
272 , timestamp(timestamp)
276 bool TouchGate::TouchEvent::removeTouch(
int touchId)
278 bool removed =
false;
279 for (
int i = 0; i < touchPoints.count() && !removed; ++i) {
280 if (touchPoints[i].
id() == touchId) {
281 touchPoints.removeAt(i);