src/events/SDL_touch.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 18 Aug 2017 20:00:29 -0400
changeset 11323 46861f3fc187
parent 11290 ef96b05151c5
child 11811 5d94cb6b24d3
permissions -rw-r--r--
cmake: added a FIXME for later.

Have to figure out what cmake version fixed this and bump the minimum to that.
jim@4640
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
jim@4640
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
jim@4640
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
jim@4640
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
jim@4640
    20
*/
icculus@8093
    21
#include "../SDL_internal.h"
jim@4640
    22
jim@4640
    23
/* General touch handling code for SDL */
jim@4640
    24
slouken@6951
    25
#include "SDL_assert.h"
jim@4640
    26
#include "SDL_events.h"
jim@4640
    27
#include "SDL_events_c.h"
slouken@10880
    28
#include "../video/SDL_sysvideo.h"
jimtla@4648
    29
jim@4640
    30
jim@4640
    31
static int SDL_num_touch = 0;
slouken@6951
    32
static SDL_Touch **SDL_touchDevices = NULL;
jim@4640
    33
jim@4640
    34
jim@4640
    35
/* Public functions */
jim@4640
    36
int
jim@4640
    37
SDL_TouchInit(void)
jim@4640
    38
{
slouken@6951
    39
    return (0);
jim@4640
    40
}
jim@4642
    41
slouken@6951
    42
int
philipp@7170
    43
SDL_GetNumTouchDevices(void)
jim@4640
    44
{
slouken@6951
    45
    return SDL_num_touch;
jim@4640
    46
}
jim@4640
    47
slouken@6951
    48
SDL_TouchID
slouken@6951
    49
SDL_GetTouchDevice(int index)
jim@4641
    50
{
jim@4642
    51
    if (index < 0 || index >= SDL_num_touch) {
slouken@10880
    52
        SDL_SetError("Unknown touch device index %d", index);
slouken@6951
    53
        return 0;
jim@4642
    54
    }
slouken@6951
    55
    return SDL_touchDevices[index]->id;
jim@4641
    56
}
jim@4641
    57
slouken@6044
    58
static int
slouken@6951
    59
SDL_GetTouchIndex(SDL_TouchID id)
jim@4640
    60
{
jim@4640
    61
    int index;
jim@4640
    62
    SDL_Touch *touch;
jim@4640
    63
jim@4640
    64
    for (index = 0; index < SDL_num_touch; ++index) {
slouken@6951
    65
        touch = SDL_touchDevices[index];
jim@4640
    66
        if (touch->id == id) {
jim@4640
    67
            return index;
jim@4640
    68
        }
jim@4640
    69
    }
jim@4640
    70
    return -1;
jim@4640
    71
}
jim@4640
    72
slouken@6951
    73
SDL_Touch *
slouken@6951
    74
SDL_GetTouch(SDL_TouchID id)
slouken@6951
    75
{
slouken@6951
    76
    int index = SDL_GetTouchIndex(id);
slouken@6951
    77
    if (index < 0 || index >= SDL_num_touch) {
slouken@10880
    78
        if (SDL_GetVideoDevice()->ResetTouch != NULL) {
slouken@10880
    79
            SDL_SetError("Unknown touch id %d, resetting", (int) id);
slouken@10880
    80
            (SDL_GetVideoDevice()->ResetTouch)(SDL_GetVideoDevice());
slouken@10880
    81
        } else {
slouken@10880
    82
            SDL_SetError("Unknown touch device id %d, cannot reset", (int) id);
slouken@10880
    83
        }
slouken@6951
    84
        return NULL;
slouken@6951
    85
    }
slouken@6951
    86
    return SDL_touchDevices[index];
slouken@6951
    87
}
slouken@6951
    88
slouken@6951
    89
static int
slouken@6951
    90
SDL_GetFingerIndex(const SDL_Touch * touch, SDL_FingerID fingerid)
slouken@6951
    91
{
slouken@6951
    92
    int index;
slouken@6951
    93
    for (index = 0; index < touch->num_fingers; ++index) {
slouken@6951
    94
        if (touch->fingers[index]->id == fingerid) {
slouken@6951
    95
            return index;
slouken@6951
    96
        }
slouken@6951
    97
    }
slouken@6951
    98
    return -1;
slouken@6951
    99
}
slouken@6951
   100
slouken@10609
   101
static SDL_Finger *
slouken@6951
   102
SDL_GetFinger(const SDL_Touch * touch, SDL_FingerID id)
slouken@6951
   103
{
slouken@6951
   104
    int index = SDL_GetFingerIndex(touch, id);
slouken@6951
   105
    if (index < 0 || index >= touch->num_fingers) {
slouken@6951
   106
        return NULL;
slouken@6951
   107
    }
slouken@6951
   108
    return touch->fingers[index];
slouken@6951
   109
}
slouken@6951
   110
