src/events/SDL_touch.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 02 Jan 2016 10:10:34 -0800
changeset 9998 f67cf37e9cd4
parent 9730 3136a8c1cf0b
child 10609 d702ecbd8ba7
permissions -rw-r--r--
Updated copyright to 2016
jim@4640
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@9998
     3
  Copyright (C) 1997-2016 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"
jimtla@4648
    28
jim@4640
    29
jim@4640
    30
static int SDL_num_touch = 0;
slouken@6951
    31
static SDL_Touch **SDL_touchDevices = NULL;
jim@4640
    32
jim@4640
    33
jim@4640
    34
/* Public functions */
jim@4640
    35
int
jim@4640
    36
SDL_TouchInit(void)
jim@4640
    37
{
slouken@6951
    38
    return (0);
jim@4640
    39
}
jim@4642
    40
slouken@6951
    41
int
philipp@7170
    42
SDL_GetNumTouchDevices(void)
jim@4640
    43
{
slouken@6951
    44
    return SDL_num_touch;
jim@4640
    45
}
jim@4640
    46
slouken@6951
    47
SDL_TouchID
slouken@6951
    48
SDL_GetTouchDevice(int index)
jim@4641
    49
{
jim@4642
    50
    if (index < 0 || index >= SDL_num_touch) {
slouken@6951
    51
        SDL_SetError("Unknown touch device");
slouken@6951
    52
        return 0;
jim@4642
    53
    }
slouken@6951
    54
    return SDL_touchDevices[index]->id;
jim@4641
    55
}
jim@4641
    56
slouken@6044
    57
static int
slouken@6951
    58
SDL_GetTouchIndex(SDL_TouchID id)
jim@4640
    59
{
jim@4640
    60
    int index;
jim@4640
    61
    SDL_Touch *touch;
jim@4640
    62
jim@4640
    63
    for (index = 0; index < SDL_num_touch; ++index) {
slouken@6951
    64
        touch = SDL_touchDevices[index];
jim@4640
    65
        if (touch->id == id) {
jim@4640
    66
            return index;
jim@4640
    67
        }
jim@4640
    68
    }
jim@4640
    69
    return -1;
jim@4640
    70
}
jim@4640
    71
slouken@6951
    72
SDL_Touch *
slouken@6951
    73
SDL_GetTouch(SDL_TouchID id)
slouken@6951
    74
{
slouken@6951
    75
    int index = SDL_GetTouchIndex(id);
slouken@6951
    76
    if (index < 0 || index >= SDL_num_touch) {
slouken@6951
    77
        SDL_SetError("Unknown touch device");
slouken@6951
    78
        return NULL;
slouken@6951
    79
    }
slouken@6951
    80
    return SDL_touchDevices[index];
slouken@6951
    81
}
slouken@6951
    82
slouken@6951
    83
static int
slouken@6951
    84
SDL_GetFingerIndex(const SDL_Touch * touch, SDL_FingerID fingerid)
slouken@6951
    85
{
slouken@6951
    86
    int index;
slouken@6951
    87
    for (index = 0; index < touch->num_fingers; ++index) {
slouken@6951
    88
        if (touch->fingers[index]->id == fingerid) {
slouken@6951
    89
            return index;
slouken@6951
    90
        }
slouken@6951
    91
    }
slouken@6951
    92
    return -1;
slouken@6951
    93
}
slouken@6951
    94
slouken@6951
    95
SDL_Finger *
slouken@6951
    96
SDL_GetFinger(const SDL_Touch * touch, SDL_FingerID id)
slouken@6951
    97
{
slouken@6951
    98
    int index = SDL_GetFingerIndex(touch, id);
slouken@6951
    99
    if (index < 0 || index >= touch->num_fingers) {
slouken@6951
   100
        return NULL;
slouken@6951
   101
    }
slouken@6951
   102
    return touch->fingers[index];
slouken@6951
   103
}
slouken@6951
   104
jim@4640
   105
int
slouken@6951
   106
SDL_GetNumTouchFingers(SDL_TouchID touchID)
jim@4640
   107
{
slouken@6951
   108
    SDL_Touch *touch = SDL_GetTouch(touchID);
slouken@6951
   109
    if (touch) {
slouken@6951
   110
        return touch->num_fingers;
slouken@6951
   111
    }
slouken@6951
   112
    return 0;
slouken@6951
   113
}
slouken@6951
   114
