src/events/SDL_touch.c
author Jim Grandpre
Thu, 27 May 2010 01:21:37 -0400
changeset 4641 49a97daea6ec
parent 4640 f068a6dfc858
child 4642 057e8762d2a1
permissions -rw-r--r--
Added touch event definitions. Heavily modified events/SDL_touch*.
jim@4640
     1
/*
jim@4640
     2
    SDL - Simple DirectMedia Layer
jim@4640
     3
    Copyright (C) 1997-2010 Sam Lantinga
jim@4640
     4
jim@4640
     5
    This library is free software; you can redistribute it and/or
jim@4640
     6
    modify it under the terms of the GNU Lesser General Public
jim@4640
     7
    License as published by the Free Software Foundation; either
jim@4640
     8
    version 2.1 of the License, or (at your option) any later version.
jim@4640
     9
jim@4640
    10
    This library is distributed in the hope that it will be useful,
jim@4640
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
jim@4640
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
jim@4640
    13
    Lesser General Public License for more details.
jim@4640
    14
jim@4640
    15
    You should have received a copy of the GNU Lesser General Public
jim@4640
    16
    License along with this library; if not, write to the Free Software
jim@4640
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
jim@4640
    18
jim@4640
    19
    Sam Lantinga
jim@4640
    20
    slouken@libsdl.org
jim@4640
    21
*/
jim@4640
    22
#include "SDL_config.h"
jim@4640
    23
jim@4640
    24
/* General touch handling code for SDL */
jim@4640
    25
jim@4640
    26
#include "SDL_events.h"
jim@4640
    27
#include "SDL_events_c.h"
jim@4640
    28
#include "../video/SDL_sysvideo.h"
jim@4640
    29
jim@4640
    30
jim@4640
    31
static int SDL_num_touch = 0;
jim@4641
    32
static SDL_Touch **SDL_touchPads = 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
{
jim@4640
    39
    return (0);
jim@4640
    40
}
jim@4640
    41
SDL_Touch *
jim@4641
    42
SDL_GetTouch(int id)
jim@4640
    43
{
jim@4641
    44
    int index = SDL_GetTouchIndexId(id);
jim@4640
    45
    if (index < 0 || index >= SDL_num_touch) {
jim@4640
    46
        return NULL;
jim@4640
    47
    }
jim@4641
    48
    return SDL_touchPads[index];
jim@4641
    49
}
jim@4641
    50
jim@4641
    51
SDL_Finger *
jim@4641
    52
SDL_GetFinger(SDL_Touch* touch,int id)
jim@4641
    53
{
jim@4641
    54
    int index = SDL_GetFingerIndexId(touch,id);
jim@4641
    55
    if(index < 0 || index >= touch->num_fingers)
jim@4641
    56
	return NULL;
jim@4641
    57
    return touch->fingers[index];
jim@4640
    58
}
jim@4640
    59
jim@4641
    60
int
jim@4641
    61
SDL_GetFingerIndexId(SDL_Touch* touch,int fingerid)
jim@4641
    62
{
jim@4641
    63
    int i;
jim@4641
    64
    for(i = 0;i < touch->num_fingers;i++)
jim@4641
    65
	if(touch->fingers[i]->id == fingerid)
jim@4641
    66
	    return i;
jim@4641
    67
    return -1;
jim@4641
    68
}
jim@4641
    69
jim@4641
    70
int
jim@4640
    71
SDL_GetTouchIndexId(int id)
jim@4640
    72
{
jim@4640
    73
    int index;
jim@4640
    74
    SDL_Touch *touch;
jim@4640
    75
jim@4640
    76
    for (index = 0; index < SDL_num_touch; ++index) {
jim@4641
    77
        touch = SDL_touchPads[index];
jim@4640
    78
        if (touch->id == id) {
jim@4640
    79
            return index;
jim@4640
    80
        }
jim@4640
    81
    }
jim@4640
    82
    return -1;
jim@4640
    83
}
jim@4640
    84
jim@4640
    85
int
jim@4640
    86
SDL_AddTouch(const SDL_Touch * touch, char *name, int pressure_max,
jim@4640
    87
             int pressure_min, int ends)