jim@4640
   111
int
slouken@6951
   112
SDL_GetNumTouchFingers(SDL_TouchID touchID)
jim@4640
   113
{
slouken@6951
   114
    SDL_Touch *touch = SDL_GetTouch(touchID);
slouken@6951
   115
    if (touch) {
slouken@6951
   116
        return touch->num_fingers;
slouken@6951
   117
    }
slouken@6951
   118
    return 0;
slouken@6951
   119
}
slouken@6951
   120
slouken@6951
   121
SDL_Finger *
slouken@6951
   122
SDL_GetTouchFinger(SDL_TouchID touchID, int index)
slouken@6951
   123
{
slouken@6951
   124
    SDL_Touch *touch = SDL_GetTouch(touchID);
slouken@6951
   125
    if (!touch) {
slouken@6951
   126
        return NULL;
slouken@6951
   127
    }
slouken@6951
   128
    if (index < 0 || index >= touch->num_fingers) {
slouken@6951
   129
        SDL_SetError("Unknown touch finger");
slouken@6951
   130
        return NULL;
slouken@6951
   131
    }
slouken@6951
   132
    return touch->fingers[index];
slouken@6951
   133
}
slouken@6951
   134
slouken@6951
   135
int
slouken@6951
   136
SDL_AddTouch(SDL_TouchID touchID, const char *name)
slouken@6951
   137
{
slouken@6951
   138
    SDL_Touch **touchDevices;
slouken@5076
   139
    int index;
jim@4640
   140
slouken@6951
   141
    index = SDL_GetTouchIndex(touchID);
slouken@6951
   142
    if (index >= 0) {
slouken@6951
   143
        return index;
jim@4640
   144
    }
jim@4640
   145
jim@4640
   146
    /* Add the touch to the list of touch */
slouken@6951
   147
    touchDevices = (SDL_Touch **) SDL_realloc(SDL_touchDevices,
slouken@6951
   148
                                      (SDL_num_touch + 1) * sizeof(*touchDevices));
slouken@6951
   149
    if (!touchDevices) {
icculus@7037
   150
        return SDL_OutOfMemory();
jim@4640
   151
    }
jim@4640
   152
slouken@6951
   153
    SDL_touchDevices = touchDevices;
philipp@9730
   154
    index = SDL_num_touch;
jim@4640
   155
slouken@6951
   156
    SDL_touchDevices[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touchDevices[index]));
slouken@6951
   157
    if (!SDL_touchDevices[index]) {
icculus@7037
   158
        return SDL_OutOfMemory();
jim@4640
   159
    }
jim@4640
   160
philipp@9730
   161
    /* Added touch to list */
philipp@9730
   162
    ++SDL_num_touch;
philipp@9730
   163
jim@4640
   164
    /* we're setting the touch properties */
slouken@6951
   165
    SDL_touchDevices[index]->id = touchID;
slouken@6951
   166
    SDL_touchDevices[index]->num_fingers = 0;
slouken@6951
   167
    SDL_touchDevices[index]->max_fingers = 0;
slouken@6951
   168
    SDL_touchDevices[index]->fingers = NULL;
jim@4642
   169
slouken@6951
   170
    /* Record this touch device for gestures */
slouken@6951
   171
    /* We could do this on the fly in the gesture code if we wanted */
slouken@6951
   172
    SDL_GestureAddTouch(touchID);
jim@4657
   173
jim@4640
   174
    return index;
jim@4640
   175
}
jim@4640
   176
slouken@7191
   177
static int
slouken@6951
   178
SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
slouken@6951
   179
{
slouken@6951
   180
    SDL_Finger *finger;
slouken@6951
   181
slouken@6951
   182
    if (touch->num_fingers == touch->max_fingers) {
slouken@6951
   183
        SDL_Finger **new_fingers;
slouken@6951
   184
        new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers+1)*sizeof(*touch->fingers));
slouken@6951
   185
        if (!new_fingers) {
icculus@7037
   186
            return SDL_OutOfMemory();
slouken@6951
   187
        }
slouken@6951
   188
        touch->fingers = new_fingers;
slouken@6951
   189
        touch->fingers[touch->max_fingers] = (SDL_Finger *)SDL_malloc(sizeof(*finger));
slouken@6951
   190
        if (!touch->fingers[touch->max_fingers]) {
icculus@7037
   191
            return SDL_OutOfMemory();
slouken@6951
   192
        }
