Implements touch support on QTWayland. Contributed by Thomas Perl.
authorGabriel Jacobo <gabomdq@gmail.com>
Fri, 27 Dec 2013 09:29:39 -0300
changeset 8082 5b83ad3f01ac
parent 8081 402b8c313246
child 8083 3782a12331d6
Implements touch support on QTWayland. Contributed by Thomas Perl.
configure
configure.in
include/SDL_config.h.in
src/video/wayland/SDL_waylandtouch.c
src/video/wayland/SDL_waylandtouch.h
src/video/wayland/SDL_waylandvideo.c
src/video/wayland/SDL_waylandvideo.h
src/video/wayland/SDL_waylandwindow.c
src/video/wayland/SDL_waylandwindow.h
--- a/configure	Wed Dec 25 17:02:15 2013 +0100
+++ b/configure	Fri Dec 27 09:29:39 2013 -0300
@@ -818,6 +818,7 @@
 enable_diskaudio
 enable_dummyaudio
 enable_video_wayland
+enable_video_wayland_qt_touch
 enable_video_x11
 with_x
 enable_x11_shared
@@ -1534,6 +1535,9 @@
   --enable-diskaudio      support the disk writer audio driver [[default=yes]]
   --enable-dummyaudio     support the dummy audio driver [[default=yes]]
   --enable-video-wayland  use Wayland video driver [[default=yes]]
+  --enable-video-wayland-qt-touch
+                          QtWayland server support for Wayland video driver
+                          [[default=yes]]
   --enable-video-x11      use X11 video driver [[default=yes]]
   --enable-x11-shared     dynamically load X11 support [[default=maybe]]
   --enable-video-x11-xcursor
@@ -18645,6 +18649,14 @@
 fi
 
 
+    # Check whether --enable-video-wayland-qt-touch was given.
+if test "${enable_video_wayland_qt_touch+set}" = set; then :
+  enableval=$enable_video_wayland_qt_touch;
+else
+  enable_video_wayland_qt_touch=yes
+fi
+
+
     if test x$enable_video = xyes -a x$enable_video_wayland = xyes; then
         # Extract the first word of "pkg-config", so it can be a program name with args.
 set dummy pkg-config; ac_word=$2
@@ -18704,6 +18716,11 @@
 
 $as_echo "#define SDL_VIDEO_DRIVER_WAYLAND 1" >>confdefs.h
 
+            if test x$enable_video_wayland_qt_touch = xyes; then
+
+$as_echo "#define SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1" >>confdefs.h
+
+            fi
             SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
             EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS"
                         EXTRA_LDFLAGS="$EXTRA_LDFLAGS $WAYLAND_LIBS"
--- a/configure.in	Wed Dec 25 17:02:15 2013 +0100
+++ b/configure.in	Fri Dec 27 09:29:39 2013 -0300
@@ -1122,6 +1122,10 @@
 AC_HELP_STRING([--enable-video-wayland], [use Wayland video driver [[default=yes]]]),
                   ,enable_video_wayland=yes)
 
+    AC_ARG_ENABLE(video-wayland-qt-touch,
+AC_HELP_STRING([--enable-video-wayland-qt-touch], [QtWayland server support for Wayland video driver [[default=yes]]]),
+                  ,enable_video_wayland_qt_touch=yes)
+
     if test x$enable_video = xyes -a x$enable_video_wayland = xyes; then
         AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
         AC_MSG_CHECKING(for Wayland support)
@@ -1137,6 +1141,9 @@
 
         if test x$video_wayland = xyes; then
             AC_DEFINE(SDL_VIDEO_DRIVER_WAYLAND, 1, [ ])
+            if test x$enable_video_wayland_qt_touch = xyes; then
+                AC_DEFINE(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH, 1, [ ])
+            fi
             SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
             EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS"
             dnl FIXME do dynamic loading code here.
--- a/include/SDL_config.h.in	Wed Dec 25 17:02:15 2013 +0100
+++ b/include/SDL_config.h.in	Fri Dec 27 09:29:39 2013 -0300
@@ -261,6 +261,7 @@
 #undef SDL_VIDEO_DRIVER_DUMMY
 #undef SDL_VIDEO_DRIVER_WINDOWS
 #undef SDL_VIDEO_DRIVER_WAYLAND