jim@4640
    88
{
jim@4641
    89
    SDL_Touch **touchPads;
jim@4640
    90
    int selected_touch;
jim@4640
    91
    int index;
jim@4640
    92
    size_t length;
jim@4640
    93
jim@4640
    94
    if (SDL_GetTouchIndexId(touch->id) != -1) {
jim@4640
    95
        SDL_SetError("Touch ID already in use");
jim@4640
    96
    }
jim@4640
    97
jim@4640
    98
    /* Add the touch to the list of touch */
jim@4641
    99
    touchPads = (SDL_Touch **) SDL_realloc(SDL_touchPads,
jim@4640
   100
                                      (SDL_num_touch + 1) * sizeof(*touch));
jim@4641
   101
    if (!touchPads) {
jim@4640
   102
        SDL_OutOfMemory();
jim@4640
   103
        return -1;
jim@4640
   104
    }
jim@4640
   105
jim@4641
   106
    SDL_touchPads = touchPads;
jim@4640
   107
    index = SDL_num_touch++;
jim@4640
   108
jim@4641
   109
    SDL_touchPads[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touchPads[index]));
jim@4641
   110
    if (!SDL_touchPads[index]) {
jim@4640
   111
        SDL_OutOfMemory();
jim@4640
   112
        return -1;
jim@4640
   113
    }
jim@4641
   114
    *SDL_touchPads[index] = *touch;
jim@4640
   115
jim@4640
   116
    /* we're setting the touch properties */
jim@4640
   117
    length = 0;
jim@4640
   118
    length = SDL_strlen(name);
jim@4641
   119
    SDL_touchPads[index]->focus = 0;
jim@4641
   120
    SDL_touchPads[index]->name = SDL_malloc((length + 2) * sizeof(char));
jim@4641
   121
    SDL_strlcpy(SDL_touchPads[index]->name, name, length + 1);
jim@4641
   122
    SDL_touchPads[index]->pressure_max = pressure_max;
jim@4641
   123
    SDL_touchPads[index]->pressure_min = pressure_min;
jim@4641
   124
    
jim@4640
   125
jim@4640
   126
    return index;
jim@4640
   127
}
jim@4640
   128
jim@4640
   129
void
jim@4641
   130
SDL_DelTouch(int id)
jim@4640
   131
{
jim@4641
   132
    int index = SDL_GetTouchIndexId(id);
jim@4641
   133
    SDL_Touch *touch = SDL_GetTouch(id);
jim@4640
   134
jim@4640
   135
    if (!touch) {
jim@4640
   136
        return;
jim@4640
   137
    }
jim@4640
   138
jim@4641
   139
    
jim@4640
   140
    SDL_free(touch->name);
jim@4640
   141
 
jim@4640
   142
    if (touch->FreeTouch) {
jim@4640
   143
        touch->FreeTouch(touch);
jim@4640
   144
    }
jim@4640
   145
    SDL_free(touch);
jim@4640
   146
jim@4641
   147
    SDL_num_touch--;
jim@4641
   148
    SDL_touchPads[index] = SDL_touchPads[SDL_num_touch];
jim@4640
   149
}
jim@4640
   150
jim@4640
   151
void
jim@4640
   152
SDL_TouchQuit(void)
jim@4640
   153
{
jim@4640
   154
    int i;
jim@4640
   155
jim@4641
   156
    for (i = SDL_num_touch-1; i > 0 ; --i) {
jim@4640
   157
        SDL_DelTouch(i);
jim@4640
   158
    }
jim@4640
   159
    SDL_num_touch = 0;
jim@4640
   160
jim@4641
   161
    if (SDL_touchPads) {
jim@4641
   162
        SDL_free(SDL_touchPads);
jim@4641
   163
        SDL_touchPads = NULL;
jim@4640
   164
    }
jim@4640
   165
}
jim@4640
   166
jim@4640
   167
int
jim@4640
   168
SDL_GetNumTouch(void)
jim@4640
   169
{
jim@4640
   170
    return SDL_num_touch;
jim@4640
   171
}
jim@4641
   172
SDL_Window *
jim@4641
   173
SDL_GetTouchFocusWindow(int id)
jim@4640
   174
{
jim@4641
   175
    SDL_Touch *touch = SDL_GetTouch(id);
jim@4640
   176
jim@4640
   177
    if (!touch) {
jim@4640
   178
        return 0;
jim@4640
   179
    }
jim@4640
   180
    return touch->focus;
jim@4640
   181
}
jim@4640
   182
jim@4640
   183
void
jim@4640
   184
SDL_SetTouchFocus(int id, SDL_Window * window)
jim@4640
   185
{
jim@4640
   186
    int index = SDL_GetTouchIndexId(id);
jim@4641
   187
    SDL_Touch *touch = SDL_GetTouch(id);
jim@4640
   188
    int i;
jim@4640
   189
    SDL_bool focus;
jim@4640
   190
jim@4640
   191
    if (!touch || (touch->focus == window)) {
jim@4640
   192
        return;
jim@4640
   193
    }
jim@4640
   194
jim@4640
   195
    /* See if the current window has lost focus */
jim@4640
   196
    if (touch->focus) {
jim@4640
   197
        focus = SDL_FALSE;
jim@4640
   198
        for (i = 0; i < SDL_num_touch; ++i) {
jim@4640
   199
            SDL_Touch *check;
jim@4640
   200
            if (i != index) {
jim@4641
   201
                check = SDL_touchPads[i];
jim@4640
   202
                if (check && check->focus == touch->focus) {
jim@4640
   203
                    focus = SDL_TRUE;
jim@4640
   204
                    break;
jim@4640
   205
                }
jim@4640
   206
            }
jim@4640
   207
        }
jim@4640
   208
        if (!focus) {
jim@4640
   209
            SDL_SendWindowEvent(touch->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
jim@4640
   210
        }
jim@4640
   211
    }
jim@4640
   212
jim@4640
   213
    touch->focus = window;
jim@4640
   214
jim@4640
   215
    if (touch->focus) {
jim@4640
   216
        focus = SDL_FALSE;
jim@4640
   217
        for (i = 0; i < SDL_num_touch; ++i) {
jim@4640
   218
            SDL_Touch *check;
jim@4640
   219
            if (i != index) {
jim@4641
   220
                check = SDL_touchPads[i];
jim@4640
   221
                if (check && check->focus == touch->focus) {
jim@4640
   222
                    focus = SDL_TRUE;
jim@4640
   223
                    break;
jim@4640
   224
                }
jim@4640
   225
            }
jim@4640
   226
        }
jim@4640
   227
        if (!focus) {
jim@4640
   228
            SDL_SendWindowEvent(touch->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
jim@4640
   229
        }
jim@4640
   230
    }
jim@4640
   231
}
jim@4640
   232
jim@4641
   233
int 
jim@4641
   234
SDL_AddFinger(SDL_Touch* touch,SDL_Finger* finger)
jim@4640
   235
{
jim@4641
   236
    int index;
jim@4641
   237
    SDL_Finger **fingers;
jim@4641
   238
    size_t length;
jim@4641
   239
    
jim@4641
   240
    if (SDL_GetFingerIndexId(touch,finger->id) != -1) {
jim@4641
   241
        SDL_SetError("Finger ID already in use");
jim@4640
   242
    }
jim@4640
   243
jim@4641
   244
    /* Add the touch to the list of touch */
jim@4641
   245
    fingers = (SDL_Finger **) SDL_realloc(touch->fingers,
jim@4641
   246
					  (touch->num_fingers + 1) * sizeof(*touch));
jim@4641
   247
    if (!fingers) {
jim@4641
   248
        SDL_OutOfMemory();
jim@4641
   249
        return -1;
jim@4640
   250
    }
jim@4641
   251
jim@4641
   252
    touch->fingers = fingers;
jim@4641
   253
    index = SDL_num_touch++;
jim@4641
   254
jim@4641
   255
    touch->fingers[index] = (SDL_Finger *) SDL_malloc(sizeof(*(touch->fingers[index])));
jim@4641
   256
    if (!touch->fingers[index]) {
jim@4641
   257
        SDL_OutOfMemory();
jim@4641
   258
        return -1;
jim@4641
   259
    }
jim@4641
   260
    *touch->fingers[index] = *finger;    
jim@4641
   261
jim@4641
   262
    return index;
jim@4640
   263
}
jim@4640
   264
jim@4640
   265
int
jim@4641
   266
SDL_DelFinger(SDL_Touch* touch,int fingerid)
jim@4641
   267
{
jim@4641
   268
    int index = SLD_GetFingerIndexId(touch,fingerid);
jim@4641
   269
    SDL_Finger* finger = SDL_GetFinger(touch,fingerid);
jim@4641
   270
jim@4641
   271
    if (!finger) {
jim@4641
   272
        return;
jim@4641
   273
    }
jim@4641
   274
 
jim@4641
   275
jim@4641
   276
    SDL_free(finger);
jim@4641
   277
    touch->num_fingers--;
jim@4641
   278
    touch->fingers[index] = touch->fingers[touch->num_fingers];
jim@4641
   279
}
jim@4641
   280
jim@4641
   281
jim@4641
   282
int
jim@4641
   283
SDL_SendFingerDown(int id, int fingerid, SDL_bool down, int x, int y, int pressure)
jim@4641
   284
{
jim@4641
   285
    SDL_Touch* touch = SDL_GetTouch(id);
jim@4641
   286
    if(down) {
jim@4641
   287
	SDL_Finger nf;
jim@4641
   288
	nf.id = id;
jim@4641
   289
	nf.x = x;
jim@4641
   290
	nf.y = y;
jim@4641
   291
	nf.pressure = pressure;
jim@4641
   292
	nf.xdelta = 0;
jim@4641
   293
	nf.ydelta = 0;
jim@4641
   294
	nf.last_x = x;
jim@4641
   295
	nf.last_y = y;
jim@4641
   296
	SDL_AddFinger(touch,&nf);
jim@4641
   297
jim@4641
   298
	posted = 0;
jim@4641
   299
	if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
jim@4641
   300
	    SDL_Event event;
jim@4641
   301
	    event.tfinger.type = SDL_FINGERDOWN;
jim@4641
   302
	    event.tfinger.touchId = (Uint8) id;
jim@4641
   303
	    event.tfinger.state = touch->buttonstate;
jim@4641
   304
	    event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
jim@4641
   305
	    event.fingerId = id;
jim@4641
   306
	    posted = (SDL_PushEvent(&event) > 0);
jim@4641
   307
	}
jim@4641
   308
	return posted;
jim@4641
   309
    }
jim@4641
   310
    else {
jim@4641
   311
	SDL_DelFinger(touch,id);
jim@4641
   312
	posted = 0;
jim@4641
   313
	if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
jim@4641
   314
	    SDL_Event event;
jim@4641
   315
	    event.tfinger.type = SDL_FINGERUP;
jim@4641
   316
	    event.tfinger.touchId = (Uint8) id;
jim@4641
   317
	    event.tfinger.state = touch->buttonstate;
jim@4641
   318
	    event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
jim@4641
   319
	    event.fingerId = id;
jim@4641
   320
	    posted = (SDL_PushEvent(&event) > 0);
jim@4641
   321
	}
jim@4641
   322
	return posted;
jim@4641
   323
    }
jim@4641
   324
}
jim@4641
   325
jim@4641
   326
int
jim@4641
   327
SDL_SendTouchMotion(int id, int fingerid, int relative, 
jim@4641
   328
		    int x, int y, int pressure)
jim@4640
   329
{
jim@4640
   330
    int index = SDL_GetTouchIndexId(id);
jim@4641
   331
    SDL_Touch *touch = SDL_GetTouch(id);
jim@4641
   332
    SDL_Finger *finger = SDL_GetFinger(touch,fingerid);
jim@4640
   333
    int posted;
jim@4640
   334
    int xrel;
jim@4640
   335
    int yrel;
jim@4640
   336
    int x_max = 0, y_max = 0;
jim@4640
   337
jim@4640
   338
    if (!touch || touch->flush_motion) {
jim@4640
   339
        return 0;
jim@4640
   340
    }
jim@4640
   341
jim@4640
   342
    /* the relative motion is calculated regarding the system cursor last position */
jim@4640
   343
    if (relative) {
jim@4640
   344
        xrel = x;
jim@4640
   345
        yrel = y;
jim@4641
   346
        x = (finger->last_x + x);
jim@4641
   347
        y = (finger->last_y + y);
jim@4640
   348
    } else {
jim@4641
   349
        xrel = x - finger->last_x;
jim@4641
   350
        yrel = y - finger->last_y;
jim@4640
   351
    }
jim@4640
   352
jim@4640
   353
    /* Drop events that don't change state */
jim@4640
   354
    if (!xrel && !yrel) {
jim@4640
   355
#if 0
jim@4640
   356
        printf("Touch event didn't change state - dropped!\n");
jim@4640
   357
#endif
jim@4640
   358
        return 0;
jim@4640
   359
    }
jim@4640
   360
jim@4640
   361
    /* Update internal touch coordinates */
jim@4640
   362
jim@4641
   363
    finger->x = x;
jim@4641
   364
    finger->y = y;
jim@4641
   365
jim@4641
   366
    /*Should scale to window? Normalize? Maintain Aspect?*/
jim@4641
   367
    //SDL_GetWindowSize(touch->focus, &x_max, &y_max);
jim@4640
   368
jim@4640
   369
    /* make sure that the pointers find themselves inside the windows */
jim@4640
   370
    /* only check if touch->xmax is set ! */
jim@4641
   371
    /*
jim@4640
   372
    if (x_max && touch->x > x_max) {
jim@4640
   373
        touch->x = x_max;
jim@4640
   374
    } else if (touch->x < 0) {
jim@4640
   375
        touch->x = 0;
jim@4640
   376
    }
jim@4640
   377
jim@4640
   378
    if (y_max && touch->y > y_max) {
jim@4640
   379
        touch->y = y_max;
jim@4640
   380
    } else if (touch->y < 0) {
jim@4640
   381
        touch->y = 0;
jim@4640
   382
    }
jim@4641
   383
    */
jim@4641
   384
    finger->xdelta += xrel;
jim@4641
   385
    finger->ydelta += yrel;
jim@4641
   386
    finger->pressure = pressure;
jim@4640
   387
jim@4640
   388
jim@4640
   389
jim@4640
   390
    /* Post the event, if desired */
jim@4640
   391
    posted = 0;
jim@4641
   392
    if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) {
jim@4640
   393
        SDL_Event event;
jim@4641
   394
        event.tfinger.type = SDL_FINGERMOTION;
jim@4641
   395
        event.tfinger.which = (Uint8) index;
jim@4641
   396
        event.tfinger.state = touch->buttonstate;
jim@4641
   397
        event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
jim@4640
   398
        posted = (SDL_PushEvent(&event) > 0);
jim@4640
   399
    }