slouken@6951
   193
        touch->max_fingers++;
slouken@6951
   194
    }
slouken@6951
   195
slouken@6951
   196
    finger = touch->fingers[touch->num_fingers++];
slouken@6951
   197
    finger->id = fingerid;
slouken@6951
   198
    finger->x = x;
slouken@6951
   199
    finger->y = y;
slouken@6951
   200
    finger->pressure = pressure;
slouken@6951
   201
    return 0;
slouken@6951
   202
}
slouken@6951
   203
slouken@6951
   204
static int
slouken@6951
   205
SDL_DelFinger(SDL_Touch* touch, SDL_FingerID fingerid)
slouken@6951
   206
{
slouken@6951
   207
    SDL_Finger *temp;
slouken@6951
   208
slouken@6951
   209
    int index = SDL_GetFingerIndex(touch, fingerid);
slouken@6951
   210
    if (index < 0) {
slouken@6951
   211
        return -1;
slouken@6951
   212
    }
slouken@6951
   213
slouken@6951
   214
    touch->num_fingers--;
slouken@6951
   215
    temp = touch->fingers[index];
slouken@6951
   216
    touch->fingers[index] = touch->fingers[touch->num_fingers];
slouken@6951
   217
    touch->fingers[touch->num_fingers] = temp;
slouken@6951
   218
    return 0;
slouken@6951
   219
}
slouken@6951
   220
slouken@6951
   221
int
slouken@6951
   222
SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
slouken@6951
   223
              SDL_bool down, float x, float y, float pressure)
slouken@6951
   224
{
slouken@6951
   225
    int posted;
slouken@6951
   226
    SDL_Finger *finger;
slouken@6951
   227
slouken@6951
   228
    SDL_Touch* touch = SDL_GetTouch(id);
slouken@6951
   229
    if (!touch) {
slouken@6951
   230
        return -1;
slouken@6951
   231
    }
slouken@6951
   232
slouken@6951
   233
    finger = SDL_GetFinger(touch, fingerid);
slouken@6951
   234
    if (down) {
slouken@6951
   235
        if (finger) {
slouken@6951
   236
            /* This finger is already down */
slouken@6951
   237
            return 0;
slouken@6951
   238
        }
slouken@6951
   239
slouken@6951
   240
        if (SDL_AddFinger(touch, fingerid, x, y, pressure) < 0) {
slouken@6951
   241
            return 0;
slouken@6951
   242
        }
slouken@6951
   243
slouken@6951
   244
        posted = 0;
slouken@6951
   245
        if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
slouken@6951
   246
            SDL_Event event;
slouken@6951
   247
            event.tfinger.type = SDL_FINGERDOWN;
slouken@6951
   248
            event.tfinger.touchId = id;
slouken@6951
   249
            event.tfinger.fingerId = fingerid;
slouken@6951
   250
            event.tfinger.x = x;
slouken@6951
   251
            event.tfinger.y = y;
slouken@6951
   252
            event.tfinger.dx = 0;
slouken@6951
   253
            event.tfinger.dy = 0;
slouken@6951
   254
            event.tfinger.pressure = pressure;
slouken@6951
   255
            posted = (SDL_PushEvent(&event) > 0);
slouken@6951
   256
        }
slouken@6951
   257
    } else {
slouken@6951
   258
        if (!finger) {
slouken@6951
   259
            /* This finger is already up */
slouken@6951
   260
            return 0;
slouken@6951
   261
        }
slouken@6951
   262
slouken@6951
   263
        posted = 0;
slouken@6951
   264
        if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
slouken@6951
   265
            SDL_Event event;
slouken@6951
   266
            event.tfinger.type = SDL_FINGERUP;
slouken@6951
   267
            event.tfinger.touchId =  id;
slouken@6951
   268
            event.tfinger.fingerId = fingerid;
slouken@6951
   269
            /* I don't trust the coordinates passed on fingerUp */
slouken@7191
   270
            event.tfinger.x = finger->x;
slouken@6951
   271
            event.tfinger.y = finger->y;
slouken@6951
   272
            event.tfinger.dx = 0;
slouken@6951
   273
            event.tfinger.dy = 0;
slouken@6951
   274
            event.tfinger.pressure = pressure;
slouken@6951
   275
            posted = (SDL_PushEvent(&event) > 0);
slouken@6951
   276
        }
slouken@6951
   277
slouken@6951
   278
        SDL_DelFinger(touch, fingerid);
slouken@6951
   279
    }
slouken@6951
   280
    return posted;
slouken@6951
   281
}
slouken@6951
   282
slouken@6951
   283
int
slouken@6951
   284
SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
slouken@6951
   285
                    float x, float y, float pressure)
slouken@6951
   286
{
slouken@6951
   287
    SDL_Touch *touch;
slouken@6951
   288
    SDL_Finger *finger;
slouken@6951
   289
    int posted;
slouken@6951
   290
    float xrel, yrel, prel;
slouken@6951
   291
slouken@6951
   292
    touch = SDL_GetTouch(id);
slouken@6951
   293
    if (!touch) {
slouken@6951
   294
        return -1;
slouken@6951
   295
    }
slouken@6951
   296
slouken@6951
   297
    finger = SDL_GetFinger(touch,fingerid);
slouken@6951
   298
    if (!finger) {
slouken@7191
   299
        return SDL_SendTouch(id, fingerid, SDL_TRUE, x, y, pressure);
slouken@6951
   300
    }
slouken@6951
   301
slouken@6951
   302
    xrel = x - finger->x;
slouken@6951
   303
    yrel = y - finger->y;
slouken@6951
   304
    prel = pressure - finger->pressure;
slouken@6951
   305
slouken@6951
   306
    /* Drop events that don't change state */
slouken@6951
   307
    if (!xrel && !yrel && !prel) {
slouken@6951
   308
#if 0
slouken@6951
   309
        printf("Touch event didn't change state - dropped!\n");
slouken@6951
   310
#endif
slouken@6951
   311
        return 0;
slouken@6951
   312
    }
slouken@6951
   313
slouken@6951
   314
    /* Update internal touch coordinates */
slouken@6951
   315
    finger->x = x;
slouken@6951
   316
    finger->y = y;
slouken@6951
   317
    finger->pressure = pressure;
slouken@7191
   318
slouken@6951
   319
    /* Post the event, if desired */
slouken@6951
   320
    posted = 0;
slouken@6951
   321
    if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) {
slouken@6951
   322
        SDL_Event event;
slouken@6951
   323
        event.tfinger.type = SDL_FINGERMOTION;
slouken@6951
   324
        event.tfinger.touchId = id;
slouken@6951
   325
        event.tfinger.fingerId = fingerid;
slouken@6951
   326
        event.tfinger.x = x;
slouken@6951
   327
        event.tfinger.y = y;
slouken@6951
   328
        event.tfinger.dx = xrel;
slouken@7191
   329
        event.tfinger.dy = yrel;
slouken@6951
   330
        event.tfinger.pressure = pressure;
slouken@6951
   331
        posted = (SDL_PushEvent(&event) > 0);
slouken@6951
   332
    }
slouken@6951
   333
    return posted;
slouken@6951
   334
}
slouken@6951
   335
jim@4640
   336
void
jimtla@4678
   337
SDL_DelTouch(SDL_TouchID id)
jim@4640
   338
{
slouken@6951
   339
    int i;
slouken@6951
   340
    int index = SDL_GetTouchIndex(id);
jim@4641
   341
    SDL_Touch *touch = SDL_GetTouch(id);
jim@4640
   342
jim@4640
   343
    if (!touch) {
jim@4640
   344
        return;
jim@4640
   345
    }
jim@4640
   346
slouken@6951
   347
    for (i = 0; i < touch->max_fingers; ++i) {
slouken@6951
   348
        SDL_free(touch->fingers[i]);
jim@4640
   349
    }
slouken@6951
   350
    SDL_free(touch->fingers);
jim@4640
   351
    SDL_free(touch);
jim@4640
   352
jim@4641
   353
    SDL_num_touch--;
slouken@6951
   354
    SDL_touchDevices[index] = SDL_touchDevices[SDL_num_touch];
slouken@11290
   355
slouken@11290
   356
    /* Delete this touch device for gestures */
slouken@11290
   357
    SDL_GestureDelTouch(id);
jim@4640
   358
}
jim@4640
   359
jim@4640
   360
void
jim@4640
   361
SDL_TouchQuit(void)
jim@4640
   362
{
jim@4640
   363
    int i;
jim@4640
   364
slouken@6951
   365
    for (i = SDL_num_touch; i--; ) {
slouken@6951
   366
        SDL_DelTouch(SDL_touchDevices[i]->id);
jim@4640
   367
    }
slouken@6951
   368
    SDL_assert(SDL_num_touch == 0);
jim@4640
   369
slouken@7719
   370
    SDL_free(SDL_touchDevices);
slouken@7719
   371
    SDL_touchDevices = NULL;
slouken@11290
   372
    SDL_GestureQuit();
jim@4640
   373
}
jim@4640
   374
jim@4640
   375
/* vi: set ts=4 sw=4 expandtab: */