+#undef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
 #undef SDL_VIDEO_DRIVER_X11
 #undef SDL_VIDEO_DRIVER_RPI
 #undef SDL_VIDEO_DRIVER_X11_DYNAMIC
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/wayland/SDL_waylandtouch.c	Fri Dec 27 09:29:39 2013 -0300
@@ -0,0 +1,253 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* Contributed by Thomas Perl <thomas.perl@jollamobile.com> */
+
+#include "SDL_config.h"
+
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+
+#include "SDL_waylandtouch.h"
+#include "SDL_log.h"
+#include "../../events/SDL_touch_c.h"
+
+struct SDL_WaylandTouch {
+    struct qt_touch_extension *touch_extension;
+};
+
+
+/**
+ * Qt TouchPointState
+ * adapted from qtbase/src/corelib/global/qnamespace.h
+ **/
+enum QtWaylandTouchPointState {
+    QtWaylandTouchPointPressed    = 0x01,
+    QtWaylandTouchPointMoved      = 0x02,
+    /*
+    Never sent by the server:
+    QtWaylandTouchPointStationary = 0x04,
+    */
+    QtWaylandTouchPointReleased   = 0x08,
+};
+
+static void
+touch_handle_touch(void *data,
+        struct qt_touch_extension *qt_touch_extension,
+        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)
+{
+    /**
+     * Event is assembled in QtWayland in TouchExtensionGlobal::postTouchEvent
+     * (src/compositor/wayland_wrapper/qwltouch.cpp)
+     **/
+
+    float FIXED_TO_FLOAT = 1. / 10000.;
+    float xf = FIXED_TO_FLOAT * x;
+    float yf = FIXED_TO_FLOAT * y;
+
+    float PRESSURE_TO_FLOAT = 1. / 255.;
+    float pressuref = PRESSURE_TO_FLOAT * pressure;
+
+    uint32_t touchState = state & 0xFFFF;
+    /*
+    Other fields that are sent by the server (qwltouch.cpp),
+    but not used at the moment can be decoded in this way:
+
+    uint32_t sentPointCount = state >> 16;
+    uint32_t touchFlags = flags & 0xFFFF;
+    uint32_t capabilities = flags >> 16;
+    */
+
+    SDL_TouchID deviceId = 0;
+    if (!SDL_GetTouch(deviceId)) {
+        if (SDL_AddTouch(deviceId, "qt_touch_extension") < 0) {
+             SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__);
+        }
+    }
+
+    switch (touchState) {
+        case QtWaylandTouchPointPressed:
+        case QtWaylandTouchPointReleased:
+            SDL_SendTouch(deviceId, (SDL_FingerID)id,
+                    (touchState == QtWaylandTouchPointPressed) ? SDL_TRUE : SDL_FALSE,
+                    xf, yf, pressuref);
+            break;
+        case QtWaylandTouchPointMoved:
+            SDL_SendTouchMotion(deviceId, (SDL_FingerID)id, xf, yf, pressuref);
+            break;
+        default:
+            /* Should not happen */
+            break;
+    }
+}
+
+static void
+touch_handle_configure(void *data,
+        struct qt_touch_extension *qt_touch_extension,
+        uint32_t flags)
+{
+}
+
+/* wayland-qt-touch-extension.c BEGINS */
+
+static const struct qt_touch_extension_listener touch_listener = {
+    touch_handle_touch,
+    touch_handle_configure,
+};
+
+static const struct wl_interface *qt_touch_extension_types[] = {
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+};
+
+static const struct wl_message qt_touch_extension_requests[] = {
+    { "dummy", "", qt_touch_extension_types + 0 },
+};
+
+static const struct wl_message qt_touch_extension_events[] = {
+    { "touch", "uuuiiiiiiuiiua", qt_touch_extension_types + 0 },
+    { "configure", "u", qt_touch_extension_types + 0 },
+};
+
+WL_EXPORT const struct wl_interface qt_touch_extension_interface = {
+    "qt_touch_extension", 1,
+    1, qt_touch_extension_requests,
+    2, qt_touch_extension_events,
+};
+
+/* wayland-qt-touch-extension.c ENDS */
+
+/* wayland-qt-windowmanager.c BEGINS */
+static const struct wl_interface *qt_windowmanager_types[] = {
+    NULL,
+    NULL,
+};
+
+static const struct wl_message qt_windowmanager_requests[] = {
+    { "open_url", "us", qt_windowmanager_types + 0 },
+};
+
+static const struct wl_message qt_windowmanager_events[] = {
+    { "hints", "i", qt_windowmanager_types + 0 },
+    { "quit", "", qt_windowmanager_types + 0 },
+};
+
+WL_EXPORT const struct wl_interface qt_windowmanager_interface = {
+    "qt_windowmanager", 1,
+    1, qt_windowmanager_requests,
+    2, qt_windowmanager_events,
+};
+/* wayland-qt-windowmanager.c ENDS */
+
+/* wayland-qt-surface-extension.c BEGINS */
+extern const struct wl_interface qt_extended_surface_interface;
+extern const struct wl_interface wl_surface_interface;
+
+static const struct wl_interface *qt_surface_extension_types[] = {
+    NULL,
+    NULL,
+    &qt_extended_surface_interface,
+    &wl_surface_interface,
+};
+
+static const struct wl_message qt_surface_extension_requests[] = {
+    { "get_extended_surface", "no", qt_surface_extension_types + 2 },
+};
+
+WL_EXPORT const struct wl_interface qt_surface_extension_interface = {
+    "qt_surface_extension", 1,
+    1, qt_surface_extension_requests,
+    0, NULL,
+};
+
+static const struct wl_message qt_extended_surface_requests[] = {
+    { "update_generic_property", "sa", qt_surface_extension_types + 0 },
+    { "set_content_orientation", "i", qt_surface_extension_types + 0 },
+    { "set_window_flags", "i", qt_surface_extension_types + 0 },
+};
+
+static const struct wl_message qt_extended_surface_events[] = {
+    { "onscreen_visibility", "i", qt_surface_extension_types + 0 },
+    { "set_generic_property", "sa", qt_surface_extension_types + 0 },
+    { "close", "", qt_surface_extension_types + 0 },
+};
+
+WL_EXPORT const struct wl_interface qt_extended_surface_interface = {
+    "qt_extended_surface", 1,
+    3, qt_extended_surface_requests,
+    3, qt_extended_surface_events,
+};
+
+/* wayland-qt-surface-extension.c ENDS */
+
+void
+Wayland_touch_create(SDL_VideoData *data, uint32_t id)
+{
+    if (data->touch) {
+        Wayland_touch_destroy(data);
+    }
+
+    data->touch = malloc(sizeof(struct SDL_WaylandTouch));
+
+    struct SDL_WaylandTouch *touch = data->touch;
+    touch->touch_extension = wl_registry_bind(data->registry, id, &qt_touch_extension_interface, 1);
+    qt_touch_extension_add_listener(touch->touch_extension, &touch_listener, data);
+}
+
+void
+Wayland_touch_destroy(SDL_VideoData *data)
+{
+    if (data->touch) {
+        struct SDL_WaylandTouch *touch = data->touch;
+        if (touch->touch_extension) {
+            qt_touch_extension_destroy(touch->touch_extension);
+        }
+
+        free(data->touch);
+        data->touch = NULL;
+    }
+}
+
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/wayland/SDL_waylandtouch.h	Fri Dec 27 09:29:39 2013 -0300
@@ -0,0 +1,351 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_config.h"
+
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+
+#ifndef _SDL_waylandtouch_h
+#define _SDL_waylandtouch_h
+
+#include "SDL_waylandvideo.h"
+#include <stdint.h>
+#include <stddef.h>
+#include "wayland-client.h"
+#include "wayland-util.h"
+
+void Wayland_touch_create(SDL_VideoData *data, uint32_t id);
+void Wayland_touch_destroy(SDL_VideoData *data);
+
+struct qt_touch_extension;
+
+/* Autogenerated QT headers */
+
+/*
+ Support for Wayland with QmlCompositor as Server
+================================================
+
+The Wayland video driver has support for some additional features when
+using QtWayland's "qmlcompositor" as Wayland server. This is needed for touch
+input when running SDL applications under a qmlcompositor Wayland server.
+
+The files following headers have been
+generated from the Wayland XML Protocol Definition in QtWayland as follows:
+
+Clone QtWayland from Git:
+    http://qt.gitorious.org/qt/qtwayland/
+
+Generate headers and glue code:
+    for extension in touch-extension surface-extension windowmanager; do
+        wayland-scanner client-header < src/extensions/$extension.xml > wayland-qt-$extension.h
+        wayland-scanner code < src/extensions/$extension.xml > wayland-qt-$extension.c
+    done
+
+*/
+
+/* wayland-qt-surface-extension.h */
+
+struct wl_client;
+struct wl_resource;
+
+struct qt_surface_extension;
+struct qt_extended_surface;
+
+extern const struct wl_interface qt_surface_extension_interface;
+extern const struct wl_interface qt_extended_surface_interface;
+
+#define QT_SURFACE_EXTENSION_GET_EXTENDED_SURFACE   0
+
+static inline void
+qt_surface_extension_set_user_data(struct qt_surface_extension *qt_surface_extension, void *user_data)
+{
+    wl_proxy_set_user_data((struct wl_proxy *) qt_surface_extension, user_data);
+}
+
+static inline void *
+qt_surface_extension_get_user_data(struct qt_surface_extension *qt_surface_extension)
+{
+    return wl_proxy_get_user_data((struct wl_proxy *) qt_surface_extension);
+}
+
+static inline void
+qt_surface_extension_destroy(struct qt_surface_extension *qt_surface_extension)
+{
+    wl_proxy_destroy((struct wl_proxy *) qt_surface_extension);
+}
+
+static inline struct qt_extended_surface *
+qt_surface_extension_get_extended_surface(struct qt_surface_extension *qt_surface_extension, struct wl_surface *surface)
+{
+    struct wl_proxy *id;
+
+    id = wl_proxy_create((struct wl_proxy *) qt_surface_extension,
+                 &qt_extended_surface_interface);
+    if (!id)
+        return NULL;
+
+    wl_proxy_marshal((struct wl_proxy *) qt_surface_extension,
+             QT_SURFACE_EXTENSION_GET_EXTENDED_SURFACE, id, surface);
+
+    return (struct qt_extended_surface *) id;
+}
+
+#ifndef QT_EXTENDED_SURFACE_ORIENTATION_ENUM
+#define QT_EXTENDED_SURFACE_ORIENTATION_ENUM
+enum qt_extended_surface_orientation {
+    QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION = 0,
+    QT_EXTENDED_SURFACE_ORIENTATION_PORTRAITORIENTATION = 1,
+    QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION = 2,
+    QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION = 4,
+    QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION = 8,
+};
+#endif /* QT_EXTENDED_SURFACE_ORIENTATION_ENUM */
+
+#ifndef QT_EXTENDED_SURFACE_WINDOWFLAG_ENUM
+#define QT_EXTENDED_SURFACE_WINDOWFLAG_ENUM
+enum qt_extended_surface_windowflag {
+    QT_EXTENDED_SURFACE_WINDOWFLAG_OVERRIDESSYSTEMGESTURES = 1,
+    QT_EXTENDED_SURFACE_WINDOWFLAG_STAYSONTOP = 2,
+};
+#endif /* QT_EXTENDED_SURFACE_WINDOWFLAG_ENUM */
+
+struct qt_extended_surface_listener {
+    /**
+     * onscreen_visibility - (none)
+     * @visible: (none)
+     */
+    void (*onscreen_visibility)(void *data,
+                    struct qt_extended_surface *qt_extended_surface,
+                    int32_t visible);
+    /**
+     * set_generic_property - (none)
+     * @name: (none)
+     * @value: (none)
+     */
+    void (*set_generic_property)(void *data,
+                     struct qt_extended_surface *qt_extended_surface,
+                     const char *name,
+                     struct wl_array *value);
+    /**
+     * close - (none)
+     */
+    void (*close)(void *data,
+              struct qt_extended_surface *qt_extended_surface);
+};
+
+static inline int
+qt_extended_surface_add_listener(struct qt_extended_surface *qt_extended_surface,
+                 const struct qt_extended_surface_listener *listener, void *data)
+{
+    return wl_proxy_add_listener((struct wl_proxy *) qt_extended_surface,
+                     (void (**)(void)) listener, data);
+}
+
+#define QT_EXTENDED_SURFACE_UPDATE_GENERIC_PROPERTY 0
+#define QT_EXTENDED_SURFACE_SET_CONTENT_ORIENTATION 1
+#define QT_EXTENDED_SURFACE_SET_WINDOW_FLAGS    2
+
+static inline void
+qt_extended_surface_set_user_data(struct qt_extended_surface *qt_extended_surface, void *user_data)
+{
+    wl_proxy_set_user_data((struct wl_proxy *) qt_extended_surface, user_data);
+}
+
+static inline void *
+qt_extended_surface_get_user_data(struct qt_extended_surface *qt_extended_surface)
+{
+    return wl_proxy_get_user_data((struct wl_proxy *) qt_extended_surface);
+}
+
+static inline void
+qt_extended_surface_destroy(struct qt_extended_surface *qt_extended_surface)
+{
+    wl_proxy_destroy((struct wl_proxy *) qt_extended_surface);
+}
+
+static inline void
+qt_extended_surface_update_generic_property(struct qt_extended_surface *qt_extended_surface, const char *name, struct wl_array *value)
+{
+    wl_proxy_marshal((struct wl_proxy *) qt_extended_surface,
+             QT_EXTENDED_SURFACE_UPDATE_GENERIC_PROPERTY, name, value);
+}
+
+static inline void
+qt_extended_surface_set_content_orientation(struct qt_extended_surface *qt_extended_surface, int32_t orientation)
+{
+    wl_proxy_marshal((struct wl_proxy *) qt_extended_surface,
+             QT_EXTENDED_SURFACE_SET_CONTENT_ORIENTATION, orientation);
+}
+
+static inline void
+qt_extended_surface_set_window_flags(struct qt_extended_surface *qt_extended_surface, int32_t flags)
+{
+    wl_proxy_marshal((struct wl_proxy *) qt_extended_surface,
+             QT_EXTENDED_SURFACE_SET_WINDOW_FLAGS, flags);
+}
+
+/* wayland-qt-touch-extension.h */
+
+extern const struct wl_interface qt_touch_extension_interface;
+
+#ifndef QT_TOUCH_EXTENSION_FLAGS_ENUM
+#define QT_TOUCH_EXTENSION_FLAGS_ENUM
+enum qt_touch_extension_flags {
+    QT_TOUCH_EXTENSION_FLAGS_MOUSE_FROM_TOUCH = 0x1,
+};
+#endif /* QT_TOUCH_EXTENSION_FLAGS_ENUM */
+
+struct qt_touch_extension_listener {
+    /**
+     * touch - (none)
+     * @time: (none)
+     * @id: (none)
+     * @state: (none)
+     * @x: (none)
+     * @y: (none)
+     * @normalized_x: (none)
+     * @normalized_y: (none)
+     * @width: (none)
+     * @height: (none)
+     * @pressure: (none)
+     * @velocity_x: (none)
+     * @velocity_y: (none)
+     * @flags: (none)
+     * @rawdata: (none)
+     */
+    void (*touch)(void *data,
+              struct qt_touch_extension *qt_touch_extension,
+              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);
+    /**
+     * configure - (none)
+     * @flags: (none)
+     */
+    void (*configure)(void *data,
+              struct qt_touch_extension *qt_touch_extension,
+              uint32_t flags);
+};
+
+static inline int
+qt_touch_extension_add_listener(struct qt_touch_extension *qt_touch_extension,
+                const struct qt_touch_extension_listener *listener, void *data)
+{
+    return wl_proxy_add_listener((struct wl_proxy *) qt_touch_extension,
+                     (void (**)(void)) listener, data);
+}
+
+#define QT_TOUCH_EXTENSION_DUMMY    0
+
+static inline void
+qt_touch_extension_set_user_data(struct qt_touch_extension *qt_touch_extension, void *user_data)
+{
+    wl_proxy_set_user_data((struct wl_proxy *) qt_touch_extension, user_data);
+}
+
+static inline void *
+qt_touch_extension_get_user_data(struct qt_touch_extension *qt_touch_extension)
+{
+    return wl_proxy_get_user_data((struct wl_proxy *) qt_touch_extension);
+}
+
+static inline void
+qt_touch_extension_destroy(struct qt_touch_extension *qt_touch_extension)
+{
+    wl_proxy_destroy((struct wl_proxy *) qt_touch_extension);
+}
+
+static inline void
+qt_touch_extension_dummy(struct qt_touch_extension *qt_touch_extension)
+{
+    wl_proxy_marshal((struct wl_proxy *) qt_touch_extension,
+             QT_TOUCH_EXTENSION_DUMMY);
+}
+
+
+/* wayland-qt-windowmanager.h */
+
+extern const struct wl_interface qt_windowmanager_interface;
+
+struct qt_windowmanager_listener {
+    /**
+     * hints - (none)
+     * @show_is_fullscreen: (none)
+     */
+    void (*hints)(void *data,
+              struct qt_windowmanager *qt_windowmanager,
+              int32_t show_is_fullscreen);
+    /**
+     * quit - (none)
+     */
+    void (*quit)(void *data,
+             struct qt_windowmanager *qt_windowmanager);
+};
+
+static inline int
+qt_windowmanager_add_listener(struct qt_windowmanager *qt_windowmanager,
+                  const struct qt_windowmanager_listener *listener, void *data)
+{
+    return wl_proxy_add_listener((struct wl_proxy *) qt_windowmanager,
+                     (void (**)(void)) listener, data);
+}
+
+#define QT_WINDOWMANAGER_OPEN_URL   0
+
+static inline void
+qt_windowmanager_set_user_data(struct qt_windowmanager *qt_windowmanager, void *user_data)
+{
+    wl_proxy_set_user_data((struct wl_proxy *) qt_windowmanager, user_data);
+}
+
+static inline void *
+qt_windowmanager_get_user_data(struct qt_windowmanager *qt_windowmanager)
+{
+    return wl_proxy_get_user_data((struct wl_proxy *) qt_windowmanager);
+}
+
+static inline void
+qt_windowmanager_destroy(struct qt_windowmanager *qt_windowmanager)
+{
+    wl_proxy_destroy((struct wl_proxy *) qt_windowmanager);
+}
+
+static inline void
+qt_windowmanager_open_url(struct qt_windowmanager *qt_windowmanager, uint32_t remaining, const char *url)
+{
+    wl_proxy_marshal((struct wl_proxy *) qt_windowmanager,
+             QT_WINDOWMANAGER_OPEN_URL, remaining, url);
+}
+
+#endif /* _SDL_waylandtouch_h */
+
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
--- a/src/video/wayland/SDL_waylandvideo.c	Wed Dec 25 17:02:15 2013 +0100
+++ b/src/video/wayland/SDL_waylandvideo.c	Fri Dec 27 09:29:39 2013 -0300
@@ -30,6 +30,7 @@
 #include "SDL_waylandwindow.h"
 #include "SDL_waylandopengles.h"
 #include "SDL_waylandmouse.h"