slouken@6951
   115
SDL_Finger *
slouken@6951
   116
SDL_GetTouchFinger(SDL_TouchID touchID, int index)
slouken@6951
   117
{
slouken@6951
   118
    SDL_Touch *touch = SDL_GetTouch(touchID);
slouken@6951
   119
    if (!touch) {
slouken@6951
   120
        return NULL;
slouken@6951
   121
    }
slouken@6951
   122
    if (index < 0 || index >= touch->num_fingers) {
slouken@6951
   123
        SDL_SetError("Unknown touch finger");
slouken@6951
   124
        return NULL;
slouken@6951
   125
    }
slouken@6951
   126
    return touch->fingers[index];
slouken@6951
   127
}
slouken@6951
   128
slouken@6951
   129
int
slouken@6951
   130
SDL_AddTouch(SDL_TouchID touchID, const char *name)
slouken@6951
   131
{
slouken@6951
   132
    SDL_Touch **touchDevices;
slouken@5076
   133
    int index;
jim@4640
   134
slouken@6951
   135
    index = SDL_GetTouchIndex(touchID);
slouken@6951
   136
    if (index >= 0) {
slouken@6951
   137
        return index;
jim@4640
   138
    }
jim@4640
   139
jim@4640
   140
    /* Add the touch to the list of touch */
slouken@6951
   141
    touchDevices = (SDL_Touch **) SDL_realloc(SDL_touchDevices,
slouken@6951
   142
                                      (SDL_num_touch + 1) * sizeof(*touchDevices));
slouken@6951
   143
    if (!touchDevices) {
icculus@7037
   144
        return SDL_OutOfMemory();
jim@4640
   145
    }
jim@4640
   146
slouken@6951
   147
    SDL_touchDevices = touchDevices;
philipp@9730
   148
    index = SDL_num_touch;
jim@4640
   149
slouken@6951
   150
    SDL_touchDevices[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touchDevices[index]));
slouken@6951
   151
    if (!SDL_touchDevices[index]) {
icculus@7037
   152
        return SDL_OutOfMemory();
jim@4640
   153
    }
jim@4640
   154
philipp@9730
   155
    /* Added touch to list */
philipp@9730
   156
    ++SDL_num_touch;
philipp@9730
   157
jim@4640
   158
    /* we're setting the touch properties */
slouken@6951
   159
    SDL_touchDevices[index]->id = touchID;
slouken@6951
   160
    SDL_touchDevices[index]->num_fingers = 0;
slouken@6951
   161
    SDL_touchDevices[index]->max_fingers = 0;
slouken@6951
   162
    SDL_touchDevices[index]->fingers = NULL;
jim@4642
   163
slouken@6951
   164
    /* Record this touch device for gestures */
slouken@6951
   165
    /* We could do this on the fly in the gesture code if we wanted */
slouken@6951
   166
    SDL_GestureAddTouch(touchID);
jim@4657
   167
jim@4640
   168
    return index;
jim@4640
   169
}
jim@4640
   170
slouken@7191
   171
static int
slouken@6951
   172
SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
slouken@6951
   173
{
slouken@6951
   174
    SDL_Finger *finger;
slouken@6951
   175
slouken@6951
   176
    if (touch->num_fingers == touch->max_fingers) {
slouken@6951
   177
        SDL_Finger **new_fingers;
slouken@6951
   178
        new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers+1)*sizeof(*touch->fingers));
slouken@6951
   179
        if (!new_fingers) {
icculus@7037
   180
            return SDL_OutOfMemory();
slouken@6951
   181
        }
slouken@6951
   182
        touch->fingers = new_fingers;
slouken@6951
   183
        touch->fingers[touch->max_fingers] = (SDL_Finger *)SDL_malloc(sizeof(*finger));
slouken@6951
   184
        if (!touch->fingers[touch->max_fingers]) {
icculus@7037
   185
            return SDL_OutOfMemory();
slouken@6951
   186
        }
slouken@6951
   187
        touch->max_fingers++;
slouken@6951
   188
    }
slouken@6951
   189
slouken@6951
   190
    finger = touch->fingers[touch->num_fingers++];
slouken@6951
   191
    finger->id = fingerid;
slouken@6951
   192
    finger->x = x;
slouken@6951
   193
    finger->y = y;
