From f089f453ae6ea3766a0ec41059371f6dc81ce9df Mon Sep 17 00:00:00 2001
From: Laszlo Agocs <laszlo.p.agocs@nokia.com>
Date: Thu, 9 Feb 2012 15:36:28 +0200
Subject: [PATCH] Add TouchCancel support.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

It maps to the protocol's touch_cancel pretty well. :)

Change-Id: Id417aac768106c2f6618b3e7ecb51d6929977c37
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
---
 .../wayland_wrapper/wlinputdevice.cpp         |  5 +++++
 .../platforms/wayland/qwaylandinputdevice.cpp | 12 ++++++++++-
 .../platforms/wayland/qwaylandtouch.cpp       | 20 +++++++++++++++----
 src/plugins/platforms/wayland/qwaylandtouch.h |  4 ++++
 4 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/src/compositor/wayland_wrapper/wlinputdevice.cpp b/src/compositor/wayland_wrapper/wlinputdevice.cpp
index fd08624b..28633562 100644
--- a/src/compositor/wayland_wrapper/wlinputdevice.cpp
+++ b/src/compositor/wayland_wrapper/wlinputdevice.cpp
@@ -174,6 +174,11 @@ void InputDevice::sendFullTouchEvent(QTouchEvent *event)
         return;
     }
 
+    if (event->type() == QEvent::TouchCancel) {
+        sendTouchCancelEvent();
+        return;
+    }
+
     TouchExtensionGlobal *ext = m_compositor->touchExtension();
     if (ext) {
         ext->postTouchEvent(event, mouseFocus());
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
index 126891fa..ee4ffc1c 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
@@ -45,6 +45,7 @@
 #include "qwaylandwindow.h"
 #include "qwaylandbuffer.h"
 #include "qwaylanddatadevicemanager.h"
+#include "qwaylandtouch.h"
 
 #include <QtGui/private/qpixmap_raster_p.h>
 #include <QtGui/QPlatformWindow>
@@ -508,7 +509,16 @@ void QWaylandInputDevice::handleTouchFrame()
 void QWaylandInputDevice::inputHandleTouchCancel(void *data, struct wl_input_device *wl_input_device)
 {
     Q_UNUSED(wl_input_device);
-    Q_UNUSED(data);
+    QWaylandInputDevice *self = static_cast<QWaylandInputDevice *>(data);
+
+    self->mPrevTouchPoints.clear();
+    self->mTouchPoints.clear();
+
+    QWaylandTouchExtension *touchExt = self->mQDisplay->touchExtension();
+    if (touchExt)
+        touchExt->touchCanceled();
+
+    QWindowSystemInterface::handleTouchCancelEvent(0, self->mTouchDevice);
 }
 
 const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = {
diff --git a/src/plugins/platforms/wayland/qwaylandtouch.cpp b/src/plugins/platforms/wayland/qwaylandtouch.cpp
index 82e1519b..6da99633 100644
--- a/src/plugins/platforms/wayland/qwaylandtouch.cpp
+++ b/src/plugins/platforms/wayland/qwaylandtouch.cpp
@@ -49,6 +49,7 @@ QWaylandTouchExtension::QWaylandTouchExtension(QWaylandDisplay *display, uint32_
     mDisplay = display;
     mPointsLeft = 0;
     mFlags = 0;
+    mMouseSourceId = -1;
 
     mTouch = static_cast<struct wl_touch_extension *>(wl_display_bind(display->wl_display(), id, &wl_touch_extension_interface));
     wl_touch_extension_add_listener(mTouch, &touch_listener, this);
@@ -173,10 +174,13 @@ void QWaylandTouchExtension::sendTouchEvent()
             const QWindowSystemInterface::TouchPoint &tp(mTouchPoints.at(i));
             if (tp.id == mMouseSourceId) {
                 Qt::MouseButtons buttons = tp.state == Qt::TouchPointReleased ? Qt::NoButton : Qt::LeftButton;
-                QPointF globalPos = tp.area.center();
-                QPointF delta = globalPos - globalPos.toPoint();
-                QPointF localPos = mTargetWindow->mapFromGlobal(globalPos.toPoint()) + delta;
-                QWindowSystemInterface::handleMouseEvent(0, mTimestamp, localPos, globalPos, buttons);
+                mLastMouseGlobal = tp.area.center();
+                QPoint globalPoint = mLastMouseGlobal.toPoint();
+                QPointF delta = mLastMouseGlobal - globalPoint;
+                mLastMouseLocal = mTargetWindow->mapFromGlobal(globalPoint) + delta;
+                QWindowSystemInterface::handleMouseEvent(0, mTimestamp, mLastMouseLocal, mLastMouseGlobal, buttons);
+                if (buttons == Qt::NoButton)
+                    mMouseSourceId = -1;
                 break;
             }
         }
@@ -189,6 +193,14 @@ void QWaylandTouchExtension::sendTouchEvent()
         mPrevTouchPoints.clear();
 }
 
+void QWaylandTouchExtension::touchCanceled()
+{
+    mTouchPoints.clear();
+    mPrevTouchPoints.clear();
+    if (mMouseSourceId != -1)
+        QWindowSystemInterface::handleMouseEvent(0, mTimestamp, mLastMouseLocal, mLastMouseGlobal, Qt::NoButton);
+}
+
 void QWaylandTouchExtension::handle_configure(void *data, wl_touch_extension *ext, uint32_t flags)
 {
     Q_UNUSED(ext);
diff --git a/src/plugins/platforms/wayland/qwaylandtouch.h b/src/plugins/platforms/wayland/qwaylandtouch.h
index b29d136c..4ac0af26 100644
--- a/src/plugins/platforms/wayland/qwaylandtouch.h
+++ b/src/plugins/platforms/wayland/qwaylandtouch.h
@@ -52,6 +52,8 @@ class QWaylandTouchExtension
 public:
     QWaylandTouchExtension(QWaylandDisplay *display, uint32_t id);
 
+    void touchCanceled();
+
 private:
     QWaylandDisplay *mDisplay;
     wl_touch_extension *mTouch;
@@ -86,6 +88,8 @@ private:
     int mPointsLeft;
     uint32_t mFlags;
     int mMouseSourceId;
+    QPointF mLastMouseLocal;
+    QPointF mLastMouseGlobal;
     QWindow *mTargetWindow;
 };
 
-- 
GitLab