+#include "SDL_waylandtouch.h"
 
 #include <fcntl.h>
 #include <xkbcommon/xkbcommon.h>
@@ -202,6 +203,25 @@
     shm_handle_format
 };
 
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+static void
+windowmanager_hints(void *data, struct qt_windowmanager *qt_windowmanager,
+        int32_t show_is_fullscreen)
+{
+}
+
+static void
+windowmanager_quit(void *data, struct qt_windowmanager *qt_windowmanager)
+{
+    SDL_SendQuit();
+}
+
+static const struct qt_windowmanager_listener windowmanager_listener = {
+    windowmanager_hints,
+    windowmanager_quit,
+};
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
+
 static void
 display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
 					const char *interface, uint32_t version)
@@ -222,6 +242,18 @@
         d->cursor_theme = wl_cursor_theme_load(NULL, 32, d->shm);
         d->default_cursor = wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
         wl_shm_add_listener(d->shm, &shm_listener, d);
+    
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+    } else if (strcmp(interface, "qt_touch_extension") == 0) {
+        Wayland_touch_create(d, id);
+    } else if (strcmp(interface, "qt_surface_extension") == 0) {
+        d->surface_extension = wl_registry_bind(registry, id,
+                &qt_surface_extension_interface, 1);
+    } else if (strcmp(interface, "qt_windowmanager") == 0) {
+        d->windowmanager = wl_registry_bind(registry, id,
+                &qt_windowmanager_interface, 1);
+        qt_windowmanager_add_listener(d->windowmanager, &windowmanager_listener, d);
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
     }
 }
 