slouken@6951
   194
    finger->pressure = pressure;
slouken@6951
   195
    return 0;
slouken@6951
   196
}
slouken@6951
   197
slouken@6951
   198
static int
slouken@6951
   199
SDL_DelFinger(SDL_Touch* touch, SDL_FingerID fingerid)
slouken@6951
   200
{
slouken@6951
   201
    SDL_Finger *temp;
slouken@6951
   202
slouken@6951
   203
    int index = SDL_GetFingerIndex(touch, fingerid);
slouken@6951
   204
    if (index < 0) {
slouken@6951
   205
        return -1;
slouken@6951
   206
    }
slouken@6951
   207
slouken@6951
   208
    touch->num_fingers--;
slouken@6951
   209
    temp = touch->fingers[index];
slouken@6951
   210
    touch->fingers[index] = touch->fingers[touch->num_fingers];
slouken@6951
   211
    touch->fingers[touch->num_fingers] = temp;
slouken@6951
   212
    return 0;
slouken@6951
   213
}
slouken@6951
   214
slouken@6951
   215
int
slouken@6951
   216
SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
slouken@6951
   217
              SDL_bool down, float x, float y, float pressure)
slouken@6951
   218
{
slouken@6951
   219
    int posted;
slouken@6951
   220
    SDL_Finger *finger;
slouken@6951
   221
slouken@6951
   222
    SDL_Touch* touch = SDL_GetTouch(id);
slouken@6951
   223
    if (!touch) {
slouken@6951
   224
        return -1;
slouken@6951
   225
    }
slouken@6951
   226
slouken@6951
   227
    finger = SDL_GetFinger(touch, fingerid);
slouken@6951
   228
    if (down) {
slouken@6951
   229
        if (finger) {
slouken@6951
   230
            /* This finger is already down */
slouken@6951
   231
            return 0;
slouken@6951
   232
        }
slouken@6951
   233
slouken@6951
   234
        if (SDL_AddFinger(touch, fingerid, x, y, pressure) < 0) {
slouken@6951
   235
            return 0;
slouken@6951
   236
        }
slouken@6951
   237
slouken@6951
   238
        posted = 0;
slouken@6951
   239
        if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
slouken@6951
   240
            SDL_Event event;
slouken@6951
   241
            event.tfinger.type = SDL_FINGERDOWN;
slouken@6951
   242
            event.tfinger.touchId = id;
slouken@6951
   243
            event.tfinger.fingerId = fingerid;
slouken@6951
   244
            event.tfinger.x = x;
slouken@6951
   245
            event.tfinger.y = y;
slouken@6951
   246
            event.tfinger.dx = 0;
slouken@6951
   247
            event.tfinger.dy = 0;
slouken@6951
   248
            event.tfinger.pressure = pressure;
slouken@6951
   249
            posted = (SDL_PushEvent(&event) > 0);
slouken@6951
   250
        }
slouken@6951
   251
    } else {
slouken@6951
   252
        if (!finger) {
slouken@6951
   253
            /* This finger is already up */
slouken@6951
   254
            return 0;
slouken@6951
   255
        }
slouken@6951
   256
slouken@6951
   257
        posted = 0;
slouken@6951
   258
        if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
slouken@6951
   259
            SDL_Event event;
slouken@6951
   260
            event.tfinger.type = SDL_FINGERUP;
slouken@6951
   261
            event.tfinger.touchId =  id;
slouken@6951
   262
            event.tfinger.fingerId = fingerid;
slouken@6951
   263
            /* I don't trust the coordinates passed on fingerUp */
slouken@7191
   264
            event.tfinger.x = finger->x;
slouken@6951
   265
            event.tfinger.y = finger->y;
slouken@6951
   266
            event.tfinger.dx = 0;
slouken@6951
   267
            event.tfinger.dy = 0;
slouken@6951
   268
            event.tfinger.pressure = pressure;
slouken@6951
   269
            posted = (SDL_PushEvent(&event) > 0);
slouken@6951
   270
        }
slouken@6951
   271
slouken@6951
   272
        SDL_DelFinger(touch, fingerid);
slouken@6951
   273
    }
slouken@6951
   274
    return posted;
slouken@6951
   275
}
slouken@6951
   276
slouken@6951
   277
int
slouken@6951
   278
SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
slouken@6951
   279
                    float x, float y, float pressure)
