Introduce a touch protocol extension.
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>
Fri, 13 Jan 2012 15:37:49 +0000 (17:37 +0200)
committerJørgen Lind <jorgen.lind@nokia.com>
Fri, 13 Jan 2012 16:28:40 +0000 (17:28 +0100)
Using this opt-in protocol extension all data from QTouchEvent will
properly be delivered to the clients.

By default compositors will still use the standard and limited
protocol for touch events to remain compatible with non-Qt
clients. However by calling enableTouchExtension() in the compositor,
touch events will be sent through the new protocol and thus Qt clients
will receive proper QTouchEvents. Non-Qt clients will get no touch
data in this mode.

The contents of the rawScreenPositions() list are not yet delivered as
the size implications remain to be checked.

Change-Id: I981b9c4d44ea808a95b770bf948320abd47fc036
Sanity-Review: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
18 files changed:
examples/qwindow-compositor/main.cpp
examples/qwindow-compositor/qwindowcompositor.cpp
extensions/touch-extension.xml [new file with mode: 0644]
src/compositor/compositor_api/waylandcompositor.cpp
src/compositor/compositor_api/waylandcompositor.h
src/compositor/wayland_wrapper/wayland_wrapper.pri
src/compositor/wayland_wrapper/wlcompositor.cpp
src/compositor/wayland_wrapper/wlcompositor.h
src/compositor/wayland_wrapper/wlinputdevice.cpp
src/compositor/wayland_wrapper/wltouch.cpp [new file with mode: 0644]
src/compositor/wayland_wrapper/wltouch.h [new file with mode: 0644]
src/plugins/platforms/wayland/qwaylanddisplay.cpp
src/plugins/platforms/wayland/qwaylanddisplay.h
src/plugins/platforms/wayland/qwaylandinputdevice.cpp
src/plugins/platforms/wayland/qwaylandinputdevice.h
src/plugins/platforms/wayland/qwaylandtouch.cpp [new file with mode: 0644]
src/plugins/platforms/wayland/qwaylandtouch.h [new file with mode: 0644]
src/plugins/platforms/wayland/wayland.pro