@@ -334,6 +366,15 @@
         xkb_context_unref(data->xkb_context);
         data->xkb_context = NULL;
     }
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+    if (data->windowmanager)
+        qt_windowmanager_destroy(data->windowmanager);
+
+    if (data->surface_extension)
+        qt_surface_extension_destroy(data->surface_extension);
+
+    Wayland_touch_destroy(data);
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
 
     if (data->shm)
         wl_shm_destroy(data->shm);
--- a/src/video/wayland/SDL_waylandvideo.h	Wed Dec 25 17:02:15 2013 +0100
+++ b/src/video/wayland/SDL_waylandvideo.h	Fri Dec 27 09:29:39 2013 -0300
@@ -33,6 +33,12 @@
 struct xkb_context;
 struct SDL_WaylandInput;
 
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+struct SDL_WaylandTouch;
+struct qt_surface_extension;
+struct qt_windowmanager;
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
+
 typedef struct {
     struct wl_display *display;
     struct wl_registry *registry;
@@ -56,6 +62,12 @@
 
     struct xkb_context *xkb_context;
     struct SDL_WaylandInput *input;
+    
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH    
+    struct SDL_WaylandTouch *touch;
+    struct qt_surface_extension *surface_extension;
+    struct qt_windowmanager *windowmanager;
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
 
     uint32_t shm_formats;
 } SDL_VideoData;
