comparison src/events/SDL_touch.c @ 4919:716b2cbf4c9e

First pass at Windows multi-touch gesture support
author Sam Lantinga <slouken@libsdl.org>
date Tue, 30 Nov 2010 17:58:51 -0800
parents d6adaafcfb10
children 8bf5781fc582
comparison
equal deleted inserted replaced
4918:f5f70fed2c4c 4919:716b2cbf4c9e
63 int 63 int
64 SDL_GetFingerIndexId(SDL_Touch* touch,SDL_FingerID fingerid) 64 SDL_GetFingerIndexId(SDL_Touch* touch,SDL_FingerID fingerid)
65 { 65 {
66 int i; 66 int i;
67 for(i = 0;i < touch->num_fingers;i++) 67 for(i = 0;i < touch->num_fingers;i++)
68 if(touch->fingers[i]->id == fingerid) 68 if(touch->fingers[i]->id == fingerid)
69 return i; 69 return i;
70 return -1; 70 return -1;
71 } 71 }
72 72
73 73
74 SDL_Finger * 74 SDL_Finger *
75 SDL_GetFinger(SDL_Touch* touch,SDL_FingerID id) 75 SDL_GetFinger(SDL_Touch* touch,SDL_FingerID id)
76 { 76 {
77 int index = SDL_GetFingerIndexId(touch,id); 77 int index = SDL_GetFingerIndexId(touch,id);
78 if(index < 0 || index >= touch->num_fingers) 78 if(index < 0 || index >= touch->num_fingers)
79 return NULL; 79 return NULL;
80 return touch->fingers[index]; 80 return touch->fingers[index];
81 } 81 }
82 82
83 83
84 int 84 int
257 int index; 257 int index;
258 SDL_Finger **fingers; 258 SDL_Finger **fingers;
259 //printf("Adding Finger...\n"); 259 //printf("Adding Finger...\n");
260 if (SDL_GetFingerIndexId(touch,finger->id) != -1) { 260 if (SDL_GetFingerIndexId(touch,finger->id) != -1) {
261 SDL_SetError("Finger ID already in use"); 261 SDL_SetError("Finger ID already in use");
262 } 262 }
263 263
264 /* Add the touch to the list of touch */ 264 /* Add the touch to the list of touch */
265 if(touch->num_fingers >= touch->max_fingers){ 265 if(touch->num_fingers >= touch->max_fingers){
266 //printf("Making room for it!\n"); 266 //printf("Making room for it!\n");
267 fingers = (SDL_Finger **) SDL_realloc(touch->fingers, 267 fingers = (SDL_Finger **) SDL_realloc(touch->fingers,
268 (touch->num_fingers + 1) * sizeof(SDL_Finger *)); 268 (touch->num_fingers + 1) * sizeof(SDL_Finger *));
269 touch->max_fingers = touch->num_fingers+1; 269 touch->max_fingers = touch->num_fingers+1;
270 if (!fingers) { 270 if (!fingers) {
271 SDL_OutOfMemory(); 271 SDL_OutOfMemory();
272 return -1; 272 return -1;
273 } else { 273 } else {
274 touch->max_fingers = touch->num_fingers+1; 274 touch->max_fingers = touch->num_fingers+1;
275 touch->fingers = fingers; 275 touch->fingers = fingers;
276 } 276 }
277 } 277 }
278 278
279 index = touch->num_fingers; 279 index = touch->num_fingers;
280 //printf("Max_Fingers: %i Index: %i\n",touch->max_fingers,index); 280 //printf("Max_Fingers: %i Index: %i\n",touch->max_fingers,index);
281 281
282 touch->fingers[index] = (SDL_Finger *) SDL_malloc(sizeof(SDL_Finger)); 282 touch->fingers[index] = (SDL_Finger *) SDL_malloc(sizeof(SDL_Finger));
308 } 308 }
309 309
310 310
311 int 311 int
312 SDL_SendFingerDown(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, 312 SDL_SendFingerDown(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down,
313 float xin, float yin, float pressurein) 313 float xin, float yin, float pressurein)
314 { 314 {
315 int posted; 315 int posted;
316 Uint16 x; 316 Uint16 x;
317 Uint16 y; 317 Uint16 y;
318 Uint16 pressure; 318 Uint16 pressure;
319 SDL_Finger *finger; 319 SDL_Finger *finger;
320 320
321 SDL_Touch* touch = SDL_GetTouch(id); 321 SDL_Touch* touch = SDL_GetTouch(id);
322 322
323 if(!touch) { 323 if(!touch) {
324 return SDL_TouchNotFoundError(id); 324 return SDL_TouchNotFoundError(id);
330 y = (Uint16)((yin+touch->y_min)*(touch->yres)/(touch->native_yres)); 330 y = (Uint16)((yin+touch->y_min)*(touch->yres)/(touch->native_yres));
331 pressure = (Uint16)((yin+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres)); 331 pressure = (Uint16)((yin+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres));
332 332
333 finger = SDL_GetFinger(touch,fingerid); 333 finger = SDL_GetFinger(touch,fingerid);
334 if(down) { 334 if(down) {
335 if(finger == NULL) { 335 if(finger == NULL) {
336 SDL_Finger nf; 336 SDL_Finger nf;
337 nf.id = fingerid; 337 nf.id = fingerid;
338 nf.x = x; 338 nf.x = x;
339 nf.y = y; 339 nf.y = y;
340 nf.pressure = pressure; 340 nf.pressure = pressure;
341 nf.xdelta = 0; 341 nf.xdelta = 0;
342 nf.ydelta = 0; 342 nf.ydelta = 0;
343 nf.last_x = x; 343 nf.last_x = x;
344 nf.last_y = y; 344 nf.last_y = y;
345 nf.last_pressure = pressure; 345 nf.last_pressure = pressure;
346 nf.down = SDL_FALSE; 346 nf.down = SDL_FALSE;
347 if(SDL_AddFinger(touch,&nf) < 0) return 0; 347 if(SDL_AddFinger(touch,&nf) < 0) return 0;
348 finger = SDL_GetFinger(touch,fingerid); 348 finger = SDL_GetFinger(touch,fingerid);
349 } 349 }
350 else if(finger->down) return 0; 350 else if(finger->down) return 0;
351 if(xin < touch->x_min || yin < touch->y_min) return 0; //should defer if only a partial input 351 if(xin < touch->x_min || yin < touch->y_min) return 0; //should defer if only a partial input
352 posted = 0; 352 posted = 0;
353 if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) { 353 if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
354 SDL_Event event; 354 SDL_Event event;
355 event.tfinger.type = SDL_FINGERDOWN; 355 event.tfinger.type = SDL_FINGERDOWN;
356 event.tfinger.touchId = id; 356 event.tfinger.touchId = id;
357 event.tfinger.x = x; 357 event.tfinger.x = x;
358 event.tfinger.y = y; 358 event.tfinger.y = y;
359 event.tfinger.pressure = pressure; 359 event.tfinger.pressure = pressure;
360 event.tfinger.state = touch->buttonstate; 360 event.tfinger.state = touch->buttonstate;
361 event.tfinger.windowID = touch->focus ? touch->focus->id : 0; 361 event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
362 event.tfinger.fingerId = fingerid; 362 event.tfinger.fingerId = fingerid;
363 posted = (SDL_PushEvent(&event) > 0); 363 posted = (SDL_PushEvent(&event) > 0);
364 } 364 }
365 if(posted) finger->down = SDL_TRUE; 365 if(posted) finger->down = SDL_TRUE;
366 return posted; 366 return posted;
367 } 367 }
368 else { 368 else {
369 if(finger == NULL) { 369 if(finger == NULL) {
370 SDL_SetError("Finger not found."); 370 SDL_SetError("Finger not found.");
371 return 0; 371 return 0;
372 } 372 }
373 posted = 0; 373 posted = 0;
374 if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) { 374 if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
375 SDL_Event event; 375 SDL_Event event;
376 event.tfinger.type = SDL_FINGERUP; 376 event.tfinger.type = SDL_FINGERUP;
377 event.tfinger.touchId = id; 377 event.tfinger.touchId = id;
378 event.tfinger.state = touch->buttonstate; 378 event.tfinger.state = touch->buttonstate;
379 event.tfinger.windowID = touch->focus ? touch->focus->id : 0; 379 event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
380 event.tfinger.fingerId = fingerid; 380 event.tfinger.fingerId = fingerid;
381 //I don't trust the coordinates passed on fingerUp 381 //I don't trust the coordinates passed on fingerUp
382 event.tfinger.x = finger->x; 382 event.tfinger.x = finger->x;
383 event.tfinger.y = finger->y; 383 event.tfinger.y = finger->y;
384 event.tfinger.dx = 0; 384 event.tfinger.dx = 0;
385 event.tfinger.dy = 0; 385 event.tfinger.dy = 0;
386 386
387 if(SDL_DelFinger(touch,fingerid) < 0) return 0; 387 if(SDL_DelFinger(touch,fingerid) < 0) return 0;
388 posted = (SDL_PushEvent(&event) > 0); 388 posted = (SDL_PushEvent(&event) > 0);
389 } 389 }
390 return posted; 390 return posted;
391 } 391 }
392 } 392 }
393 393
394 int 394 int
395 SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, int relative, 395 SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, int relative,
396 float xin, float yin, float pressurein) 396 float xin, float yin, float pressurein)
397 { 397 {
398 int index = SDL_GetTouchIndexId(id); 398 int index = SDL_GetTouchIndexId(id);
399 SDL_Touch *touch = SDL_GetTouch(id); 399 SDL_Touch *touch = SDL_GetTouch(id);
400 SDL_Finger *finger = SDL_GetFinger(touch,fingerid); 400 SDL_Finger *finger = SDL_GetFinger(touch,fingerid);
401 int posted; 401 int posted;
402 Sint16 xrel, yrel; 402 Sint16 xrel, yrel;
403 float x_max = 0, y_max = 0; 403 float x_max = 0, y_max = 0;
404 Uint16 x; 404 Uint16 x;
405 Uint16 y; 405 Uint16 y;
406 Uint16 pressure; 406 Uint16 pressure;
407 407
408 if (!touch) { 408 if (!touch) {
409 return SDL_TouchNotFoundError(id); 409 return SDL_TouchNotFoundError(id);
410 } 410 }
411 411
412 //scale to Integer coordinates 412 //scale to Integer coordinates
413 x = (Uint16)((xin+touch->x_min)*(touch->xres)/(touch->native_xres)); 413 x = (Uint16)((xin+touch->x_min)*(touch->xres)/(touch->native_xres));
414 y = (Uint16)((yin+touch->y_min)*(touch->yres)/(touch->native_yres)); 414 y = (Uint16)((yin+touch->y_min)*(touch->yres)/(touch->native_yres));
415 pressure = (Uint16)((yin+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres)); 415 pressure = (Uint16)((yin+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres));
416 if(touch->flush_motion) { 416 if(touch->flush_motion) {
417 return 0; 417 return 0;
418 } 418 }
419 419
420 if(finger == NULL || !finger->down) { 420 if(finger == NULL || !finger->down) {
421 return SDL_SendFingerDown(id,fingerid,SDL_TRUE,xin,yin,pressurein); 421 return SDL_SendFingerDown(id,fingerid,SDL_TRUE,xin,yin,pressurein);
422 } else { 422 } else {
423 /* the relative motion is calculated regarding the last position */ 423 /* the relative motion is calculated regarding the last position */
424 if (relative) { 424 if (relative) {
425 xrel = x; 425 xrel = x;
426 yrel = y; 426 yrel = y;
427 x = (finger->last_x + x); 427 x = (finger->last_x + x);
428 y = (finger->last_y + y); 428 y = (finger->last_y + y);
429 } else { 429 } else {
430 if(xin < touch->x_min) x = finger->last_x; /*If movement is only in one axis,*/ 430 if(xin < touch->x_min) x = finger->last_x; /*If movement is only in one axis,*/
431 if(yin < touch->y_min) y = finger->last_y; /*The other is marked as -1*/ 431 if(yin < touch->y_min) y = finger->last_y; /*The other is marked as -1*/
432 if(pressurein < touch->pressure_min) pressure = finger->last_pressure; 432 if(pressurein < touch->pressure_min) pressure = finger->last_pressure;
433 xrel = x - finger->last_x; 433 xrel = x - finger->last_x;
434 yrel = y - finger->last_y; 434 yrel = y - finger->last_y;
435 //printf("xrel,yrel (%i,%i)\n",(int)xrel,(int)yrel); 435 //printf("xrel,yrel (%i,%i)\n",(int)xrel,(int)yrel);
436 } 436 }
437 437
438 /* Drop events that don't change state */ 438 /* Drop events that don't change state */
439 if (!xrel && !yrel) { 439 if (!xrel && !yrel) {
440 #if 0 440 #if 0
441 printf("Touch event didn't change state - dropped!\n"); 441 printf("Touch event didn't change state - dropped!\n");
442 #endif 442 #endif
443 return 0; 443 return 0;
444 } 444 }
445 445
446 /* Update internal touch coordinates */ 446 /* Update internal touch coordinates */
447 447
448 finger->x = x; 448 finger->x = x;
449 finger->y = y; 449 finger->y = y;
450 450
451 /*Should scale to window? Normalize? Maintain Aspect?*/ 451 /*Should scale to window? Normalize? Maintain Aspect?*/
452 //SDL_GetWindowSize(touch->focus, &x_max, &y_max); 452 //SDL_GetWindowSize(touch->focus, &x_max, &y_max);
453 453
454 /* make sure that the pointers find themselves inside the windows */ 454 /* make sure that the pointers find themselves inside the windows */
455 /* only check if touch->xmax is set ! */ 455 /* only check if touch->xmax is set ! */
456 /* 456 /*
457 if (x_max && touch->x > x_max) { 457 if (x_max && touch->x > x_max) {
458 touch->x = x_max; 458 touch->x = x_max;
459 } else if (touch->x < 0) { 459 } else if (touch->x < 0) {
460 touch->x = 0; 460 touch->x = 0;
461 } 461 }
462 462
463 if (y_max && touch->y > y_max) { 463 if (y_max && touch->y > y_max) {
464 touch->y = y_max; 464 touch->y = y_max;
465 } else if (touch->y < 0) { 465 } else if (touch->y < 0) {
466 touch->y = 0; 466 touch->y = 0;
467 } 467 }
468 */ 468 */
469 finger->xdelta = xrel; 469 finger->xdelta = xrel;
470 finger->ydelta = yrel; 470 finger->ydelta = yrel;
471 finger->pressure = pressure; 471 finger->pressure = pressure;
472 472
473 473
474 474
475 /* Post the event, if desired */ 475 /* Post the event, if desired */
476 posted = 0; 476 posted = 0;
477 if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) { 477 if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) {
478 SDL_Event event; 478 SDL_Event event;
479 event.tfinger.type = SDL_FINGERMOTION; 479 event.tfinger.type = SDL_FINGERMOTION;
480 event.tfinger.touchId = id; 480 event.tfinger.touchId = id;
481 event.tfinger.fingerId = fingerid; 481 event.tfinger.fingerId = fingerid;
482 event.tfinger.x = x; 482 event.tfinger.x = x;
483 event.tfinger.y = y; 483 event.tfinger.y = y;
484 event.tfinger.dx = xrel; 484 event.tfinger.dx = xrel;
485 event.tfinger.dy = yrel; 485 event.tfinger.dy = yrel;
486 486
487 event.tfinger.pressure = pressure; 487 event.tfinger.pressure = pressure;
488 event.tfinger.state = touch->buttonstate; 488 event.tfinger.state = touch->buttonstate;
489 event.tfinger.windowID = touch->focus ? touch->focus->id : 0; 489 event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
490 posted = (SDL_PushEvent(&event) > 0); 490 posted = (SDL_PushEvent(&event) > 0);
491 } 491 }
492 finger->last_x = finger->x; 492 finger->last_x = finger->x;
493 finger->last_y = finger->y; 493 finger->last_y = finger->y;
494 finger->last_pressure = finger->pressure; 494 finger->last_pressure = finger->pressure;
495 return posted; 495 return posted;
496 } 496 }
497 } 497 }
498 int 498 int
499 SDL_SendTouchButton(SDL_TouchID id, Uint8 state, Uint8 button) 499 SDL_SendTouchButton(SDL_TouchID id, Uint8 state, Uint8 button)
500 { 500 {