src/video/wayland/SDL_waylandtouch.c
author Alex Szpakowski
Sun, 04 Aug 2019 16:56:40 -0300
changeset 12996 b4a7e94357f2
parent 12979 bbbb30026158
child 13201 c88f111dc41f
permissions -rw-r--r--
Fix touch-related compile errors on Linux.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 /* Contributed by Thomas Perl <thomas.perl@jollamobile.com> */
    23 
    24 #include "../../SDL_internal.h"
    25 
    26 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
    27 
    28 #include "SDL_log.h"
    29 #include "SDL_mouse.h"
    30 #include "SDL_keyboard.h"
    31 #include "SDL_waylandtouch.h"
    32 #include "../../events/SDL_touch_c.h"
    33 
    34 struct SDL_WaylandTouch {
    35     struct qt_touch_extension *touch_extension;
    36 };
    37 
    38 
    39 /**
    40  * Qt TouchPointState
    41  * adapted from qtbase/src/corelib/global/qnamespace.h
    42  **/
    43 enum QtWaylandTouchPointState {
    44     QtWaylandTouchPointPressed    = 0x01,
    45     QtWaylandTouchPointMoved      = 0x02,
    46     /*
    47     Never sent by the server:
    48     QtWaylandTouchPointStationary = 0x04,
    49     */
    50     QtWaylandTouchPointReleased   = 0x08,
    51 };
    52 
    53 static void
    54 touch_handle_touch(void *data,
    55         struct qt_touch_extension *qt_touch_extension,
    56         uint32_t time,
    57         uint32_t id,
    58         uint32_t state,
    59         int32_t x,
    60         int32_t y,
    61         int32_t normalized_x,
    62         int32_t normalized_y,
    63         int32_t width,
    64         int32_t height,
    65         uint32_t pressure,
    66         int32_t velocity_x,
    67         int32_t velocity_y,
    68         uint32_t flags,
    69         struct wl_array *rawdata)
    70 {
    71     /**
    72      * Event is assembled in QtWayland in TouchExtensionGlobal::postTouchEvent
    73      * (src/compositor/wayland_wrapper/qwltouch.cpp)
    74      **/
    75 
    76     float FIXED_TO_FLOAT = 1. / 10000.;
    77     float xf = FIXED_TO_FLOAT * x;
    78     float yf = FIXED_TO_FLOAT * y;
    79 
    80     float PRESSURE_TO_FLOAT = 1. / 255.;
    81     float pressuref = PRESSURE_TO_FLOAT * pressure;
    82 
    83     uint32_t touchState = state & 0xFFFF;
    84     /*
    85     Other fields that are sent by the server (qwltouch.cpp),
    86     but not used at the moment can be decoded in this way:
    87 
    88     uint32_t sentPointCount = state >> 16;
    89     uint32_t touchFlags = flags & 0xFFFF;
    90     uint32_t capabilities = flags >> 16;
    91     */
    92 
    93     SDL_Window* window = NULL;
    94 
    95     SDL_TouchID deviceId = 1;
    96     if (SDL_AddTouch(deviceId, SDL_TOUCH_DEVICE_DIRECT, "qt_touch_extension") < 0) {
    97          SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__);
    98     }
    99 
   100     /* FIXME: This should be the window the given wayland surface is associated
   101      * with, but how do we get the wayland surface? */
   102     window = SDL_GetMouseFocus();
   103     if (window == NULL) {
   104         window = SDL_GetKeyboardFocus();
   105     }
   106 
   107     switch (touchState) {
   108         case QtWaylandTouchPointPressed:
   109         case QtWaylandTouchPointReleased:
   110             SDL_SendTouch(deviceId, (SDL_FingerID)id, window,
   111                     (touchState == QtWaylandTouchPointPressed) ? SDL_TRUE : SDL_FALSE,
   112                     xf, yf, pressuref);
   113             break;
   114         case QtWaylandTouchPointMoved:
   115             SDL_SendTouchMotion(deviceId, (SDL_FingerID)id, window, xf, yf, pressuref);
   116             break;
   117         default:
   118             /* Should not happen */
   119             break;
   120     }
   121 }
   122 
   123 static void
   124 touch_handle_configure(void *data,
   125         struct qt_touch_extension *qt_touch_extension,
   126         uint32_t flags)
   127 {
   128 }
   129 
   130 
   131 /* wayland-qt-touch-extension.c BEGINS */
   132 
   133 static const struct qt_touch_extension_listener touch_listener = {
   134     touch_handle_touch,
   135     touch_handle_configure,
   136 };
   137 
   138 static const struct wl_interface *qt_touch_extension_types[] = {
   139     NULL,
   140     NULL,
   141     NULL,
   142     NULL,
   143     NULL,
   144     NULL,
   145     NULL,
   146     NULL,
   147     NULL,
   148     NULL,
   149     NULL,
   150     NULL,
   151     NULL,
   152     NULL,
   153 };
   154 
   155 static const struct wl_message qt_touch_extension_requests[] = {
   156     { "dummy", "", qt_touch_extension_types + 0 },
   157 };
   158 
   159 static const struct wl_message qt_touch_extension_events[] = {
   160     { "touch", "uuuiiiiiiuiiua", qt_touch_extension_types + 0 },
   161     { "configure", "u", qt_touch_extension_types + 0 },
   162 };
   163 
   164 WL_EXPORT const struct wl_interface qt_touch_extension_interface = {
   165     "qt_touch_extension", 1,
   166     1, qt_touch_extension_requests,
   167     2, qt_touch_extension_events,
   168 };
   169 
   170 /* wayland-qt-touch-extension.c ENDS */
   171 
   172 /* wayland-qt-windowmanager.c BEGINS */
   173 static const struct wl_interface *qt_windowmanager_types[] = {
   174     NULL,
   175     NULL,
   176 };
   177 
   178 static const struct wl_message qt_windowmanager_requests[] = {
   179     { "open_url", "us", qt_windowmanager_types + 0 },
   180 };
   181 
   182 static const struct wl_message qt_windowmanager_events[] = {
   183     { "hints", "i", qt_windowmanager_types + 0 },
   184     { "quit", "", qt_windowmanager_types + 0 },
   185 };
   186 
   187 WL_EXPORT const struct wl_interface qt_windowmanager_interface = {
   188     "qt_windowmanager", 1,
   189     1, qt_windowmanager_requests,
   190     2, qt_windowmanager_events,
   191 };
   192 /* wayland-qt-windowmanager.c ENDS */
   193 
   194 /* wayland-qt-surface-extension.c BEGINS */
   195 extern const struct wl_interface qt_extended_surface_interface;
   196 #ifndef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
   197 extern const struct wl_interface wl_surface_interface;
   198 #endif
   199 
   200 static const struct wl_interface *qt_surface_extension_types[] = {
   201     NULL,
   202     NULL,
   203     &qt_extended_surface_interface,
   204 #ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
   205     /* FIXME: Set this dynamically to (*WAYLAND_wl_surface_interface) ? 
   206      * The value comes from auto generated code and does 
   207      * not appear to actually be used anywhere
   208      */
   209     NULL, 
   210 #else
   211     &wl_surface_interface,
   212 #endif    
   213 };
   214 
   215 static const struct wl_message qt_surface_extension_requests[] = {
   216     { "get_extended_surface", "no", qt_surface_extension_types + 2 },
   217 };
   218 
   219 WL_EXPORT const struct wl_interface qt_surface_extension_interface = {
   220     "qt_surface_extension", 1,
   221     1, qt_surface_extension_requests,
   222     0, NULL,
   223 };
   224 
   225 static const struct wl_message qt_extended_surface_requests[] = {
   226     { "update_generic_property", "sa", qt_surface_extension_types + 0 },
   227     { "set_content_orientation", "i", qt_surface_extension_types + 0 },
   228     { "set_window_flags", "i", qt_surface_extension_types + 0 },
   229 };
   230 
   231 static const struct wl_message qt_extended_surface_events[] = {
   232     { "onscreen_visibility", "i", qt_surface_extension_types + 0 },
   233     { "set_generic_property", "sa", qt_surface_extension_types + 0 },
   234     { "close", "", qt_surface_extension_types + 0 },
   235 };
   236 
   237 WL_EXPORT const struct wl_interface qt_extended_surface_interface = {
   238     "qt_extended_surface", 1,
   239     3, qt_extended_surface_requests,
   240     3, qt_extended_surface_events,
   241 };
   242 
   243 /* wayland-qt-surface-extension.c ENDS */
   244 
   245 void
   246 Wayland_touch_create(SDL_VideoData *data, uint32_t id)
   247 {
   248     struct SDL_WaylandTouch *touch;
   249 
   250     if (data->touch) {
   251         Wayland_touch_destroy(data);
   252     }
   253 
   254     /* !!! FIXME: check for failure, call SDL_OutOfMemory() */
   255     data->touch = SDL_malloc(sizeof(struct SDL_WaylandTouch));
   256 
   257     touch = data->touch;
   258     touch->touch_extension = wl_registry_bind(data->registry, id, &qt_touch_extension_interface, 1);
   259     qt_touch_extension_add_listener(touch->touch_extension, &touch_listener, data);
   260 }
   261 
   262 void
   263 Wayland_touch_destroy(SDL_VideoData *data)
   264 {
   265     if (data->touch) {
   266         struct SDL_WaylandTouch *touch = data->touch;
   267         if (touch->touch_extension) {
   268             qt_touch_extension_destroy(touch->touch_extension);
   269         }
   270 
   271         SDL_free(data->touch);
   272         data->touch = NULL;
   273     }
   274 }
   275 
   276 #endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */