src/events/SDL_touch.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 22 Jun 2015 23:36:06 -0700
changeset 9776 952ff8a5076f
parent 9730 3136a8c1cf0b
child 9998 f67cf37e9cd4
permissions -rw-r--r--
Fixed bug 3030 - SDL_RecreateWindow fails to restore title, icon, etc.

Adam M.

It loses the title and icon when window recreation fails. For instance, this may happen when trying to create an OpenGL ES window on a system that doesn't support it. But at that point, the title and icon have already been lost.
jim@4640
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@9619
     3
  Copyright (C) 1997-2015 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);
slouken@6951
    39
}
slouken@6951
    40
slouken@6951
    41
int
philipp@7170
    42
SDL_GetNumTouchDevices(void)
slouken@6951
    43
{
slouken@6951
    44
    return SDL_num_touch;
jim@4640
    45
}
jim@4642
    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@4640
    55
}
jim@4640
    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)
jim@4640
    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@5076
    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
}
jim@4640
   104
slouken@6951
   105
int
slouken@6951
   106
SDL_GetNumTouchFingers(SDL_TouchID touchID)
slouken@6951
   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@6951
   133
    int index;
slouken@6951
   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();
slouken@6951
   145
    }
slouken@6951
   146
slouken@6951
   147
    SDL_touchDevices = touchDevices;
philipp@9730
   148
    index = SDL_num_touch;
slouken@6951
   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
slouken@6951
   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;
slouken@6951
   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);
slouken@6951
   167
slouken@6951
   168
    return index;
slouken@6951
   169
}
slouken@6951
   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
    }
jim@4640
   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) {
jim@4640
   224
        return -1;
jim@4640
   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
        }
jim@4640
   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
}
jim@4642
   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;
jim@4657
   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;
jim@4640
   328
}
jim@4640
   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: */