parent 971b278f0756 author Edward Rudd <urkle@outoforder.cc> 1358022907 18000 committer Edward Rudd <urkle@outoforder.cc> 1358022907 18000 revision 6819 branch default Remove some redundant assigns
573 lines
16 KiB
C
573 lines
16 KiB
C
/*
|
|
Simple DirectMedia Layer
|
|
Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
warranty. In no event will the authors be held liable for any damages
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it
|
|
freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
claim that you wrote the original software. If you use this software
|
|
in a product, an acknowledgment in the product documentation would be
|
|
appreciated but is not required.
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
misrepresented as being the original software.
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
*/
|
|
#include "SDL_config.h"
|
|
|
|
/* General touch handling code for SDL */
|
|
|
|
#include "SDL_events.h"
|
|
#include "SDL_events_c.h"
|
|
#include "../video/SDL_sysvideo.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
static int SDL_num_touch = 0;
|
|
static SDL_Touch **SDL_touchPads = NULL;
|
|
|
|
|
|
/* Public functions */
|
|
int
|
|
SDL_TouchInit(void)
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
SDL_Touch *
|
|
SDL_GetTouch(SDL_TouchID id)
|
|
{
|
|
int index = SDL_GetTouchIndexId(id);
|
|
if (index < 0 || index >= SDL_num_touch) {
|
|
return NULL;
|
|
}
|
|
return SDL_touchPads[index];
|
|
}
|
|
|
|
SDL_Touch *
|
|
SDL_GetTouchIndex(int index)
|
|
{
|
|
if (index < 0 || index >= SDL_num_touch) {
|
|
return NULL;
|
|
}
|
|
return SDL_touchPads[index];
|
|
}
|
|
|
|
static int
|
|
SDL_GetFingerIndexId(SDL_Touch* touch,SDL_FingerID fingerid)
|
|
{
|
|
int i;
|
|
for(i = 0;i < touch->num_fingers;i++)
|
|
if(touch->fingers[i]->id == fingerid)
|
|
return i;
|
|
return -1;
|
|
}
|
|
|
|
|
|
SDL_Finger *
|
|
SDL_GetFinger(SDL_Touch* touch,SDL_FingerID id)
|
|
{
|
|
int index = SDL_GetFingerIndexId(touch,id);
|
|
if(index < 0 || index >= touch->num_fingers)
|
|
return NULL;
|
|
return touch->fingers[index];
|
|
}
|
|
|
|
|
|
int
|
|
SDL_GetTouchIndexId(SDL_TouchID id)
|
|
{
|
|
int index;
|
|
SDL_Touch *touch;
|
|
|
|
for (index = 0; index < SDL_num_touch; ++index) {
|
|
touch = SDL_touchPads[index];
|
|
if (touch->id == id) {
|
|
return index;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int
|
|
SDL_AddTouch(const SDL_Touch * touch, char *name)
|
|
{
|
|
SDL_Touch **touchPads;
|
|
int index;
|
|
size_t length;
|
|
|
|
if (SDL_GetTouchIndexId(touch->id) != -1) {
|
|
SDL_SetError("Touch ID already in use");
|
|
}
|
|
|
|
/* Add the touch to the list of touch */
|
|
touchPads = (SDL_Touch **) SDL_realloc(SDL_touchPads,
|
|
(SDL_num_touch + 1) * sizeof(*touch));
|
|
if (!touchPads) {
|
|
SDL_OutOfMemory();
|
|
return -1;
|
|
}
|
|
|
|
SDL_touchPads = touchPads;
|
|
index = SDL_num_touch++;
|
|
|
|
SDL_touchPads[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touchPads[index]));
|
|
if (!SDL_touchPads[index]) {
|
|
SDL_OutOfMemory();
|
|
return -1;
|
|
}
|
|
SDL_memcpy(SDL_touchPads[index], touch, sizeof(*touch));
|
|
|
|
/* we're setting the touch properties */
|
|
length = SDL_strlen(name);
|
|
SDL_touchPads[index]->focus = 0;
|
|
SDL_touchPads[index]->name = SDL_malloc((length + 2) * sizeof(char));
|
|
SDL_strlcpy(SDL_touchPads[index]->name, name, length + 1);
|
|
|
|
SDL_touchPads[index]->num_fingers = 0;
|
|
SDL_touchPads[index]->max_fingers = 1;
|
|
SDL_touchPads[index]->fingers = (SDL_Finger **) SDL_malloc(sizeof(SDL_Finger*));
|
|
SDL_touchPads[index]->fingers[0] = NULL;
|
|
SDL_touchPads[index]->buttonstate = 0;
|
|
SDL_touchPads[index]->relative_mode = SDL_FALSE;
|
|
SDL_touchPads[index]->flush_motion = SDL_FALSE;
|
|
|
|
SDL_touchPads[index]->xres = (1<<(16-1));
|
|
SDL_touchPads[index]->yres = (1<<(16-1));
|
|
SDL_touchPads[index]->pressureres = (1<<(16-1));
|
|
//Do I want this here? Probably
|
|
SDL_GestureAddTouch(SDL_touchPads[index]);
|
|
|
|
return index;
|
|
}
|
|
|
|
void
|
|
SDL_DelTouch(SDL_TouchID id)
|
|
{
|
|
int index = SDL_GetTouchIndexId(id);
|
|
SDL_Touch *touch = SDL_GetTouch(id);
|
|
|
|
if (!touch) {
|
|
return;
|
|
}
|
|
|
|
|
|
SDL_free(touch->name);
|
|
|
|
if (touch->FreeTouch) {
|
|
touch->FreeTouch(touch);
|
|
}
|
|
SDL_free(touch);
|
|
|
|
SDL_num_touch--;
|
|
SDL_touchPads[index] = SDL_touchPads[SDL_num_touch];
|
|
}
|
|
|
|
void
|
|
SDL_TouchQuit(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = SDL_num_touch-1; i > 0 ; --i) {
|
|
SDL_DelTouch(i);
|
|
}
|
|
SDL_num_touch = 0;
|
|
|
|
if (SDL_touchPads) {
|
|
SDL_free(SDL_touchPads);
|
|
SDL_touchPads = NULL;
|
|
}
|
|
}
|
|
|
|
int
|
|
SDL_GetNumTouch(void)
|
|
{
|
|
return SDL_num_touch;
|
|
}
|
|
|
|
SDL_Window *
|
|
SDL_GetTouchFocusWindow(SDL_TouchID id)
|
|
{
|
|
SDL_Touch *touch = SDL_GetTouch(id);
|
|
|
|
if (!touch) {
|
|
return 0;
|
|
}
|
|
return touch->focus;
|
|
}
|
|
|
|
void
|
|
SDL_SetTouchFocus(SDL_TouchID id, SDL_Window * window)
|
|
{
|
|
int index = SDL_GetTouchIndexId(id);
|
|
SDL_Touch *touch = SDL_GetTouch(id);
|
|
int i;
|
|
SDL_bool focus;
|
|
|
|
if (!touch || (touch->focus == window)) {
|
|
return;
|
|
}
|
|
|
|
/* See if the current window has lost focus */
|
|
if (touch->focus) {
|
|
focus = SDL_FALSE;
|
|
for (i = 0; i < SDL_num_touch; ++i) {
|
|
SDL_Touch *check;
|
|
if (i != index) {
|
|
check = SDL_touchPads[i];
|
|
if (check && check->focus == touch->focus) {
|
|
focus = SDL_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!focus) {
|
|
SDL_SendWindowEvent(touch->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
|
|
}
|
|
}
|
|
|
|
touch->focus = window;
|
|
|
|
if (touch->focus) {
|
|
focus = SDL_FALSE;
|
|
for (i = 0; i < SDL_num_touch; ++i) {
|
|
SDL_Touch *check;
|
|
if (i != index) {
|
|
check = SDL_touchPads[i];
|
|
if (check && check->focus == touch->focus) {
|
|
focus = SDL_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!focus) {
|
|
SDL_SendWindowEvent(touch->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
SDL_AddFinger(SDL_Touch* touch,SDL_Finger *finger)
|
|
{
|
|
int index;
|
|
SDL_Finger **fingers;
|
|
//printf("Adding Finger...\n");
|
|
if (SDL_GetFingerIndexId(touch,finger->id) != -1) {
|
|
SDL_SetError("Finger ID already in use");
|
|
}
|
|
|
|
/* Add the touch to the list of touch */
|
|
if(touch->num_fingers >= touch->max_fingers){
|
|
//printf("Making room for it!\n");
|
|
fingers = (SDL_Finger **) SDL_realloc(touch->fingers,
|
|
(touch->num_fingers + 1) * sizeof(SDL_Finger *));
|
|
if (!fingers) {
|
|
SDL_OutOfMemory();
|
|
return -1;
|
|
} else {
|
|
touch->max_fingers = touch->num_fingers+1;
|
|
touch->fingers = fingers;
|
|
}
|
|
}
|
|
|
|
index = touch->num_fingers;
|
|
//printf("Max_Fingers: %i Index: %i\n",touch->max_fingers,index);
|
|
|
|
touch->fingers[index] = (SDL_Finger *) SDL_malloc(sizeof(SDL_Finger));
|
|
if (!touch->fingers[index]) {
|
|
SDL_OutOfMemory();
|
|
return -1;
|
|
}
|
|
*(touch->fingers[index]) = *finger;
|
|
touch->num_fingers++;
|
|
|
|
return index;
|
|
}
|
|
|
|
int
|
|
SDL_DelFinger(SDL_Touch* touch,SDL_FingerID fingerid)
|
|
{
|
|
int index = SDL_GetFingerIndexId(touch,fingerid);
|
|
SDL_Finger* finger = SDL_GetFinger(touch,fingerid);
|
|
|
|
if (!finger) {
|
|
return -1;
|
|
}
|
|
|
|
|
|
SDL_free(finger);
|
|
touch->num_fingers--;
|
|
touch->fingers[index] = touch->fingers[touch->num_fingers];
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
SDL_SendFingerDown(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down,
|
|
float xin, float yin, float pressurein)
|
|
{
|
|
int posted;
|
|
Uint16 x;
|
|
Uint16 y;
|
|
Uint16 pressure;
|
|
SDL_Finger *finger;
|
|
|
|
SDL_Touch* touch = SDL_GetTouch(id);
|
|
|
|
if(!touch) {
|
|
return SDL_TouchNotFoundError(id);
|
|
}
|
|
|
|
|
|
//scale to Integer coordinates
|
|
x = (Uint16)((xin+touch->x_min)*(touch->xres)/(touch->native_xres));
|
|
y = (Uint16)((yin+touch->y_min)*(touch->yres)/(touch->native_yres));
|
|
pressure = (Uint16)((pressurein+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres));
|
|
|
|
finger = SDL_GetFinger(touch,fingerid);
|
|
if(down) {
|
|
if(finger == NULL) {
|
|
SDL_Finger nf;
|
|
nf.id = fingerid;
|
|
nf.x = x;
|
|
nf.y = y;
|
|
nf.pressure = pressure;
|
|
nf.xdelta = 0;
|
|
nf.ydelta = 0;
|
|
nf.last_x = x;
|
|
nf.last_y = y;
|
|
nf.last_pressure = pressure;
|
|
nf.down = SDL_FALSE;
|
|
if(SDL_AddFinger(touch,&nf) < 0) return 0;
|
|
finger = SDL_GetFinger(touch,fingerid);
|
|
}
|
|
else if(finger->down) return 0;
|
|
if(xin < touch->x_min || yin < touch->y_min) return 0; //should defer if only a partial input
|
|
posted = 0;
|
|
if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
|
|
SDL_Event event;
|
|
event.tfinger.type = SDL_FINGERDOWN;
|
|
event.tfinger.touchId = id;
|
|
event.tfinger.x = x;
|
|
event.tfinger.y = y;
|
|
event.tfinger.dx = 0;
|
|
event.tfinger.dy = 0;
|
|
event.tfinger.pressure = pressure;
|
|
event.tfinger.state = touch->buttonstate;
|
|
event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
|
|
event.tfinger.fingerId = fingerid;
|
|
posted = (SDL_PushEvent(&event) > 0);
|
|
}
|
|
if(posted) finger->down = SDL_TRUE;
|
|
return posted;
|
|
}
|
|
else {
|
|
if(finger == NULL) {
|
|
SDL_SetError("Finger not found.");
|
|
return 0;
|
|
}
|
|
posted = 0;
|
|
if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
|
|
SDL_Event event;
|
|
event.tfinger.type = SDL_FINGERUP;
|
|
event.tfinger.touchId = id;
|
|
event.tfinger.state = touch->buttonstate;
|
|
event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
|
|
event.tfinger.fingerId = fingerid;
|
|
//I don't trust the coordinates passed on fingerUp
|
|
event.tfinger.x = finger->x;
|
|
event.tfinger.y = finger->y;
|
|
event.tfinger.dx = 0;
|
|
event.tfinger.dy = 0;
|
|
event.tfinger.pressure = pressure;
|
|
|
|
if(SDL_DelFinger(touch,fingerid) < 0) return 0;
|
|
posted = (SDL_PushEvent(&event) > 0);
|
|
}
|
|
return posted;
|
|
}
|
|
}
|
|
|
|
int
|
|
SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, int relative,
|
|
float xin, float yin, float pressurein)
|
|
{
|
|
SDL_Touch *touch;
|
|
SDL_Finger *finger;
|
|
int posted;
|
|
Sint16 xrel, yrel;
|
|
Uint16 x;
|
|
Uint16 y;
|
|
Uint16 pressure;
|
|
|
|
touch = SDL_GetTouch(id);
|
|
if (!touch) {
|
|
return SDL_TouchNotFoundError(id);
|
|
}
|
|
|
|
//scale to Integer coordinates
|
|
x = (Uint16)((xin+touch->x_min)*(touch->xres)/(touch->native_xres));
|
|
y = (Uint16)((yin+touch->y_min)*(touch->yres)/(touch->native_yres));
|
|
pressure = (Uint16)((pressurein+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres));
|
|
if(touch->flush_motion) {
|
|
return 0;
|
|
}
|
|
|
|
finger = SDL_GetFinger(touch,fingerid);
|
|
if(finger == NULL || !finger->down) {
|
|
return SDL_SendFingerDown(id,fingerid,SDL_TRUE,xin,yin,pressurein);
|
|
} else {
|
|
/* the relative motion is calculated regarding the last position */
|
|
if (relative) {
|
|
xrel = x;
|
|
yrel = y;
|
|
x = (finger->last_x + x);
|
|
y = (finger->last_y + y);
|
|
} else {
|
|
if(xin < touch->x_min) x = finger->last_x; /*If movement is only in one axis,*/
|
|
if(yin < touch->y_min) y = finger->last_y; /*The other is marked as -1*/
|
|
if(pressurein < touch->pressure_min) pressure = finger->last_pressure;
|
|
xrel = x - finger->last_x;
|
|
yrel = y - finger->last_y;
|
|
//printf("xrel,yrel (%i,%i)\n",(int)xrel,(int)yrel);
|
|
}
|
|
|
|
/* Drop events that don't change state */
|
|
if (!xrel && !yrel) {
|
|
#if 0
|
|
printf("Touch event didn't change state - dropped!\n");
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/* Update internal touch coordinates */
|
|
|
|
finger->x = x;
|
|
finger->y = y;
|
|
|
|
/*Should scale to window? Normalize? Maintain Aspect?*/
|
|
//SDL_GetWindowSize(touch->focus, &x_max, &y_max);
|
|
|
|
/* make sure that the pointers find themselves inside the windows */
|
|
/* only check if touch->xmax is set ! */
|
|
/*
|
|
if (x_max && touch->x > x_max) {
|
|
touch->x = x_max;
|
|
} else if (touch->x < 0) {
|
|
touch->x = 0;
|
|
}
|
|
|
|
if (y_max && touch->y > y_max) {
|
|
touch->y = y_max;
|
|
} else if (touch->y < 0) {
|
|
touch->y = 0;
|
|
}
|
|
*/
|
|
finger->xdelta = xrel;
|
|
finger->ydelta = yrel;
|
|
finger->pressure = pressure;
|
|
|
|
|
|
|
|
/* Post the event, if desired */
|
|
posted = 0;
|
|
if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) {
|
|
SDL_Event event;
|
|
event.tfinger.type = SDL_FINGERMOTION;
|
|
event.tfinger.touchId = id;
|
|
event.tfinger.fingerId = fingerid;
|
|
event.tfinger.x = x;
|
|
event.tfinger.y = y;
|
|
event.tfinger.dx = xrel;
|
|
event.tfinger.dy = yrel;
|
|
|
|
event.tfinger.pressure = pressure;
|
|
event.tfinger.state = touch->buttonstate;
|
|
event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
|
|
posted = (SDL_PushEvent(&event) > 0);
|
|
}
|
|
finger->last_x = finger->x;
|
|
finger->last_y = finger->y;
|
|
finger->last_pressure = finger->pressure;
|
|
return posted;
|
|
}
|
|
}
|
|
|
|
int
|
|
SDL_SendTouchButton(SDL_TouchID id, Uint8 state, Uint8 button)
|
|
{
|
|
SDL_Touch *touch;
|
|
int posted;
|
|
Uint32 type;
|
|
|
|
|
|
touch = SDL_GetTouch(id);
|
|
if (!touch) {
|
|
return SDL_TouchNotFoundError(id);
|
|
}
|
|
|
|
/* Figure out which event to perform */
|
|
switch (state) {
|
|
case SDL_PRESSED:
|
|
if (touch->buttonstate & SDL_BUTTON(button)) {
|
|
/* Ignore this event, no state change */
|
|
return 0;
|
|
}
|
|
type = SDL_TOUCHBUTTONDOWN;
|
|
touch->buttonstate |= SDL_BUTTON(button);
|
|
break;
|
|
case SDL_RELEASED:
|
|
if (!(touch->buttonstate & SDL_BUTTON(button))) {
|
|
/* Ignore this event, no state change */
|
|
return 0;
|
|
}
|
|
type = SDL_TOUCHBUTTONUP;
|
|
touch->buttonstate &= ~SDL_BUTTON(button);
|
|
break;
|
|
default:
|
|
/* Invalid state -- bail */
|
|
return 0;
|
|
}
|
|
|
|
/* Post the event, if desired */
|
|
posted = 0;
|
|
if (SDL_GetEventState(type) == SDL_ENABLE) {
|
|
SDL_Event event;
|
|
event.type = type;
|
|
event.tbutton.touchId = touch->id;
|
|
event.tbutton.state = state;
|
|
event.tbutton.button = button;
|
|
event.tbutton.windowID = touch->focus ? touch->focus->id : 0;
|
|
posted = (SDL_PushEvent(&event) > 0);
|
|
}
|
|
return posted;
|
|
}
|
|
|
|
char *
|
|
SDL_GetTouchName(SDL_TouchID id)
|
|
{
|
|
SDL_Touch *touch = SDL_GetTouch(id);
|
|
if (!touch) {
|
|
return NULL;
|
|
}
|
|
return touch->name;
|
|
}
|
|
|
|
int SDL_TouchNotFoundError(SDL_TouchID id) {
|
|
//int i;
|
|
SDL_SetError("ERROR: Cannot send touch on non-existent device with id: %li make sure SDL_AddTouch has been called\n",id);
|
|
#if 0
|
|
printf("ERROR: There are %i touches installed with Id's:\n",SDL_num_touch);
|
|
for(i=0;i < SDL_num_touch;i++) {
|
|
printf("ERROR: %li\n",SDL_touchPads[i]->id);
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
/* vi: set ts=4 sw=4 expandtab: */
|