src/events/SDL_touch.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 21 May 2019 17:33:31 -0700
changeset 12747 cdf53e16feb7
parent 12701 3477a301a5a8
permissions -rw-r--r--
Fixed bug 4639 - CMake build does not generate libhidapi.so for Android

Manuel Sabogal

I noticed that the current Android.mk builds a libhidapi.so library for Android but the CMake build hasn't been updated to do so. I'll attach a patch that fixes this issue.
     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 #include "../SDL_internal.h"
    22 
    23 /* General touch handling code for SDL */
    24 
    25 #include "SDL_assert.h"
    26 #include "SDL_events.h"
    27 #include "SDL_events_c.h"
    28 #include "../video/SDL_sysvideo.h"
    29 
    30 
    31 static int SDL_num_touch = 0;
    32 static SDL_Touch **SDL_touchDevices = NULL;
    33 
    34 /* for mapping touch events to mice */
    35 static SDL_bool finger_touching = SDL_FALSE;
    36 static SDL_FingerID track_fingerid;
    37 static SDL_TouchID  track_touchid;
    38 
    39 /* Public functions */
    40 int
    41 SDL_TouchInit(void)
    42 {
    43     return (0);
    44 }
    45 
    46 int
    47 SDL_GetNumTouchDevices(void)
    48 {
    49     return SDL_num_touch;
    50 }
    51 
    52 SDL_TouchID
    53 SDL_GetTouchDevice(int index)
    54 {
    55     if (index < 0 || index >= SDL_num_touch) {
    56         SDL_SetError("Unknown touch device index %d", index);
    57         return 0;
    58     }
    59     return SDL_touchDevices[index]->id;
    60 }
    61 
    62 static int
    63 SDL_GetTouchIndex(SDL_TouchID id)
    64 {
    65     int index;
    66     SDL_Touch *touch;
    67 
    68     for (index = 0; index < SDL_num_touch; ++index) {
    69         touch = SDL_touchDevices[index];
    70         if (touch->id == id) {
    71             return index;
    72         }
    73     }
    74     return -1;
    75 }
    76 
    77 SDL_Touch *
    78 SDL_GetTouch(SDL_TouchID id)
    79 {
    80     int index = SDL_GetTouchIndex(id);
    81     if (index < 0 || index >= SDL_num_touch) {
    82         if (SDL_GetVideoDevice()->ResetTouch != NULL) {
    83             SDL_SetError("Unknown touch id %d, resetting", (int) id);
    84             (SDL_GetVideoDevice()->ResetTouch)(SDL_GetVideoDevice());
    85         } else {
    86             SDL_SetError("Unknown touch device id %d, cannot reset", (int) id);
    87         }
    88         return NULL;
    89     }
    90     return SDL_touchDevices[index];
    91 }
    92 
    93 SDL_TouchDeviceType
    94 SDL_GetTouchDeviceType(SDL_TouchID id)
    95 {
    96     SDL_Touch *touch = SDL_GetTouch(id);
    97     if (touch) {
    98         return touch->type;
    99     }
   100     return SDL_TOUCH_DEVICE_INVALID;
   101 }
   102 
   103 static int
   104 SDL_GetFingerIndex(const SDL_Touch * touch, SDL_FingerID fingerid)
   105 {
   106     int index;
   107     for (index = 0; index < touch->num_fingers; ++index) {
   108         if (touch->fingers[index]->id == fingerid) {
   109             return index;
   110         }
   111     }
   112     return -1;
   113 }
   114 
   115 static SDL_Finger *
   116 SDL_GetFinger(const SDL_Touch * touch, SDL_FingerID id)
   117 {
   118     int index = SDL_GetFingerIndex(touch, id);
   119     if (index < 0 || index >= touch->num_fingers) {
   120         return NULL;
   121     }
   122     return touch->fingers[index];
   123 }
   124 
   125 int
   126 SDL_GetNumTouchFingers(SDL_TouchID touchID)
   127 {
   128     SDL_Touch *touch = SDL_GetTouch(touchID);
   129     if (touch) {
   130         return touch->num_fingers;
   131     }
   132     return 0;
   133 }
   134 
   135 SDL_Finger *
   136 SDL_GetTouchFinger(SDL_TouchID touchID, int index)
   137 {
   138     SDL_Touch *touch = SDL_GetTouch(touchID);
   139     if (!touch) {
   140         return NULL;
   141     }
   142     if (index < 0 || index >= touch->num_fingers) {
   143         SDL_SetError("Unknown touch finger");
   144         return NULL;
   145     }
   146     return touch->fingers[index];
   147 }
   148 
   149 int
   150 SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
   151 {
   152     SDL_Touch **touchDevices;
   153     int index;
   154 
   155     index = SDL_GetTouchIndex(touchID);
   156     if (index >= 0) {
   157         return index;
   158     }
   159 
   160     /* Add the touch to the list of touch */
   161     touchDevices = (SDL_Touch **) SDL_realloc(SDL_touchDevices,
   162                                       (SDL_num_touch + 1) * sizeof(*touchDevices));
   163     if (!touchDevices) {
   164         return SDL_OutOfMemory();
   165     }
   166 
   167     SDL_touchDevices = touchDevices;
   168     index = SDL_num_touch;
   169 
   170     SDL_touchDevices[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touchDevices[index]));
   171     if (!SDL_touchDevices[index]) {
   172         return SDL_OutOfMemory();
   173     }
   174 
   175     /* Added touch to list */
   176     ++SDL_num_touch;
   177 
   178     /* we're setting the touch properties */
   179     SDL_touchDevices[index]->id = touchID;
   180     SDL_touchDevices[index]->type = type;
   181     SDL_touchDevices[index]->num_fingers = 0;
   182     SDL_touchDevices[index]->max_fingers = 0;
   183     SDL_touchDevices[index]->fingers = NULL;
   184 
   185     /* Record this touch device for gestures */
   186     /* We could do this on the fly in the gesture code if we wanted */
   187     SDL_GestureAddTouch(touchID);
   188 
   189     return index;
   190 }
   191 
   192 static int
   193 SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
   194 {
   195     SDL_Finger *finger;
   196 
   197     if (touch->num_fingers == touch->max_fingers) {
   198         SDL_Finger **new_fingers;
   199         new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers+1)*sizeof(*touch->fingers));
   200         if (!new_fingers) {
   201             return SDL_OutOfMemory();
   202         }
   203         touch->fingers = new_fingers;
   204         touch->fingers[touch->max_fingers] = (SDL_Finger *)SDL_malloc(sizeof(*finger));
   205         if (!touch->fingers[touch->max_fingers]) {
   206             return SDL_OutOfMemory();
   207         }
   208         touch->max_fingers++;
   209     }
   210 
   211     finger = touch->fingers[touch->num_fingers++];
   212     finger->id = fingerid;
   213     finger->x = x;
   214     finger->y = y;
   215     finger->pressure = pressure;
   216     return 0;
   217 }
   218 
   219 static int
   220 SDL_DelFinger(SDL_Touch* touch, SDL_FingerID fingerid)
   221 {
   222     SDL_Finger *temp;
   223 
   224     int index = SDL_GetFingerIndex(touch, fingerid);
   225     if (index < 0) {
   226         return -1;
   227     }
   228 
   229     touch->num_fingers--;
   230     temp = touch->fingers[index];
   231     touch->fingers[index] = touch->fingers[touch->num_fingers];
   232     touch->fingers[touch->num_fingers] = temp;
   233     return 0;
   234 }
   235 
   236 int
   237 SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
   238               SDL_bool down, float x, float y, float pressure)
   239 {
   240     int posted;
   241     SDL_Finger *finger;
   242 
   243     SDL_Touch* touch = SDL_GetTouch(id);
   244     if (!touch) {
   245         return -1;
   246     }
   247 
   248     /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
   249     {
   250         SDL_Mouse *mouse = SDL_GetMouse();
   251         if (mouse->touch_mouse_events) {
   252             /* FIXME: maybe we should only restrict to a few SDL_TouchDeviceType */
   253             if (id != SDL_MOUSE_TOUCHID) {
   254                 SDL_Window *window = SDL_GetMouseFocus();
   255                 if (window) {
   256                     if (down) {
   257                         if (finger_touching == SDL_FALSE) {
   258                             int pos_x = (int)(x * (float)window->w);
   259                             int pos_y = (int)(y * (float)window->h);
   260                             if (pos_x < 0) pos_x = 0;
   261                             if (pos_x > window->w - 1) pos_x = window->w - 1;
   262                             if (pos_y < 0) pos_y = 0;
   263                             if (pos_y > window->h - 1) pos_y = window->h - 1;
   264                             SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
   265                             SDL_SendMouseButton(window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
   266                         }
   267                     } else {
   268                         if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
   269                             SDL_SendMouseButton(window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
   270                         }
   271                     }
   272                 }
   273                 if (down) {
   274                     if (finger_touching == SDL_FALSE) {
   275                         finger_touching = SDL_TRUE;
   276                         track_touchid = id;
   277                         track_fingerid = fingerid;
   278                     }
   279                 } else {
   280                     if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
   281                         finger_touching = SDL_FALSE;
   282                     }
   283                 }
   284             }
   285         }
   286     }
   287 
   288     finger = SDL_GetFinger(touch, fingerid);
   289     if (down) {
   290         if (finger) {
   291             /* This finger is already down */
   292             return 0;
   293         }
   294 
   295         if (SDL_AddFinger(touch, fingerid, x, y, pressure) < 0) {
   296             return 0;
   297         }
   298 
   299         posted = 0;
   300         if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
   301             SDL_Event event;
   302             event.tfinger.type = SDL_FINGERDOWN;
   303             event.tfinger.touchId = id;
   304             event.tfinger.fingerId = fingerid;
   305             event.tfinger.x = x;
   306             event.tfinger.y = y;
   307             event.tfinger.dx = 0;
   308             event.tfinger.dy = 0;
   309             event.tfinger.pressure = pressure;
   310             posted = (SDL_PushEvent(&event) > 0);
   311         }
   312     } else {
   313         if (!finger) {
   314             /* This finger is already up */
   315             return 0;
   316         }
   317 
   318         posted = 0;
   319         if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
   320             SDL_Event event;
   321             event.tfinger.type = SDL_FINGERUP;
   322             event.tfinger.touchId =  id;
   323             event.tfinger.fingerId = fingerid;
   324             /* I don't trust the coordinates passed on fingerUp */
   325             event.tfinger.x = finger->x;
   326             event.tfinger.y = finger->y;
   327             event.tfinger.dx = 0;
   328             event.tfinger.dy = 0;
   329             event.tfinger.pressure = pressure;
   330             posted = (SDL_PushEvent(&event) > 0);
   331         }
   332 
   333         SDL_DelFinger(touch, fingerid);
   334     }
   335     return posted;
   336 }
   337 
   338 int
   339 SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
   340                     float x, float y, float pressure)
   341 {
   342     SDL_Touch *touch;
   343     SDL_Finger *finger;
   344     int posted;
   345     float xrel, yrel, prel;
   346 
   347     touch = SDL_GetTouch(id);
   348     if (!touch) {
   349         return -1;
   350     }
   351 
   352     /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
   353     {
   354         SDL_Mouse *mouse = SDL_GetMouse();
   355         if (mouse->touch_mouse_events) {
   356             if (id != SDL_MOUSE_TOUCHID) {
   357                 SDL_Window *window = SDL_GetMouseFocus();
   358                 if (window) {
   359                     if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
   360                         int pos_x = (int)(x * (float)window->w);
   361                         int pos_y = (int)(y * (float)window->h);
   362                         if (pos_x < 0) pos_x = 0;
   363                         if (pos_x > window->w - 1) pos_x = window->w - 1;
   364                         if (pos_y < 0) pos_y = 0;
   365                         if (pos_y > window->h - 1) pos_y = window->h - 1;
   366                         SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
   367                     }
   368                 }
   369             }
   370         }
   371     }
   372 
   373     finger = SDL_GetFinger(touch,fingerid);
   374     if (!finger) {
   375         return SDL_SendTouch(id, fingerid, SDL_TRUE, x, y, pressure);
   376     }
   377 
   378     xrel = x - finger->x;
   379     yrel = y - finger->y;
   380     prel = pressure - finger->pressure;
   381 
   382     /* Drop events that don't change state */
   383     if (xrel == 0.0f && yrel == 0.0f && prel == 0.0f) {
   384 #if 0
   385         printf("Touch event didn't change state - dropped!\n");
   386 #endif
   387         return 0;
   388     }
   389 
   390     /* Update internal touch coordinates */
   391     finger->x = x;
   392     finger->y = y;
   393     finger->pressure = pressure;
   394 
   395     /* Post the event, if desired */
   396     posted = 0;
   397     if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) {
   398         SDL_Event event;
   399         event.tfinger.type = SDL_FINGERMOTION;
   400         event.tfinger.touchId = id;
   401         event.tfinger.fingerId = fingerid;
   402         event.tfinger.x = x;
   403         event.tfinger.y = y;
   404         event.tfinger.dx = xrel;
   405         event.tfinger.dy = yrel;
   406         event.tfinger.pressure = pressure;
   407         posted = (SDL_PushEvent(&event) > 0);
   408     }
   409     return posted;
   410 }
   411 
   412 void
   413 SDL_DelTouch(SDL_TouchID id)
   414 {
   415     int i;
   416     int index = SDL_GetTouchIndex(id);
   417     SDL_Touch *touch = SDL_GetTouch(id);
   418 
   419     if (!touch) {
   420         return;
   421     }
   422 
   423     for (i = 0; i < touch->max_fingers; ++i) {
   424         SDL_free(touch->fingers[i]);
   425     }
   426     SDL_free(touch->fingers);
   427     SDL_free(touch);
   428 
   429     SDL_num_touch--;
   430     SDL_touchDevices[index] = SDL_touchDevices[SDL_num_touch];
   431 
   432     /* Delete this touch device for gestures */
   433     SDL_GestureDelTouch(id);
   434 }
   435 
   436 void
   437 SDL_TouchQuit(void)
   438 {
   439     int i;
   440 
   441     for (i = SDL_num_touch; i--; ) {
   442         SDL_DelTouch(SDL_touchDevices[i]->id);
   443     }
   444     SDL_assert(SDL_num_touch == 0);
   445 
   446     SDL_free(SDL_touchDevices);
   447     SDL_touchDevices = NULL;
   448     SDL_GestureQuit();
   449 }
   450 
   451 /* vi: set ts=4 sw=4 expandtab: */