index 3a64014..fdacaf5 100644 (file)
 
 int main(int argc, char *argv[])
 {
+    // Enable the following to have touch events generated from mouse events.
+    // Very handy for testing touch event delivery without a real touch device.
+    // QGuiApplication::setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true);
+
     QGuiApplication app(argc, argv);
     QScreen *screen = QGuiApplication::primaryScreen();
     QRect screenGeometry = screen->availableGeometry();
index 310ff19..1aa4f10 100644 (file)
@@ -14,6 +14,10 @@ QWindowCompositor::QWindowCompositor(QOpenGLWindow *window)
     , m_draggingWindow(0)
     , m_dragKeyIsPressed(false)
 {
+    // Enable the following to have all QTouchEvent-specific data delivered
+    // using a custom protocol extension.
+    // enableTouchExtension();
+
     enableSubSurfaceExtension();
     m_window->makeCurrent();
 
diff --git a/extensions/touch-extension.xml b/extensions/touch-extension.xml
new file mode 100644 (file)
index 0000000..a70fc13
--- /dev/null
@@ -0,0 +1,77 @@
+<!--
+# /****************************************************************************
+# **
+# ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+# ** Contact: Nokia Corporation (qt-info@nokia.com)
+# **
+# ** This file is part of qt-compositor.
+# **
+# ****************************************************************************/
+-->
+<protocol name="touch_extension">
+
+    <copyright>
+        Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+        All rights reserved.
+        Contact: Nokia Corporation (qt-info@nokia.com)
+
+        This file is part of the plugins of the Qt Toolkit.
+
+        $QT_BEGIN_LICENSE:LGPL$
+        GNU Lesser General Public License Usage
+        This file may be used under the terms of the GNU Lesser General Public
+        License version 2.1 as published by the Free Software Foundation and
+        appearing in the file LICENSE.LGPL included in the packaging of this
+        file. Please review the following information to ensure the GNU Lesser
+        General Public License version 2.1 requirements will be met:
+        http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+
+        In addition, as a special exception, Nokia gives you certain additional
+        rights. These rights are described in the Nokia Qt LGPL Exception
+        version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+
+        GNU General Public License Usage
+        Alternatively, this file may be used under the terms of the GNU General
+        Public License version 3.0 as published by the Free Software Foundation
+        and appearing in the file LICENSE.GPL included in the packaging of this
+        file. Please review the following information to ensure the GNU General
+        Public License version 3.0 requirements will be met:
+        http://www.gnu.org/copyleft/gpl.html.
+
+        Other Usage
+        Alternatively, this file may be used in accordance with the terms and
+        conditions contained in a signed written agreement between you and Nokia.
+
+
+
+
+
+        $QT_END_LICENSE$
+    </copyright>
+
+    <interface name="wl_touch" version="1">
+      <event name="touch">
+        <arg name="time" type="uint" />
+        <arg name="id" type="uint" />
+        <arg name="state" type="uint" />
+        <arg name="x" type="int" />
+        <arg name="y" type="int" />
+        <arg name="normalized_x" type="int" />
+        <arg name="normalized_y" type="int" />
+        <arg name="width" type="int" />
+        <arg name="height" type="int" />
+        <arg name="pressure" type="uint" />
+        <arg name="velocity_x" type="int" />
+        <arg name="velocity_y" type="int" />
+        <arg name="flags" type="uint" />
+        <arg name="rawdata" type="array" />
+      </event>
+
+      <event name="touch_frame">
+      </event>
+
+      <request name="dummy">
+      </request>
+
+    </interface>
+</protocol>
index 93abee4..8975031 100644 (file)
@@ -188,3 +188,8 @@ void WaylandCompositor::enableSubSurfaceExtension()
 {
     m_compositor->enableSubSurfaceExtension();
 }
+
+void WaylandCompositor::enableTouchExtension()
+{
+    m_compositor->enableTouchExtension();
+}
index d5cad38..ff45d36 100644 (file)
@@ -94,6 +94,8 @@ public:
 
     void enableSubSurfaceExtension();
 
+    void enableTouchExtension();
+
 private:
     static void retainedSelectionChanged(QMimeData *mimeData, void *param);
 
index 8bb7b17..4c1f6ee 100644 (file)
@@ -1,7 +1,8 @@
 WAYLANDSOURCES += \
                 $$PWD/../../../extensions/surface-extension.xml \
                 $$PWD/../../../extensions/sub-surface-extension.xml \
-                $$PWD/../../../extensions/output-extension.xml
+                $$PWD/../../../extensions/output-extension.xml \
+                $$PWD/../../../extensions/touch-extension.xml
 
 
 HEADERS += \
@@ -18,7 +19,8 @@ HEADERS += \
     $$PWD/wldatasource.h \
     $$PWD/wlextendedsurface.h \
     $$PWD/wlextendedoutput.h \
-    $$PWD/wlsubsurface.h
+    $$PWD/wlsubsurface.h \
+    $$PWD/wltouch.h
 
 SOURCES += \
     $$PWD/wlcompositor.cpp \
@@ -34,5 +36,6 @@ SOURCES += \
     $$PWD/wldatasource.cpp \
     $$PWD/wlextendedsurface.cpp \
     $$PWD/wlextendedoutput.cpp \
-    $$PWD/wlsubsurface.cpp
+    $$PWD/wlsubsurface.cpp \
+    $$PWD/wltouch.cpp
 
index 5b762f5..2e9464a 100644 (file)
@@ -51,6 +51,8 @@
 #include "wlextendedsurface.h"
 #include "wlsubsurface.h"
 #include "wlshellsurface.h"
+#include "wltouch.h"
+#include "wlinputdevice.h"
 
 #include <QWindow>
 #include <QSocketNotifier>
@@ -102,8 +104,8 @@ Compositor *Compositor::instance()
 
 Compositor::Compositor(WaylandCompositor *qt_compositor)
     : m_display(new Display)
-    , m_shm(m_display)
     , m_default_input_device(0)
+    , m_shm(m_display)
     , m_current_frame(0)
     , m_last_queued_buf(-1)
     , m_qt_compositor(qt_compositor)
@@ -115,6 +117,7 @@ Compositor::Compositor(WaylandCompositor *qt_compositor)
     , m_outputExtension(0)
     , m_surfaceExtension(0)
     , m_subSurfaceExtension(0)
+    , m_touchExtension(0)
     , m_retainNotify(0)
 {
     compositor = this;
@@ -373,6 +376,13 @@ QList<Wayland::Surface *> Compositor::surfacesForClient(wl_client *client)
     return ret;
 }
 
+void Compositor::enableTouchExtension()
+{
+    if (!m_touchExtension) {
+        m_touchExtension = new TouchExtensionGlobal(this);
+    }
+}
+
 void Compositor::setRetainedSelectionWatcher(RetainedSelectionFunc func, void *param)
 {
     m_retainNotify = func;
index 135228a..2dbc44f 100644 (file)
@@ -65,6 +65,7 @@ class OutputExtensionGlobal;
 class SurfaceExtensionGlobal;
 class SubSurfaceExtensionGlobal;
 class Shell;
+class TouchExtensionGlobal;
 
 class Q_COMPOSITOR_EXPORT Compositor : public QObject
 {
@@ -116,6 +117,9 @@ public:
     Qt::ScreenOrientation screenOrientation() const;
     void setOutputGeometry(const QRect &geometry);
 
+    void enableTouchExtension();
+    TouchExtensionGlobal *touchExtension() { return m_touchExtension; }
+
     bool isDragging() const;
     void sendDragMoveEvent(const QPoint &global, const QPoint &local, Surface *surface);
     void sendDragEndEvent();
@@ -173,6 +177,7 @@ private:
     OutputExtensionGlobal *m_outputExtension;
     SurfaceExtensionGlobal *m_surfaceExtension;
     SubSurfaceExtensionGlobal *m_subSurfaceExtension;
+    TouchExtensionGlobal *m_touchExtension;
 
     static void bind_func(struct wl_client *client, void *data,
                           uint32_t version, uint32_t id);
index dfd2c63..77cccf6 100644 (file)
@@ -44,7 +44,7 @@
 #include "wlcompositor.h"
 #include "wldatadevice.h"
 #include "wlsurface.h"
-
+#include "wltouch.h"
 #include "waylandcompositor.h"
 
 #include <QtGui/QTouchEvent>
@@ -169,13 +169,21 @@ void InputDevice::sendTouchCancelEvent()
 
 void InputDevice::sendFullTouchEvent(QTouchEvent *event)
 {
-    const QList<QTouchEvent::TouchPoint> points = event->touchPoints();
-    if (points.isEmpty())
-        return;
     if (!mouseFocus()) {
         qWarning("Cannot send touch event, no pointer focus, fix the compositor");
         return;
     }
+
+    TouchExtensionGlobal *ext = m_compositor->touchExtension();
+    if (ext) {
+        ext->postTouchEvent(event, mouseFocus());
+        return;
+    }
+
+    const QList<QTouchEvent::TouchPoint> points = event->touchPoints();
+    if (points.isEmpty())
+        return;
+
     const int pointCount = points.count();
     QPointF pos = mouseFocus()->pos();
     for (int i = 0; i < pointCount; ++i) {
diff --git a/src/compositor/wayland_wrapper/wltouch.cpp b/src/compositor/wayland_wrapper/wltouch.cpp
new file mode 100644 (file)
index 0000000..88044f1
--- /dev/null
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Compositor.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "wltouch.h"
+#include "wlsurface.h"
+#include <QTouchEvent>
+#include <QWindow>
+
+namespace Wayland {
+
+static void dummy(wl_client *, wl_resource *)
+{
+}
+
+const struct wl_touch_interface TouchExtensionGlobal::touch_interface = {
+    dummy
+};
+
+TouchExtensionGlobal::TouchExtensionGlobal(Compositor *compositor)
+    : m_compositor(compositor)
+{
+    wl_display_add_global(compositor->wl_display(),
+                          &wl_touch_interface,
+                          this,
+                          TouchExtensionGlobal::bind_func);
+}
+
+void TouchExtensionGlobal::destroy_resource(wl_resource *resource)
+{
+    TouchExtensionGlobal *self = static_cast<TouchExtensionGlobal *>(resource->data);
+    self->m_resources.removeOne(resource);
+    free(resource);
+}
+
+void TouchExtensionGlobal::bind_func(wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+    Q_UNUSED(version);
+    wl_resource *resource = wl_client_add_object(client, &wl_touch_interface, &touch_interface, id, data);
+    resource->destroy = destroy_resource;
+    TouchExtensionGlobal *self = static_cast<TouchExtensionGlobal *>(resource->data);
+    self->m_resources.append(resource);
+}
+
+static inline int toFixed(qreal f)
+{
+    return int(f * 10000);
+}
+
+void TouchExtensionGlobal::postTouchEvent(QTouchEvent *event, Surface *surface)
+{
+    const QList<QTouchEvent::TouchPoint> points = event->touchPoints();
+    const int pointCount = points.count();
+    if (!pointCount)
+        return;
+
+    QPointF surfacePos = surface->pos();
+    uint32_t time = m_compositor->currentTimeMsecs();
+    const int rescount = m_resources.count();
+    for (int res = 0; res < rescount; ++res) {
+        wl_resource *target = m_resources.at(res);
+
+        for (int i = 0; i < pointCount; ++i) {
+            const QTouchEvent::TouchPoint &tp(points.at(i));
+            uint32_t id = tp.id();
+            uint32_t state = tp.state();
+            uint32_t flags = tp.flags();
+            QPointF p = tp.pos() - surfacePos; // surface-relative
+            int x = toFixed(p.x());
+            int y = toFixed(p.y());
+            int nx = toFixed(tp.normalizedPos().x());
+            int ny = toFixed(tp.normalizedPos().y());
+            int w = toFixed(tp.rect().width());
+            int h = toFixed(tp.rect().height());
+            int vx = toFixed(tp.velocity().x());
+            int vy = toFixed(tp.velocity().y());
+            uint32_t pressure = uint32_t(tp.pressure() * 255);
+            wl_array *rawData = 0;
+            wl_resource_post_event(target, WL_TOUCH_TOUCH,
+                                   time, id, state,
+                                   x, y, nx, ny, w, h,
+                                   pressure, vx, vy,
+                                   flags, rawData);
+        }
+
+        wl_resource_post_event(target, WL_TOUCH_TOUCH_FRAME);
+    }
+}
+
+}
diff --git a/src/compositor/wayland_wrapper/wltouch.h b/src/compositor/wayland_wrapper/wltouch.h
new file mode 100644 (file)
index 0000000..4ed01f6
--- /dev/null
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** This file is part of QtCompositor**
+**
+** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+**
+** Contact:  Nokia Corporation qt-info@nokia.com
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**
+** Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+#ifndef WLTOUCH_H
+#define WLTOUCH_H
+
+#include "wlcompositor.h"
+#include "wayland-touch-extension-server-protocol.h"
+
+class Compositor;
+class Surface;
+class QTouchEvent;
+
+namespace Wayland {
+
+class TouchExtensionGlobal
+{
+public:
+    TouchExtensionGlobal(Compositor *compositor);
+
+    void postTouchEvent(QTouchEvent *event, Surface *surface);
+
+private:
+    Compositor *m_compositor;
+
+    static void bind_func(struct wl_client *client, void *data,
+                          uint32_t version, uint32_t id);
+
+    static void destroy_resource(wl_resource *resource);
+
+    static const struct wl_touch_interface touch_interface;
+
+    QList<wl_resource *> m_resources;
+};
+
+}
+
+#endif // WLTOUCH_H
index 944c412..d329690 100644 (file)
@@ -60,6 +60,7 @@
 #include "qwaylandextendedoutput.h"
 #include "qwaylandextendedsurface.h"
 #include "qwaylandsubsurface.h"
+#include "qwaylandtouch.h"
 
 #include <QtCore/QAbstractEventDispatcher>
 #include <QtGui/private/qguiapplication_p.h>
@@ -111,10 +112,11 @@ void QWaylandDisplay::setLastKeyboardFocusInputDevice(QWaylandInputDevice *devic
 static QWaylandDisplay *display = 0;
 
 QWaylandDisplay::QWaylandDisplay(void)
-    : mDndSelectionHandler(0)
-    , mLastKeyboardFocusInputDevice(0)
+    : mLastKeyboardFocusInputDevice(0)
+    , mDndSelectionHandler(0)
     , mWindowExtension(0)
     , mOutputExtension(0)
+    , mTouchExtension(0)
 {
     display = this;
     qRegisterMetaType<uint32_t>("uint32_t");
@@ -309,6 +311,8 @@ void QWaylandDisplay::displayHandleGlobal(uint32_t id,
         mWindowExtension = new QWaylandSurfaceExtension(this,id);
     } else if (interface == "wl_sub_surface_extension") {
         mSubSurfaceExtension = new QWaylandSubSurfaceExtension(this,id);
+    } else if (interface == "wl_touch") {
+        mTouchExtension = new QWaylandTouchExtension(this, id);
     }
 }
 
index 8b92b71..856e764 100644 (file)
@@ -62,6 +62,7 @@ class QWaylandShell;
 class QWaylandSurfaceExtension;
 class QWaylandSubSurfaceExtension;
 class QWaylandOutputExtension;
+class QWaylandTouchExtension;
 
 class QWaylandDisplay : public QObject {
     Q_OBJECT
@@ -100,6 +101,7 @@ public:
     QWaylandSurfaceExtension *windowExtension() const { return mWindowExtension; }
     QWaylandSubSurfaceExtension *subSurfaceExtension() const { return mSubSurfaceExtension; }
     QWaylandOutputExtension *outputExtension() const { return mOutputExtension; }
+    QWaylandTouchExtension *touchExtension() const { return mTouchExtension; }
 
     struct wl_shm *shm() const { return mShm; }
 
@@ -129,6 +131,7 @@ private:
     QWaylandSurfaceExtension *mWindowExtension;
     QWaylandSubSurfaceExtension *mSubSurfaceExtension;
     QWaylandOutputExtension *mOutputExtension;
+    QWaylandTouchExtension *mTouchExtension;
 
     QSocketNotifier *mReadNotifier;
     int mFd;
index 48aa291..9625cd8 100644 (file)
@@ -65,8 +65,9 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display,
     : mQDisplay(display)
     , mDisplay(display->wl_display())
     , mTransferDevice(0)
-    , mPointerFocus(NULL)
-    , mKeyboardFocus(NULL)
+    , mPointerFocus(0)
+    , mKeyboardFocus(0)
+    , mTouchFocus(0)
     , mButtons(0)
 {
     mInputDevice = static_cast<struct wl_input_device *>
index 313fa9f..f47194d 100644 (file)
@@ -131,6 +131,8 @@ private:
     QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
     QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints;
     QTouchDevice *mTouchDevice;
+
+    friend class QWaylandTouchExtension;
 };
 
 QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/qwaylandtouch.cpp b/src/plugins/platforms/wayland/qwaylandtouch.cpp
new file mode 100644 (file)
index 0000000..c1700e3
--- /dev/null
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandtouch.h"
+#include "qwaylandinputdevice.h"
+
+#include "wayland-touch-extension-client-protocol.h"
+
+QWaylandTouchExtension::QWaylandTouchExtension(QWaylandDisplay *display, uint32_t id)
+{
+    mDisplay = display;
+    mTouch = static_cast<struct wl_touch *>(wl_display_bind(display->wl_display(), id, &wl_touch_interface));
+    wl_touch_add_listener(mTouch, &touch_listener, this);
+
+    QTouchDevice::Capabilities caps = QTouchDevice::Position
+            | QTouchDevice::Area
+            | QTouchDevice::Pressure
+            | QTouchDevice::Velocity
+            | QTouchDevice::RawPositions
+            | QTouchDevice::NormalizedPosition;
+    mTouchDevice = new QTouchDevice;
+    mTouchDevice->setType(QTouchDevice::TouchScreen);
+    mTouchDevice->setCapabilities(caps);
+    QWindowSystemInterface::registerTouchDevice(mTouchDevice);
+}
+
+static inline qreal fromFixed(int f)
+{
+    return f / qreal(10000);
+}
+
+void QWaylandTouchExtension::handle_touch(void *data, wl_touch *wl_touch, uint32_t time,
+                                          uint32_t id, uint32_t state, int32_t x, int32_t y,
+                                          int32_t normalized_x, int32_t normalized_y,
+                                          int32_t width, int32_t height, uint32_t pressure,
+                                          int32_t velocity_x, int32_t velocity_y,
+                                          uint32_t flags, wl_array *rawdata)
+{
+    Q_UNUSED(wl_touch);
+    QWaylandTouchExtension *self = static_cast<QWaylandTouchExtension *>(data);
+    QList<QWaylandInputDevice *> inputDevices = self->mDisplay->inputDevices();
+    if (inputDevices.isEmpty()) {
+        qWarning("handle_touch: No input device");
+        return;
+    }
+    QWaylandInputDevice *dev = inputDevices.first();
+    QWaylandWindow *win = dev->mTouchFocus;
+    if (!win)
+        win = dev->mPointerFocus;
+    if (!win)
+        win = dev->mKeyboardFocus;
+    if (!win || !win->window())
+        return;
+
+    QWindowSystemInterface::TouchPoint tp;
+    tp.id = id;
+    tp.state = Qt::TouchPointState(int(state));
+    tp.flags = QTouchEvent::TouchPoint::InfoFlags(int(flags));
+
+    tp.area = QRectF(0, 0, fromFixed(width), fromFixed(height));
+    // Got surface-relative coords but need a (virtual) screen position.
+    QPointF relPos = QPointF(fromFixed(x), fromFixed(y));
+    QPointF delta = relPos - relPos.toPoint();
+    tp.area.moveCenter(win->window()->mapToGlobal(relPos.toPoint()) + delta);
+
+    tp.normalPosition.setX(fromFixed(normalized_x));
+    tp.normalPosition.setY(fromFixed(normalized_y));
+    tp.pressure = pressure / 255.0;
+    tp.velocity.setX(fromFixed(velocity_x));
+    tp.velocity.setY(fromFixed(velocity_y));
+
+    self->mTouchPoints.append(tp);
+    self->mTimestamp = time;
+}
+
+void QWaylandTouchExtension::handle_touch_frame(void *data, wl_touch *wl_touch)
+{
+    Q_UNUSED(wl_touch);
+    QWaylandTouchExtension *self = static_cast<QWaylandTouchExtension *>(data);
+    self->sendTouchEvent();
+}
+
+void QWaylandTouchExtension::sendTouchEvent()
+{
+    // Copy all points, that are in the previous but not in the current list, as stationary.
+    for (int i = 0; i < mPrevTouchPoints.count(); ++i) {
+        const QWindowSystemInterface::TouchPoint &prevPoint(mPrevTouchPoints.at(i));
+        if (prevPoint.state == Qt::TouchPointReleased)
+            continue;
+        bool found = false;
+        for (int j = 0; j < mTouchPoints.count(); ++j)
+            if (mTouchPoints.at(j).id == prevPoint.id) {
+                found = true;
+                break;
+            }
+        if (!found) {
+            QWindowSystemInterface::TouchPoint p = prevPoint;
+            p.state = Qt::TouchPointStationary;
+            mTouchPoints.append(p);
+        }
+    }
+
+    if (mTouchPoints.isEmpty()) {
+        mPrevTouchPoints.clear();
+        return;
+    }
+
+    QWindowSystemInterface::handleTouchEvent(0, mTimestamp, mTouchDevice, mTouchPoints);
+
+    bool allReleased = true;
+    for (int i = 0; i < mTouchPoints.count(); ++i)
+        if (mTouchPoints.at(i).state != Qt::TouchPointReleased) {
+            allReleased = false;
+            break;
+        }
+
+    mPrevTouchPoints = mTouchPoints;
+    mTouchPoints.clear();
+
+    if (allReleased)
+        mPrevTouchPoints.clear();
+}
+
+const struct wl_touch_listener QWaylandTouchExtension::touch_listener = {
+    QWaylandTouchExtension::handle_touch,
+    QWaylandTouchExtension::handle_touch_frame
+};
diff --git a/src/plugins/platforms/wayland/qwaylandtouch.h b/src/plugins/platforms/wayland/qwaylandtouch.h
new file mode 100644 (file)
index 0000000..541958a
--- /dev/null
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDTOUCh_H
+#define QWAYLANDTOUCH_H
+
+#include "qwaylanddisplay.h"
+#include <QWindowSystemInterface>
+
+class wl_touch;
+
+class QWaylandTouchExtension
+{
+public:
+    QWaylandTouchExtension(QWaylandDisplay *display, uint32_t id);
+
+private:
+    QWaylandDisplay *mDisplay;
+    wl_touch *mTouch;
+    static const struct wl_touch_listener touch_listener;
+
+    static void handle_touch(void *data,
+                             struct wl_touch *wl_touch,
+                             uint32_t time,
+                             uint32_t id,
+                             uint32_t state,
+                             int32_t x,
+                             int32_t y,
+                             int32_t normalized_x,
+                             int32_t normalized_y,
+                             int32_t width,
+                             int32_t height,
+                             uint32_t pressure,
+                             int32_t velocity_x,
+                             int32_t velocity_y,
+                             uint32_t flags,
+                             struct wl_array *rawdata);
+
+    static void handle_touch_frame(void *data,
+                                   struct wl_touch *wl_touch);
+
+    void sendTouchEvent();
+
+    QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
+    QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints;
+    QTouchDevice *mTouchDevice;
+    uint32_t mTimestamp;
+};
+
+#endif // QWAYLANDTOUCH_H
index 51ad95a..05fa21f 100644 (file)
@@ -18,7 +18,8 @@ QT += core-private gui-private platformsupport-private
 WAYLANDSOURCES += \
             $$PWD/../../../../extensions/surface-extension.xml \
             $$PWD/../../../../extensions/sub-surface-extension.xml \
-            $$PWD/../../../../extensions/output-extension.xml
+            $$PWD/../../../../extensions/output-extension.xml \
+            $$PWD/../../../../extensions/touch-extension.xml
 
 SOURCES =   main.cpp \
             qwaylandintegration.cpp \
@@ -39,7 +40,8 @@ SOURCES =   main.cpp \
             qwaylandshellsurface.cpp \
             qwaylandextendedoutput.cpp \
             qwaylandextendedsurface.cpp \
-            qwaylandsubsurface.cpp
+            qwaylandsubsurface.cpp \
+            qwaylandtouch.cpp
 
 HEADERS =   qwaylandintegration.h \
             qwaylandnativeinterface.h \
@@ -59,7 +61,8 @@ HEADERS =   qwaylandintegration.h \
             qwaylandshellsurface.h \
             qwaylandextendedoutput.h \
             qwaylandextendedsurface.h \
-            qwaylandsubsurface.h
+            qwaylandsubsurface.h \
+            qwaylandtouch.h
 
 INCLUDEPATH += $$QMAKE_INCDIR_WAYLAND
 LIBS += $$QMAKE_LIBS_WAYLAND