Mercurial > sdl-ios-xcode
view src/events/SDL_touch.c @ 4640:f068a6dfc858
Added SDL_touch.c/SDL_touch_c.h as slightly modifeind SDL_mouse*. Made reads in touchSimp non-blocking.
author | Jim Grandpre <jim.tla@gmail.com> |
---|---|
date | Tue, 25 May 2010 23:23:23 -0400 |
parents | |
children | 49a97daea6ec |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2010 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" /* General touch handling code for SDL */ #include "SDL_events.h" #include "SDL_events_c.h" #include "../video/SDL_sysvideo.h" static int SDL_num_touch = 0; static int SDL_current_touch = -1; static SDL_Touch **SDL_touch = NULL; /* Public functions */ int SDL_TouchInit(void) { return (0); } SDL_Touch * SDL_GetTouch(int index) { if (index < 0 || index >= SDL_num_touch) { return NULL; } return SDL_touch[index]; } static int SDL_GetTouchIndexId(int id) { int index; SDL_Touch *touch; for (index = 0; index < SDL_num_touch; ++index) { touch = SDL_GetTouch(index); if (touch->id == id) { return index; } } return -1; } int SDL_AddTouch(const SDL_Touch * touch, char *name, int pressure_max, int pressure_min, int ends) { SDL_Touch **touch; int selected_touch; 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 */ touch = (SDL_Touch **) SDL_realloc(SDL_touch, (SDL_num_touch + 1) * sizeof(*touch)); if (!touch) { SDL_OutOfMemory(); return -1; } SDL_touch = touch; index = SDL_num_touch++; SDL_touch[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touch[index])); if (!SDL_touch[index]) { SDL_OutOfMemory(); return -1; } *SDL_touch[index] = *touch; /* we're setting the touch properties */ length = 0; length = SDL_strlen(name); SDL_touch[index]->focus = 0; SDL_touch[index]->name = SDL_malloc((length + 2) * sizeof(char)); SDL_strlcpy(SDL_touch[index]->name, name, length + 1); SDL_touch[index]->pressure_max = pressure_max; SDL_touch[index]->pressure_min = pressure_min; SDL_touch[index]->cursor_shown = SDL_TRUE; selected_touch = SDL_SelectTouch(index); SDL_touch[index]->cur_cursor = NULL; SDL_touch[index]->def_cursor = /* we're assuming that all touch are in the computer sensing zone */ SDL_touch[index]->proximity = SDL_TRUE; /* we're assuming that all touch are working in the absolute position mode thanx to that, the users that don't want to use many touch don't have to worry about anything */ SDL_touch[index]->relative_mode = SDL_FALSE; SDL_touch[index]->current_end = 0; SDL_touch[index]->total_ends = ends; SDL_SelectTouch(selected_touch); return index; } void SDL_DelTouch(int index) { SDL_Touch *touch = SDL_GetTouch(index); if (!touch) { return; } touch->def_cursor = NULL; SDL_free(touch->name); if (touch->FreeTouch) { touch->FreeTouch(touch); } SDL_free(touch); SDL_touch[index] = NULL; } void SDL_ResetTouch(int index) { SDL_Touch *touch = SDL_GetTouch(index); if (!touch) { return; } /* FIXME */ } void SDL_TouchQuit(void) { int i; for (i = 0; i < SDL_num_touch; ++i) { SDL_DelTouch(i); } SDL_num_touch = 0; SDL_current_touch = -1; if (SDL_touch) { SDL_free(SDL_touch); SDL_touch = NULL; } } int SDL_GetNumTouch(void) { return SDL_num_touch; } int SDL_SelectTouch(int index) { if (index >= 0 && index < SDL_num_touch) { SDL_current_touch = index; } return SDL_current_touch; } SDL_Window * SDL_GetTouchFocusWindow(int index) { SDL_Touch *touch = SDL_GetTouch(index); if (!touch) { return 0; } return touch->focus; } static int SDLCALL FlushTouchMotion(void *param, SDL_Event * event) { if (event->type == SDL_TOUCHMOTION && event->motion.which == (Uint8) SDL_current_touch) { return 0; } else { return 1; } } int SDL_SetRelativeTouchMode(int index, SDL_bool enabled) { SDL_Touch *touch = SDL_GetTouch(index); if (!touch) { return -1; } /* Flush pending touch motion */ touch->flush_motion = SDL_TRUE; SDL_PumpEvents(); touch->flush_motion = SDL_FALSE; SDL_FilterEvents(FlushTouchMotion, touch); /* Set the relative mode */ touch->relative_mode = enabled; if (!enabled) { /* Restore the expected touch position */ SDL_WarpTouchInWindow(touch->focus, touch->x, touch->y); } return 0; } SDL_bool SDL_GetRelativeTouchMode(int index) { SDL_Touch *touch = SDL_GetTouch(index); if (!touch) { return SDL_FALSE; } return touch->relative_mode; } Uint8 SDL_GetTouchState(int *x, int *y) { SDL_Touch *touch = SDL_GetTouch(SDL_current_touch); if (!touch) { if (x) { *x = 0; } if (y) { *y = 0; } return 0; } if (x) { *x = touch->x; } if (y) { *y = touch->y; } return touch->buttonstate; } Uint8 SDL_GetRelativeTouchState(int index, int *x, int *y) { SDL_Touch *touch = SDL_GetTouch(index); if (!touch) { if (x) { *x = 0; } if (y) { *y = 0; } return 0; } if (x) { *x = touch->xdelta; } if (y) { *y = touch->ydelta; } touch->xdelta = 0; touch->ydelta = 0; return touch->buttonstate; } void SDL_SetTouchFocus(int id, SDL_Window * window) { int index = SDL_GetTouchIndexId(id); SDL_Touch *touch = SDL_GetTouch(index); 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_GetTouch(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_GetTouch(i); if (check && check->focus == touch->focus) { focus = SDL_TRUE; break; } } } if (!focus) { SDL_SendWindowEvent(touch->focus, SDL_WINDOWEVENT_ENTER, 0, 0); } } } int SDL_SendProximity(int id, int x, int y, int type) { int index = SDL_GetTouchIndexId(id); SDL_Touch *touch = SDL_GetTouch(index); int posted = 0; if (!touch) { return 0; } touch->last_x = x; touch->last_y = y; if (SDL_GetEventState(type) == SDL_ENABLE) { SDL_Event event; event.proximity.which = (Uint8) index; event.proximity.x = x; event.proximity.y = y; event.proximity.cursor = touch->current_end; event.proximity.type = type; /* FIXME: is this right? */ event.proximity.windowID = touch->focus ? touch->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); if (type == SDL_PROXIMITYIN) { touch->proximity = SDL_TRUE; } else { touch->proximity = SDL_FALSE; } } return posted; } int SDL_SendTouchMotion(int id, int relative, int x, int y, int pressure) { int index = SDL_GetTouchIndexId(id); SDL_Touch *touch = SDL_GetTouch(index); int posted; int xrel; int yrel; int x_max = 0, y_max = 0; if (!touch || touch->flush_motion) { return 0; } /* if the touch is out of proximity we don't to want to have any motion from it */ if (touch->proximity == SDL_FALSE) { touch->last_x = x; touch->last_y = y; return 0; } /* the relative motion is calculated regarding the system cursor last position */ if (relative) { xrel = x; yrel = y; x = (touch->last_x + x); y = (touch->last_y + y); } else { xrel = x - touch->last_x; yrel = y - touch->last_y; } /* 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 */ if (touch->relative_mode == SDL_FALSE) { touch->x = x; touch->y = y; } else { touch->x += xrel; touch->y += yrel; } 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; } touch->xdelta += xrel; touch->ydelta += yrel; touch->pressure = pressure; /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_TOUCHMOTION) == SDL_ENABLE && touch->proximity == SDL_TRUE) { SDL_Event event; event.motion.type = SDL_TOUCHMOTION; event.motion.which = (Uint8) index; event.motion.state = touch->buttonstate; event.motion.x = touch->x; event.motion.y = touch->y; event.motion.z = touch->z; event.motion.pressure = touch->pressure; event.motion.pressure_max = touch->pressure_max; event.motion.pressure_min = touch->pressure_min; event.motion.rotation = 0; event.motion.tilt_x = 0; event.motion.tilt_y = 0; event.motion.cursor = touch->current_end; event.motion.xrel = xrel; event.motion.yrel = yrel; event.motion.windowID = touch->focus ? touch->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); } touch->last_x = touch->x; touch->last_y = touch->y; return posted; } int SDL_SendTouchButton(int id, Uint8 state, Uint8 button) { int index = SDL_GetTouchIndexId(id); SDL_Touch *touch = SDL_GetTouch(index); int posted; Uint32 type; if (!touch) { return 0; } /* 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.button.which = (Uint8) index; event.button.state = state; event.button.button = button; event.button.x = touch->x; event.button.y = touch->y; event.button.windowID = touch->focus ? touch->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); } return posted; } int SDL_SendTouchWheel(int index, int x, int y) { SDL_Touch *touch = SDL_GetTouch(index); int posted; if (!touch || (!x && !y)) { return 0; } /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_TOUCHWHEEL) == SDL_ENABLE) { SDL_Event event; event.type = SDL_TOUCHWHEEL; event.wheel.which = (Uint8) index; event.wheel.x = x; event.wheel.y = y; event.wheel.windowID = touch->focus ? touch->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); } return posted; } char * SDL_GetTouchName(int index) { SDL_Touch *touch = SDL_GetTouch(index); if (!touch) { return NULL; } return touch->name; } void SDL_ChangeEnd(int id, int end) { int index = SDL_GetTouchIndexId(id); SDL_Touch *touch = SDL_GetTouch(index); if (touch) { touch->current_end = end; } } /* vi: set ts=4 sw=4 expandtab: */