jim@4641
   400
    finger->last_x = finger->x;
jim@4641
   401
    finger->last_y = finger->y;
jim@4640
   402
    return posted;
jim@4640
   403
}
jim@4640
   404
jim@4640
   405
int
jim@4640
   406
SDL_SendTouchButton(int id, Uint8 state, Uint8 button)
jim@4640
   407
{
jim@4641
   408
    SDL_Touch *touch = SDL_GetTouch(id);
jim@4640
   409
    int posted;
jim@4640
   410
    Uint32 type;
jim@4640
   411
jim@4640
   412
    if (!touch) {
jim@4640
   413
        return 0;
jim@4640
   414
    }
jim@4640
   415
jim@4640
   416
    /* Figure out which event to perform */
jim@4640
   417
    switch (state) {
jim@4640
   418
    case SDL_PRESSED:
jim@4640
   419
        if (touch->buttonstate & SDL_BUTTON(button)) {
jim@4640
   420
            /* Ignore this event, no state change */
jim@4640
   421
            return 0;
jim@4640
   422
        }
jim@4640
   423
        type = SDL_TOUCHBUTTONDOWN;
jim@4640
   424
        touch->buttonstate |= SDL_BUTTON(button);
jim@4640
   425
        break;
jim@4640
   426
    case SDL_RELEASED:
jim@4640
   427
        if (!(touch->buttonstate & SDL_BUTTON(button))) {
jim@4640
   428
            /* Ignore this event, no state change */
jim@4640
   429
            return 0;
jim@4640
   430
        }
jim@4640
   431
        type = SDL_TOUCHBUTTONUP;
jim@4640
   432
        touch->buttonstate &= ~SDL_BUTTON(button);
jim@4640
   433
        break;
jim@4640
   434
    default:
jim@4640
   435
        /* Invalid state -- bail */
jim@4640
   436
        return 0;
jim@4640
   437
    }
jim@4640
   438
jim@4640
   439
    /* Post the event, if desired */
jim@4640
   440
    posted = 0;
jim@4640
   441
    if (SDL_GetEventState(type) == SDL_ENABLE) {
jim@4640
   442
        SDL_Event event;
jim@4640
   443
        event.type = type;
jim@4641
   444
        event.tbutton.which = (Uint8) index;
jim@4641
   445
        event.tbutton.state = state;
jim@4641
   446
        event.tbutton.button = button;
jim@4641
   447
        event.tbutton.windowID = touch->focus ? touch->focus->id : 0;
jim@4640
   448
        posted = (SDL_PushEvent(&event) > 0);
jim@4640
   449
    }
jim@4640
   450
    return posted;
jim@4640
   451
}
jim@4640
   452
jim@4641
   453
char *
jim@4641
   454
SDL_GetTouchName(int id)
jim@4640
   455
{
jim@4641
   456
    SDL_Touch *touch = SDL_GetTouch(id);
jim@4640
   457
    if (!touch) {
jim@4640
   458
        return NULL;
jim@4640
   459
    }
jim@4640
   460
    return touch->name;
jim@4640
   461
}
jim@4640
   462
jim@4640
   463
/* vi: set ts=4 sw=4 expandtab: */