SDL  2.0
SDL_touch.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../SDL_internal.h"
22 
23 /* General touch handling code for SDL */
24 
25 #include "SDL_assert.h"
26 #include "SDL_events.h"
27 #include "SDL_events_c.h"
28 #include "../video/SDL_sysvideo.h"
29 
30 
31 static int SDL_num_touch = 0;
33 
34 /* for mapping touch events to mice */
35 
36 #define SYNTHESIZE_TOUCH_TO_MOUSE 1
37 
38 #if SYNTHESIZE_TOUCH_TO_MOUSE
42 #endif
43 
44 /* Public functions */
45 int
47 {
48  return (0);
49 }
50 
51 int
53 {
54  return SDL_num_touch;
55 }
56 
59 {
61  SDL_SetError("Unknown touch device index %d", index);
62  return 0;
63  }
64  return SDL_touchDevices[index]->id;
65 }
66 
67 static int
69 {
70  int index;
71  SDL_Touch *touch;
72 
73  for (index = 0; index < SDL_num_touch; ++index) {
74  touch = SDL_touchDevices[index];
75  if (touch->id == id) {
76  return index;
77  }
78  }
79  return -1;
80 }
81 
82 SDL_Touch *
84 {
85  int index = SDL_GetTouchIndex(id);
87  if (SDL_GetVideoDevice()->ResetTouch != NULL) {
88  SDL_SetError("Unknown touch id %d, resetting", (int) id);
90  } else {
91  SDL_SetError("Unknown touch device id %d, cannot reset", (int) id);
92  }
93  return NULL;
94  }
95  return SDL_touchDevices[index];
96 }
97 
100 {
101  SDL_Touch *touch = SDL_GetTouch(id);
102  if (touch) {
103  return touch->type;
104  }
106 }
107 
108 static int
109 SDL_GetFingerIndex(const SDL_Touch * touch, SDL_FingerID fingerid)
110 {
111  int index;
112  for (index = 0; index < touch->num_fingers; ++index) {
113  if (touch->fingers[index]->id == fingerid) {
114  return index;
115  }
116  }
117  return -1;
118 }
119 
120 static SDL_Finger *
122 {
123  int index = SDL_GetFingerIndex(touch, id);
124  if (index < 0 || index >= touch->num_fingers) {
125  return NULL;
126  }
127  return touch->fingers[index];
128 }
129 
130 int
132 {
133  SDL_Touch *touch = SDL_GetTouch(touchID);
134  if (touch) {
135  return touch->num_fingers;
136  }
137  return 0;
138 }
139 
140 SDL_Finger *
142 {
143  SDL_Touch *touch = SDL_GetTouch(touchID);
144  if (!touch) {
145  return NULL;
146  }
147  if (index < 0 || index >= touch->num_fingers) {
148  SDL_SetError("Unknown touch finger");
149  return NULL;
150  }
151  return touch->fingers[index];
152 }
153 
154 int
156 {
157  SDL_Touch **touchDevices;
158  int index;
159 
160  index = SDL_GetTouchIndex(touchID);
161  if (index >= 0) {
162  return index;
163  }
164 
165  /* Add the touch to the list of touch */
166  touchDevices = (SDL_Touch **) SDL_realloc(SDL_touchDevices,
167  (SDL_num_touch + 1) * sizeof(*touchDevices));
168  if (!touchDevices) {
169  return SDL_OutOfMemory();
170  }
171 
172  SDL_touchDevices = touchDevices;
174 
176  if (!SDL_touchDevices[index]) {
177  return SDL_OutOfMemory();
178  }
179 
180  /* Added touch to list */
181  ++SDL_num_touch;
182 
183  /* we're setting the touch properties */
184  SDL_touchDevices[index]->id = touchID;
189 
190  /* Record this touch device for gestures */
191  /* We could do this on the fly in the gesture code if we wanted */
192  SDL_GestureAddTouch(touchID);
193 
194  return index;
195 }
196 
197 static int
198 SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
199 {
200  SDL_Finger *finger;
201 
202  if (touch->num_fingers == touch->max_fingers) {
203  SDL_Finger **new_fingers;
204  new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers+1)*sizeof(*touch->fingers));
205  if (!new_fingers) {
206  return SDL_OutOfMemory();
207  }
208  touch->fingers = new_fingers;
209  touch->fingers[touch->max_fingers] = (SDL_Finger *)SDL_malloc(sizeof(*finger));
210  if (!touch->fingers[touch->max_fingers]) {
211  return SDL_OutOfMemory();
212  }
213  touch->max_fingers++;
214  }
215 
216  finger = touch->fingers[touch->num_fingers++];
217  finger->id = fingerid;
218  finger->x = x;
219  finger->y = y;
220  finger->pressure = pressure;
221  return 0;
222 }
223 
224 static int
226 {
227  SDL_Finger *temp;
228 
229  int index = SDL_GetFingerIndex(touch, fingerid);
230  if (index < 0) {
231  return -1;
232  }
233 
234  touch->num_fingers--;
235  temp = touch->fingers[index];
236  touch->fingers[index] = touch->fingers[touch->num_fingers];
237  touch->fingers[touch->num_fingers] = temp;
238  return 0;
239 }
240 
241 int
243  SDL_bool down, float x, float y, float pressure)
244 {
245  int posted;
246  SDL_Finger *finger;
247  SDL_Mouse *mouse;
248 
249  SDL_Touch* touch = SDL_GetTouch(id);
250  if (!touch) {
251  return -1;
252  }
253 
254  mouse = SDL_GetMouse();
255 
256 #if SYNTHESIZE_TOUCH_TO_MOUSE
257  /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
258  {
259  if (mouse->touch_mouse_events) {
260  /* FIXME: maybe we should only restrict to a few SDL_TouchDeviceType */
261  if (id != SDL_MOUSE_TOUCHID) {
262  if (window) {
263  if (down) {
264  if (finger_touching == SDL_FALSE) {
265  int pos_x = (int)(x * (float)window->w);
266  int pos_y = (int)(y * (float)window->h);
267  if (pos_x < 0) pos_x = 0;
268  if (pos_x > window->w - 1) pos_x = window->w - 1;
269  if (pos_y < 0) pos_y = 0;
270  if (pos_y > window->h - 1) pos_y = window->h - 1;
271  SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
273  }
274  } else {
275  if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
277  }
278  }
279  }
280  if (down) {
281  if (finger_touching == SDL_FALSE) {
283  track_touchid = id;
284  track_fingerid = fingerid;
285  }
286  } else {
287  if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
289  }
290  }
291  }
292  }
293  }
294 #endif
295 
296  /* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */
297  if (mouse->mouse_touch_events == 0) {
298  if (id == SDL_MOUSE_TOUCHID) {
299  return 0;
300  }
301  }
302 
303  finger = SDL_GetFinger(touch, fingerid);
304  if (down) {
305  if (finger) {
306  /* This finger is already down */
307  return 0;
308  }
309 
310  if (SDL_AddFinger(touch, fingerid, x, y, pressure) < 0) {
311  return 0;
312  }
313 
314  posted = 0;
317  event.tfinger.type = SDL_FINGERDOWN;
318  event.tfinger.touchId = id;
319  event.tfinger.fingerId = fingerid;
320  event.tfinger.x = x;
321  event.tfinger.y = y;
322  event.tfinger.dx = 0;
323  event.tfinger.dy = 0;
324  event.tfinger.pressure = pressure;
325  event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
326  posted = (SDL_PushEvent(&event) > 0);
327  }
328  } else {
329  if (!finger) {
330  /* This finger is already up */
331  return 0;
332  }
333 
334  posted = 0;
337  event.tfinger.type = SDL_FINGERUP;
338  event.tfinger.touchId = id;
339  event.tfinger.fingerId = fingerid;
340  /* I don't trust the coordinates passed on fingerUp */
341  event.tfinger.x = finger->x;
342  event.tfinger.y = finger->y;
343  event.tfinger.dx = 0;
344  event.tfinger.dy = 0;
345  event.tfinger.pressure = pressure;
346  event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
347  posted = (SDL_PushEvent(&event) > 0);
348  }
349 
350  SDL_DelFinger(touch, fingerid);
351  }
352  return posted;
353 }
354 
355 int
357  float x, float y, float pressure)
358 {
359  SDL_Touch *touch;
360  SDL_Finger *finger;
361  SDL_Mouse *mouse;
362  int posted;
363  float xrel, yrel, prel;
364 
365  touch = SDL_GetTouch(id);
366  if (!touch) {
367  return -1;
368  }
369 
370  mouse = SDL_GetMouse();
371 
372 #if SYNTHESIZE_TOUCH_TO_MOUSE
373  /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
374  {
375  if (mouse->touch_mouse_events) {
376  if (id != SDL_MOUSE_TOUCHID) {
377  if (window) {
378  if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
379  int pos_x = (int)(x * (float)window->w);
380  int pos_y = (int)(y * (float)window->h);
381  if (pos_x < 0) pos_x = 0;
382  if (pos_x > window->w - 1) pos_x = window->w - 1;
383  if (pos_y < 0) pos_y = 0;
384  if (pos_y > window->h - 1) pos_y = window->h - 1;
385  SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
386  }
387  }
388  }
389  }
390  }
391 #endif
392 
393  /* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */
394  if (mouse->mouse_touch_events == 0) {
395  if (id == SDL_MOUSE_TOUCHID) {
396  return 0;
397  }
398  }
399 
400  finger = SDL_GetFinger(touch,fingerid);
401  if (!finger) {
402  return SDL_SendTouch(id, fingerid, window, SDL_TRUE, x, y, pressure);
403  }
404 
405  xrel = x - finger->x;
406  yrel = y - finger->y;
407  prel = pressure - finger->pressure;
408 
409  /* Drop events that don't change state */
410  if (xrel == 0.0f && yrel == 0.0f && prel == 0.0f) {
411 #if 0
412  printf("Touch event didn't change state - dropped!\n");
413 #endif
414  return 0;
415  }
416 
417  /* Update internal touch coordinates */
418  finger->x = x;
419  finger->y = y;
420  finger->pressure = pressure;
421 
422  /* Post the event, if desired */
423  posted = 0;
426  event.tfinger.type = SDL_FINGERMOTION;
427  event.tfinger.touchId = id;
428  event.tfinger.fingerId = fingerid;
429  event.tfinger.x = x;
430  event.tfinger.y = y;
431  event.tfinger.dx = xrel;
432  event.tfinger.dy = yrel;
433  event.tfinger.pressure = pressure;
434  event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
435  posted = (SDL_PushEvent(&event) > 0);
436  }
437  return posted;
438 }
439 
440 void
442 {
443  int i;
444  int index = SDL_GetTouchIndex(id);
445  SDL_Touch *touch = SDL_GetTouch(id);
446 
447  if (!touch) {
448  return;
449  }
450 
451  for (i = 0; i < touch->max_fingers; ++i) {
452  SDL_free(touch->fingers[i]);
453  }
454  SDL_free(touch->fingers);
455  SDL_free(touch);
456 
457  SDL_num_touch--;
459 
460  /* Delete this touch device for gestures */
462 }
463 
464 void
466 {
467  int i;
468 
469  for (i = SDL_num_touch; i--; ) {
471  }
473 
476  SDL_GestureQuit();
477 }
478 
479 /* 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:170
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_GetWindowID
#define SDL_GetWindowID
Definition: SDL_dynapi_overrides.h:516
SDL_FingerID
Sint64 SDL_FingerID
Definition: SDL_touch.h:42
track_fingerid
static SDL_FingerID track_fingerid
Definition: SDL_touch.c:40
SDL_SendTouch
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, SDL_bool down, float x, float y, float pressure)
Definition: SDL_touch.c:242
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:760
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:173
index
GLuint index
Definition: SDL_opengl_glext.h:663
SDL_RELEASED
#define SDL_RELEASED
Definition: SDL_events.h:49
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:75
SDL_Finger
Definition: SDL_touch.h:53
SDL_TOUCH_MOUSEID
#define SDL_TOUCH_MOUSEID
Definition: SDL_touch.h:61
SDL_TouchDeviceType
SDL_TouchDeviceType
Definition: SDL_touch.h:45
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:2652
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:106
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
SDL_GetEventState
#define SDL_GetEventState(type)
Definition: SDL_events.h:773
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:1873
SDL_PushEvent
#define SDL_PushEvent
Definition: SDL_dynapi_overrides.h:125
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:663
SDL_SendMouseMotion
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:293
SDL_GestureDelTouch
int SDL_GestureDelTouch(SDL_TouchID touchId)
Definition: SDL_gesture.c:472
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:44
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_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_DelTouch
void SDL_DelTouch(SDL_TouchID id)
Definition: SDL_touch.c:441
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_TouchID
Sint64 SDL_TouchID
Definition: SDL_touch.h:41
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:454
id
GLuint id
Definition: SDL_opengl_glext.h:531
SDL_MOUSE_TOUCHID
#define SDL_MOUSE_TOUCHID
Definition: SDL_touch.h:64
SDL_Touch
Definition: SDL_touch_c.h:28
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_Finger::pressure
float pressure
Definition: SDL_touch.h:57
SDL_SendTouchMotion
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, float x, float y, float pressure)
Definition: SDL_touch.c:356
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_bool
SDL_bool
Definition: SDL_stdinc.h:162
SDL_Finger::id
SDL_FingerID id
Definition: SDL_touch.h:54
SDL_Event
General event structure.
Definition: SDL_events.h:559
SDL_GetVideoDevice
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:586
SDL_Finger::x
float x
Definition: SDL_touch.h:55
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
SDL_TouchQuit
void SDL_TouchQuit(void)
Definition: SDL_touch.c:465
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:594
SDL_GetTouch
SDL_Touch * SDL_GetTouch(SDL_TouchID id)
Definition: SDL_touch.c:83