slouken@6951
   280
{
slouken@6951
   281
    SDL_Touch *touch;
slouken@6951
   282
    SDL_Finger *finger;
slouken@6951
   283
    int posted;
slouken@6951
   284
    float xrel, yrel, prel;
slouken@6951
   285
slouken@6951
   286
    touch = SDL_GetTouch(id);
slouken@6951
   287
    if (!touch) {
slouken@6951
   288
        return -1;
slouken@6951
   289
    }
slouken@6951
   290
slouken@6951
   291
    finger = SDL_GetFinger(touch,fingerid);
slouken@6951
   292
    if (!finger) {
slouken@7191
   293
        return SDL_SendTouch(id, fingerid, SDL_TRUE, x, y, pressure);
slouken@6951
   294
    }
slouken@6951
   295
slouken@6951
   296
    xrel = x - finger->x;
slouken@6951
   297
    yrel = y - finger->y;
slouken@6951
   298
    prel = pressure - finger->pressure;
slouken@6951
   299
slouken@6951
   300
    /* Drop events that don't change state */
slouken@6951
   301
    if (!xrel && !yrel && !prel) {
slouken@6951
   302
#if 0
slouken@6951
   303
        printf("Touch event didn't change state - dropped!\n");
slouken@6951
   304
#endif
slouken@6951
   305
        return 0;
slouken@6951
   306
    }
slouken@6951
   307
slouken@6951
   308
    /* Update internal touch coordinates */
slouken@6951
   309
    finger->x = x;
slouken@6951
   310
    finger->y = y;
slouken@6951
   311
    finger->pressure = pressure;
slouken@7191
   312
slouken@6951
   313
    /* Post the event, if desired */
slouken@6951
   314
    posted = 0;
slouken@6951
   315
    if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) {
slouken@6951
   316
        SDL_Event event;
slouken@6951
   317
        event.tfinger.type = SDL_FINGERMOTION;
slouken@6951
   318
        event.tfinger.touchId = id;
slouken@6951
   319
        event.tfinger.fingerId = fingerid;
slouken@6951
   320
        event.tfinger.x = x;
slouken@6951
   321
        event.tfinger.y = y;
slouken@6951
   322
        event.tfinger.dx = xrel;
slouken@7191
   323
        event.tfinger.dy = yrel;
slouken@6951
   324
        event.tfinger.pressure = pressure;
slouken@6951
   325
        posted = (SDL_PushEvent(&event) > 0);
slouken@6951
   326
    }
slouken@6951
   327
    return posted;
slouken@6951
   328
}
slouken@6951
   329
jim@4640
   330
void
jimtla@4678
   331
SDL_DelTouch(SDL_TouchID id)
jim@4640
   332
{
slouken@6951
   333
    int i;
slouken@6951
   334
    int index = SDL_GetTouchIndex(id);
jim@4641
   335
    SDL_Touch *touch = SDL_GetTouch(id);
jim@4640
   336
jim@4640
   337
    if (!touch) {
jim@4640
   338
        return;
jim@4640
   339
    }
jim@4640
   340
slouken@6951
   341
    for (i = 0; i < touch->max_fingers; ++i) {
slouken@6951
   342
        SDL_free(touch->fingers[i]);
jim@4640
   343
    }
slouken@6951
   344
    SDL_free(touch->fingers);
jim@4640
   345
    SDL_free(touch);
jim@4640
   346
jim@4641
   347
    SDL_num_touch--;
slouken@6951
   348
    SDL_touchDevices[index] = SDL_touchDevices[SDL_num_touch];
jim@4640
   349
}
jim@4640
   350
jim@4640
   351
void
jim@4640
   352
SDL_TouchQuit(void)
jim@4640
   353
{
jim@4640
   354
    int i;
jim@4640
   355
slouken@6951
   356
    for (i = SDL_num_touch; i--; ) {
slouken@6951
   357
        SDL_DelTouch(SDL_touchDevices[i]->id);
jim@4640
   358
    }
slouken@6951
   359
    SDL_assert(SDL_num_touch == 0);
jim@4640
   360
slouken@7719
   361
    SDL_free(SDL_touchDevices);
slouken@7719
   362
    SDL_touchDevices = NULL;
jim@4640
   363
}
jim@4640
   364
jim@4640
   365
/* vi: set ts=4 sw=4 expandtab: */