SDL_touch.c
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 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_internal.h"
/* General touch handling code for SDL */
#include "SDL_assert.h"
#include "SDL_events.h"
#include "SDL_events_c.h"
#include "../video/SDL_sysvideo.h"
static int SDL_num_touch = 0;
static SDL_Touch **SDL_touchDevices = NULL;
/* for mapping touch events to mice */
#define SYNTHESIZE_TOUCH_TO_MOUSE 1
#if SYNTHESIZE_TOUCH_TO_MOUSE
static SDL_bool finger_touching = SDL_FALSE;
static SDL_FingerID track_fingerid;
static SDL_TouchID track_touchid;
#endif
/* Public functions */
int
SDL_TouchInit(void)
{
return (0);
}
int
SDL_GetNumTouchDevices(void)
{
return SDL_num_touch;
}
SDL_TouchID
SDL_GetTouchDevice(int index)
{
if (index < 0 || index >= SDL_num_touch) {
SDL_SetError("Unknown touch device index %d", index);
return 0;
}
return SDL_touchDevices[index]->id;
}
static int
SDL_GetTouchIndex(SDL_TouchID id)
{
int index;
SDL_Touch *touch;
for (index = 0; index < SDL_num_touch; ++index) {
touch = SDL_touchDevices[index];
if (touch->id == id) {
return index;
}
}
return -1;
}
SDL_Touch *
SDL_GetTouch(SDL_TouchID id)
{
int index = SDL_GetTouchIndex(id);
if (index < 0 || index >= SDL_num_touch) {
if (SDL_GetVideoDevice()->ResetTouch != NULL) {
SDL_SetError("Unknown touch id %d, resetting", (int) id);
(SDL_GetVideoDevice()->ResetTouch)(SDL_GetVideoDevice());
} else {
SDL_SetError("Unknown touch device id %d, cannot reset", (int) id);
}
return NULL;
}
return SDL_touchDevices[index];
}
SDL_TouchDeviceType
SDL_GetTouchDeviceType(SDL_TouchID id)
{
SDL_Touch *touch = SDL_GetTouch(id);
if (touch) {
return touch->type;
}
return SDL_TOUCH_DEVICE_INVALID;
}
static int
SDL_GetFingerIndex(const SDL_Touch * touch, SDL_FingerID fingerid)
{
int index;
for (index = 0; index < touch->num_fingers; ++index) {
if (touch->fingers[index]->id == fingerid) {
return index;
}
}
return -1;
}
static SDL_Finger *
SDL_GetFinger(const SDL_Touch * touch, SDL_FingerID id)
{
int index = SDL_GetFingerIndex(touch, id);
if (index < 0 || index >= touch->num_fingers) {
return NULL;
}
return touch->fingers[index];
}
int
SDL_GetNumTouchFingers(SDL_TouchID touchID)
{
SDL_Touch *touch = SDL_GetTouch(touchID);
if (touch) {
return touch->num_fingers;
}
return 0;
}
SDL_Finger *
SDL_GetTouchFinger(SDL_TouchID touchID, int index)
{
SDL_Touch *touch = SDL_GetTouch(touchID);
if (!touch) {
return NULL;
}
if (index < 0 || index >= touch->num_fingers) {
SDL_SetError("Unknown touch finger");
return NULL;
}
return touch->fingers[index];
}
int
SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
{
SDL_Touch **touchDevices;
int index;
index = SDL_GetTouchIndex(touchID);
if (index >= 0) {
return index;
}
/* Add the touch to the list of touch */
touchDevices = (SDL_Touch **) SDL_realloc(SDL_touchDevices,
(SDL_num_touch + 1) * sizeof(*touchDevices));
if (!touchDevices) {
return SDL_OutOfMemory();
}
SDL_touchDevices = touchDevices;
index = SDL_num_touch;
SDL_touchDevices[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touchDevices[index]));
if (!SDL_touchDevices[index]) {
return SDL_OutOfMemory();
}
/* Added touch to list */
++SDL_num_touch;
/* we're setting the touch properties */
SDL_touchDevices[index]->id = touchID;
SDL_touchDevices[index]->type = type;
SDL_touchDevices[index]->num_fingers = 0;
SDL_touchDevices[index]->max_fingers = 0;
SDL_touchDevices[index]->fingers = NULL;
/* Record this touch device for gestures */
/* We could do this on the fly in the gesture code if we wanted */
SDL_GestureAddTouch(touchID);
return index;
}
static int
SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
{
SDL_Finger *finger;
if (touch->num_fingers == touch->max_fingers) {
SDL_Finger **new_fingers;
new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers+1)*sizeof(*touch->fingers));
if (!new_fingers) {
return SDL_OutOfMemory();
}
touch->fingers = new_fingers;
touch->fingers[touch->max_fingers] = (SDL_Finger *)SDL_malloc(sizeof(*finger));
if (!touch->fingers[touch->max_fingers]) {
return SDL_OutOfMemory();
}
touch->max_fingers++;
}
finger = touch->fingers[touch->num_fingers++];
finger->id = fingerid;
finger->x = x;
finger->y = y;
finger->pressure = pressure;
return 0;
}
static int
SDL_DelFinger(SDL_Touch* touch, SDL_FingerID fingerid)
{
SDL_Finger *temp;
int index = SDL_GetFingerIndex(touch, fingerid);
if (index < 0) {
return -1;
}
touch->num_fingers--;
temp = touch->fingers[index];
touch->fingers[index] = touch->fingers[touch->num_fingers];
touch->fingers[touch->num_fingers] = temp;
return 0;
}
int
SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid,
SDL_bool down, float x, float y, float pressure)
{
int posted;
SDL_Finger *finger;
SDL_Mouse *mouse;
SDL_Touch* touch = SDL_GetTouch(id);
if (!touch) {
return -1;
}
mouse = SDL_GetMouse();
#if SYNTHESIZE_TOUCH_TO_MOUSE
/* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
{
if (mouse->touch_mouse_events) {
/* FIXME: maybe we should only restrict to a few SDL_TouchDeviceType */
if (id != SDL_MOUSE_TOUCHID) {
SDL_Window *window = SDL_GetMouseFocus();
if (window == NULL) {
/* Mouse focus may have been lost by e.g. the window resizing
* due to device orientation change while the mouse state is
* pressed (because its position is now out of the window).
* SendMouse* will update mouse focus again after that, but
* if those are never called then SDL might think the
* 'mouse' has no focus at all. */
window = SDL_GetKeyboardFocus();
}
if (window) {
if (down) {
if (finger_touching == SDL_FALSE) {
int pos_x = (int)(x * (float)window->w);
int pos_y = (int)(y * (float)window->h);
if (pos_x < 0) pos_x = 0;
if (pos_x > window->w - 1) pos_x = window->w - 1;
if (pos_y < 0) pos_y = 0;
if (pos_y > window->h - 1) pos_y = window->h - 1;
SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
SDL_SendMouseButton(window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
}
} else {
if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
SDL_SendMouseButton(window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
}
}
}
if (down) {
if (finger_touching == SDL_FALSE) {
finger_touching = SDL_TRUE;
track_touchid = id;
track_fingerid = fingerid;
}
} else {
if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
finger_touching = SDL_FALSE;
}
}
}
}
}
#endif
/* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */
if (mouse->mouse_touch_events == 0) {
if (id == SDL_MOUSE_TOUCHID) {
return 0;
}
}
finger = SDL_GetFinger(touch, fingerid);
if (down) {
if (finger) {
/* This finger is already down */
return 0;
}
if (SDL_AddFinger(touch, fingerid, x, y, pressure) < 0) {
return 0;
}
posted = 0;
if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
SDL_Event event;
event.tfinger.type = SDL_FINGERDOWN;
event.tfinger.touchId = id;
event.tfinger.fingerId = fingerid;
event.tfinger.x = x;
event.tfinger.y = y;
event.tfinger.dx = 0;
event.tfinger.dy = 0;
event.tfinger.pressure = pressure;
posted = (SDL_PushEvent(&event) > 0);
}
} else {
if (!finger) {
/* This finger is already up */
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.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;
posted = (SDL_PushEvent(&event) > 0);
}
SDL_DelFinger(touch, fingerid);
}
return posted;
}
int
SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
float x, float y, float pressure)
{
SDL_Touch *touch;
SDL_Finger *finger;
SDL_Mouse *mouse;
int posted;
float xrel, yrel, prel;
touch = SDL_GetTouch(id);
if (!touch) {
return -1;
}
mouse = SDL_GetMouse();
#if SYNTHESIZE_TOUCH_TO_MOUSE
/* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
{
if (mouse->touch_mouse_events) {
if (id != SDL_MOUSE_TOUCHID) {
SDL_Window *window = SDL_GetMouseFocus();
if (window) {
if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
int pos_x = (int)(x * (float)window->w);
int pos_y = (int)(y * (float)window->h);
if (pos_x < 0) pos_x = 0;
if (pos_x > window->w - 1) pos_x = window->w - 1;
if (pos_y < 0) pos_y = 0;
if (pos_y > window->h - 1) pos_y = window->h - 1;
SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
}
}
}
}
}
#endif
/* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */
if (mouse->mouse_touch_events == 0) {
if (id == SDL_MOUSE_TOUCHID) {
return 0;
}
}
finger = SDL_GetFinger(touch,fingerid);
if (!finger) {
return SDL_SendTouch(id, fingerid, SDL_TRUE, x, y, pressure);
}
xrel = x - finger->x;
yrel = y - finger->y;
prel = pressure - finger->pressure;
/* Drop events that don't change state */
if (xrel == 0.0f && yrel == 0.0f && prel == 0.0f) {
#if 0
printf("Touch event didn't change state - dropped!\n");
#endif
return 0;
}
/* Update internal touch coordinates */
finger->x = x;
finger->y = y;
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;
posted = (SDL_PushEvent(&event) > 0);
}
return posted;
}
void
SDL_DelTouch(SDL_TouchID id)
{
int i;
int index = SDL_GetTouchIndex(id);
SDL_Touch *touch = SDL_GetTouch(id);
if (!touch) {
return;
}
for (i = 0; i < touch->max_fingers; ++i) {
SDL_free(touch->fingers[i]);
}
SDL_free(touch->fingers);
SDL_free(touch);
SDL_num_touch--;
SDL_touchDevices[index] = SDL_touchDevices[SDL_num_touch];
/* Delete this touch device for gestures */
SDL_GestureDelTouch(id);
}
void
SDL_TouchQuit(void)
{
int i;
for (i = SDL_num_touch; i--; ) {
SDL_DelTouch(SDL_touchDevices[i]->id);
}
SDL_assert(SDL_num_touch == 0);
SDL_free(SDL_touchDevices);
SDL_touchDevices = NULL;
SDL_GestureQuit();
}
/* vi: set ts=4 sw=4 expandtab: */
SDL_num_touch
static int SDL_num_touch
Definition: SDL_touch.c:31
SDL_GetMouse
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:178
SDL_events.h
NULL
#define NULL
Definition: begin_code.h:167
SDL_TOUCH_DEVICE_INVALID
@ SDL_TOUCH_DEVICE_INVALID
Definition: SDL_touch.h:46
SDL_GetTouchDevice
SDL_TouchID SDL_GetTouchDevice(int index)
Get the touch ID with the given index, or 0 if the index is invalid.
Definition: SDL_touch.c:58
SDL_Mouse::touch_mouse_events
SDL_bool touch_mouse_events
Definition: SDL_mouse_c.h:95
SDL_FingerID
Sint64 SDL_FingerID
Definition: SDL_touch.h:42
track_fingerid
static SDL_FingerID track_fingerid
Definition: SDL_touch.c:40
SDL_TouchID
Sint64 SDL_TouchID
Definition: SDL_touch.h:41
SDL_realloc
#define SDL_realloc
Definition: SDL_dynapi_overrides.h:376
finger_touching
static SDL_bool finger_touching
Definition: SDL_touch.c:39
SDL_GetFinger
static SDL_Finger * SDL_GetFinger(const SDL_Touch *touch, SDL_FingerID id)
Definition: SDL_touch.c:121
SDL_ENABLE
#define SDL_ENABLE
Definition: SDL_events.h:759
SDL_DelFinger
static int SDL_DelFinger(SDL_Touch *touch, SDL_FingerID fingerid)
Definition: SDL_touch.c:225
SDL_VideoDevice::ResetTouch
void(* ResetTouch)(_THIS)
Definition: SDL_sysvideo.h:172
SDL_SendTouch
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, float x, float y, float pressure)
Definition: SDL_touch.c:242
index
GLuint index
Definition: SDL_opengl_glext.h:660
SDL_RELEASED
#define SDL_RELEASED
Definition: SDL_events.h:49
SDL_SendTouchMotion
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:364
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:73
SDL_GetKeyboardFocus
#define SDL_GetKeyboardFocus
Definition: SDL_dynapi_overrides.h:216
SDL_Finger
Definition: SDL_touch.h:52
SDL_TOUCH_MOUSEID
#define SDL_TOUCH_MOUSEID
Definition: SDL_touch.h:61
SDL_TouchDeviceType
SDL_TouchDeviceType
Definition: SDL_touch.h:44
track_touchid
static SDL_TouchID track_touchid
Definition: SDL_touch.c:41
SDL_FINGERUP
@ SDL_FINGERUP
Definition: SDL_events.h:129
SDL_GetTouchIndex
static int SDL_GetTouchIndex(SDL_TouchID id)
Definition: SDL_touch.c:68
SDL_Mouse::mouse_touch_events
SDL_bool mouse_touch_events
Definition: SDL_mouse_c.h:96
SDL_PRESSED
#define SDL_PRESSED
Definition: SDL_events.h:50
event
struct _cl_event * event
Definition: SDL_opengl_glext.h:2649
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_AddTouch
int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
Definition: SDL_touch.c:155
SDL_FINGERDOWN
@ SDL_FINGERDOWN
Definition: SDL_events.h:128
SDL_BUTTON_LEFT
#define SDL_BUTTON_LEFT
Definition: SDL_mouse.h:282
SDL_GestureQuit
void SDL_GestureQuit()
Definition: SDL_gesture.c:104
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
SDL_GetEventState
#define SDL_GetEventState(type)
Definition: SDL_events.h:772
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
SDL_GetTouchDeviceType
SDL_TouchDeviceType SDL_GetTouchDeviceType(SDL_TouchID id)
Get the type of the given touch device.
Definition: SDL_touch.c:99
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_GetNumTouchFingers
int SDL_GetNumTouchFingers(SDL_TouchID touchID)
Get the number of active fingers for a given touch device.
Definition: SDL_touch.c:131
f
GLfloat f
Definition: SDL_opengl_glext.h:1870
SDL_PushEvent
#define SDL_PushEvent
Definition: SDL_dynapi_overrides.h:125
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:660
SDL_SendMouseMotion
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:301
SDL_GestureDelTouch
int SDL_GestureDelTouch(SDL_TouchID touchId)
Definition: SDL_gesture.c:468
SDL_assert.h
SDL_FINGERMOTION
@ SDL_FINGERMOTION
Definition: SDL_events.h:130
SDL_Touch::num_fingers
int num_fingers
Definition: SDL_touch_c.h:31
SDL_Mouse
Definition: SDL_mouse_c.h:43
SDL_Touch::fingers
SDL_Finger ** fingers
Definition: SDL_touch_c.h:33
SDL_GetTouchFinger
SDL_Finger * SDL_GetTouchFinger(SDL_TouchID touchID, int index)
Get the finger object of the given touch, with the given index.
Definition: SDL_touch.c:141
SDL_DelTouch
void SDL_DelTouch(SDL_TouchID id)
Definition: SDL_touch.c:449
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_AddFinger
static int SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:198
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
SDL_GestureAddTouch
int SDL_GestureAddTouch(SDL_TouchID touchId)
Definition: SDL_gesture.c:450
id
GLuint id
Definition: SDL_opengl_glext.h:528
SDL_MOUSE_TOUCHID
#define SDL_MOUSE_TOUCHID
Definition: SDL_touch.h:64
SDL_Touch
Definition: SDL_touch_c.h:27
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_Touch::max_fingers
int max_fingers
Definition: SDL_touch_c.h:32
SDL_Touch::id
SDL_TouchID id
Definition: SDL_touch_c.h:29
SDL_Finger::y
float y
Definition: SDL_touch.h:56
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_GetMouseFocus
#define SDL_GetMouseFocus
Definition: SDL_dynapi_overrides.h:245
SDL_Finger::pressure
float pressure
Definition: SDL_touch.h:57
SDL_GetNumTouchDevices
int SDL_GetNumTouchDevices(void)
Get the number of registered touch devices.
Definition: SDL_touch.c:52
SDL_touchDevices
static SDL_Touch ** SDL_touchDevices
Definition: SDL_touch.c:32
SDL_events_c.h
SDL_Finger::id
SDL_FingerID id
Definition: SDL_touch.h:54
SDL_Event
General event structure.
Definition: SDL_events.h:557
SDL_GetVideoDevice
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:583
SDL_Finger::x
float x
Definition: SDL_touch.h:55
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
SDL_TouchQuit
void SDL_TouchQuit(void)
Definition: SDL_touch.c:473
SDL_GetFingerIndex
static int SDL_GetFingerIndex(const SDL_Touch *touch, SDL_FingerID fingerid)
Definition: SDL_touch.c:109
SDL_Touch::type
SDL_TouchDeviceType type
Definition: SDL_touch_c.h:30
SDL_TouchInit
int SDL_TouchInit(void)
Definition: SDL_touch.c:46
type
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
SDL_SendMouseButton
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:605
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
SDL_GetTouch
SDL_Touch * SDL_GetTouch(SDL_TouchID id)
Definition: SDL_touch.c:83