--- a/src/video/wayland/SDL_waylandwindow.c	Wed Dec 25 17:02:15 2013 +0100
+++ b/src/video/wayland/SDL_waylandwindow.c	Fri Dec 27 09:29:39 2013 -0300
@@ -26,6 +26,7 @@
 #include "../SDL_egl_c.h"
 #include "SDL_waylandwindow.h"
 #include "SDL_waylandvideo.h"
+#include "SDL_waylandtouch.h"
 
 static void
 handle_ping(void *data, struct wl_shell_surface *shell_surface,
@@ -51,6 +52,34 @@
     handle_popup_done
 };
 
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+static void
+handle_onscreen_visibility(void *data,
+        struct qt_extended_surface *qt_extended_surface, int32_t visible)
+{
+}
+
+static void
+handle_set_generic_property(void *data,
+        struct qt_extended_surface *qt_extended_surface, const char *name,
+        struct wl_array *value)
+{
+}
+
+static void
+handle_close(void *data, struct qt_extended_surface *qt_extended_surface)
+{
+    SDL_WindowData *window = (SDL_WindowData *)data;
+    SDL_SendWindowEvent(window->sdlwindow, SDL_WINDOWEVENT_CLOSE, 0, 0);
+}
+
+static const struct qt_extended_surface_listener extended_surface_listener = {
+    handle_onscreen_visibility,
+    handle_set_generic_property,
+    handle_close,
+};
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
+
 SDL_bool
 Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
 {
@@ -127,6 +156,12 @@
     wl_surface_set_user_data(data->surface, data);
     data->shell_surface = wl_shell_get_shell_surface(c->shell,
                                                      data->surface);
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH    
+    if (c->surface_extension) {
+        data->extended_surface = qt_surface_extension_get_extended_surface(
+                c->surface_extension, data->surface);
+    }
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
     data->egl_window = wl_egl_window_create(data->surface,
                                             window->w, window->h);
 
@@ -144,6 +179,14 @@
                                       &shell_surface_listener, data);
     }
 
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+    if (data->extended_surface) {
+        qt_extended_surface_set_user_data(data->extended_surface, data);
+        qt_extended_surface_add_listener(data->extended_surface,
+                                         &extended_surface_listener, data);
+    }
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
+
     region = wl_compositor_create_region(c->compositor);
     wl_region_add(region, 0, 0, window->w, window->h);
     wl_surface_set_opaque_region(data->surface, region);
@@ -182,6 +225,10 @@
         if (wind->shell_surface)
             wl_shell_surface_destroy(wind->shell_surface);
 
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+        if (wind->extended_surface)
+            qt_extended_surface_destroy(wind->extended_surface);
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
         wl_surface_destroy(wind->surface);
 
         SDL_free(wind);
--- a/src/video/wayland/SDL_waylandwindow.h	Wed Dec 25 17:02:15 2013 +0100
+++ b/src/video/wayland/SDL_waylandwindow.h	Fri Dec 27 09:29:39 2013 -0300
@@ -38,8 +38,11 @@
     struct wl_shell_surface *shell_surface;
     struct wl_egl_window *egl_window;
     struct SDL_WaylandInput *keyboard_device;
+    EGLSurface egl_surface;
 
-    EGLSurface egl_surface;
+#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
+    struct qt_extended_surface *extended_surface;
+#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */    
 } SDL_WindowData;
 
 extern void Wayland_ShowWindow(_THIS, SDL_Window *window);