From 296912c3a3ccdc48cdc318d761b4154a8d7db359 Mon Sep 17 00:00:00 2001
From: Johan Klokkhammer Helsing <johan.helsing@qt.io>
Date: Wed, 12 Oct 2016 14:29:01 +0200
Subject: [PATCH] Client: Fix touch getting stuck after drag-and-drop

wl_touch.up is not sent by compositors when dragging, so release all touch
points when the drag ends.

Task-number: QTBUG-56187
Change-Id: I1c3d03c72e75a551355c50bb5d82433f5e2e35f0
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
---
 src/client/qwaylanddnd.cpp         |  2 +-
 src/client/qwaylandinputdevice.cpp | 16 ++++++++++++++++
 src/client/qwaylandinputdevice_p.h |  2 ++
 3 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/src/client/qwaylanddnd.cpp b/src/client/qwaylanddnd.cpp
index 31b1c491..7c2cc8ee 100644
--- a/src/client/qwaylanddnd.cpp
+++ b/src/client/qwaylanddnd.cpp
@@ -91,7 +91,7 @@ void QWaylandDrag::drop(const QPoint &globalPos)
 
 void QWaylandDrag::endDrag()
 {
-    // Do nothing
+    m_display->currentInputDevice()->handleEndDrag();
 }
 
 void QWaylandDrag::updateTarget(const QString &mimeType)
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index 6c72c59d..669deac2 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -256,6 +256,12 @@ void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window)
         mTouch->mFocus = 0;
 }
 
+void QWaylandInputDevice::handleEndDrag()
+{
+    if (mTouch)
+        mTouch->releasePoints();
+}
+
 void QWaylandInputDevice::setDataDevice(QWaylandDataDevice *device)
 {
     mDataDevice = device;
@@ -827,6 +833,16 @@ bool QWaylandInputDevice::Touch::allTouchPointsReleased()
     return true;
 }
 
+void QWaylandInputDevice::Touch::releasePoints()
+{
+    Q_FOREACH (const QWindowSystemInterface::TouchPoint &previousPoint, mPrevTouchPoints) {
+        QWindowSystemInterface::TouchPoint tp = previousPoint;
+        tp.state = Qt::TouchPointReleased;
+        mTouchPoints.append(tp);
+    }
+    touch_frame();
+}
+
 void QWaylandInputDevice::Touch::touch_frame()
 {
     // Copy all points, that are in the previous but not in the current list, as stationary.
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index e38ad2f8..f1a82d45 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -98,6 +98,7 @@ public:
     void setCursor(struct wl_buffer *buffer, const QPoint &hotSpot, const QSize &size);
     void setCursor(const QSharedPointer<QWaylandBuffer> &buffer, const QPoint &hotSpot);
     void handleWindowDestroyed(QWaylandWindow *window);
+    void handleEndDrag();
 
     void setDataDevice(QWaylandDataDevice *device);
     QWaylandDataDevice *dataDevice() const;
@@ -259,6 +260,7 @@ public:
     void touch_cancel() Q_DECL_OVERRIDE;
 
     bool allTouchPointsReleased();
+    void releasePoints();
 
     QWaylandInputDevice *mParent;
     QWaylandWindow *mFocus;
-- 
GitLab