SDL  2.0
SDL_touch.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2019 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) {
263  if (window == NULL) {
264  /* Mouse focus may have been lost by e.g. the window resizing
265  * due to device orientation change while the mouse state is
266  * pressed (because its position is now out of the window).
267  * SendMouse* will update mouse focus again after that, but
268  * if those are never called then SDL might think the
269  * 'mouse' has no focus at all. */
271  }
272  if (window) {
273  if (down) {
274  if (finger_touching == SDL_FALSE) {
275  int pos_x = (int)(x * (float)window->w);
276  int pos_y = (int)(y * (float)window->h);
277  if (pos_x < 0) pos_x = 0;
278  if (pos_x > window->w - 1) pos_x = window->w - 1;
279  if (pos_y < 0) pos_y = 0;
280  if (pos_y > window->h - 1) pos_y = window->h - 1;
281  SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
283  }
284  } else {
285  if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
287  }
288  }
289  }
290  if (down) {
291  if (finger_touching == SDL_FALSE) {
293  track_touchid = id;
294  track_fingerid = fingerid;
295  }
296  } else {
297  if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
299  }
300  }
301  }
302  }
303  }
304 #endif
305 
306  /* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */
307  if (mouse->mouse_touch_events == 0) {
308  if (id == SDL_MOUSE_TOUCHID) {
309  return 0;
310  }
311  }
312 
313  finger = SDL_GetFinger(touch, fingerid);
314  if (down) {
315  if (finger) {
316  /* This finger is already down */
317  return 0;
318  }
319 
320  if (SDL_AddFinger(touch, fingerid, x, y, pressure) < 0) {
321  return 0;
322  }
323 
324  posted = 0;
327  event.tfinger.type = SDL_FINGERDOWN;
328  event.tfinger.touchId = id;
329  event.tfinger.fingerId = fingerid;
330  event.tfinger.x = x;
331  event.tfinger.y = y;
332  event.tfinger.dx = 0;
333  event.tfinger.dy = 0;
334  event.tfinger.pressure = pressure;
335  posted = (SDL_PushEvent(&event) > 0);
336  }
337  } else {
338  if (!finger) {
339  /* This finger is already up */
340  return 0;
341  }
342 
343  posted = 0;
346  event.tfinger.type = SDL_FINGERUP;
347  event.tfinger.touchId = id;
348  event.tfinger.fingerId = fingerid;
349  /* I don't trust the coordinates passed on fingerUp */
350  event.tfinger.x = finger->x;
351  event.tfinger.y = finger->y;
352  event.tfinger.dx = 0;
353  event.tfinger.dy = 0;
354  event.tfinger.pressure = pressure;
355  posted = (SDL_PushEvent(&event) > 0);
356  }
357 
358  SDL_DelFinger(touch, fingerid);
359  }
360  return posted;
361 }
362 
363 int
365  float x, float y, float pressure)
366 {
367  SDL_Touch *touch;
368  SDL_Finger *finger;
369  SDL_Mouse *mouse;
370  int posted;
371  float xrel, yrel, prel;
372 
373  touch = SDL_GetTouch(id);
374  if (!touch) {
375  return -1;
376  }
377 
378  mouse = SDL_GetMouse();
379 
380 #if SYNTHESIZE_TOUCH_TO_MOUSE
381  /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
382  {
383  if (mouse->touch_mouse_events) {
384  if (id != SDL_MOUSE_TOUCHID) {
386  if (window) {
387  if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
388  int pos_x = (int)(x * (float)window->w);
389  int pos_y = (int)(y * (float)window->h);
390  if (pos_x < 0) pos_x = 0;
391  if (pos_x > window->w - 1) pos_x = window->w - 1;
392  if (pos_y < 0) pos_y = 0;
393  if (pos_y > window->h - 1) pos_y = window->h - 1;
394  SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
395  }
396  }
397  }
398  }
399  }
400 #endif
401 
402  /* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */
403  if (mouse->mouse_touch_events == 0) {
404  if (id == SDL_MOUSE_TOUCHID) {
405  return 0;
406  }
407  }
408 
409  finger = SDL_GetFinger(touch,fingerid);
410  if (!finger) {
411  return SDL_SendTouch(id, fingerid, SDL_TRUE, x, y, pressure);
412  }
413 
414  xrel = x - finger->x;
415  yrel = y - finger->y;
416  prel = pressure - finger->pressure;
417 
418  /* Drop events that don't change state */
419  if (xrel == 0.0f && yrel == 0.0f && prel == 0.0f) {
420 #if 0
421  printf("Touch event didn't change state - dropped!\n");
422 #endif
423  return 0;
424  }
425 
426  /* Update internal touch coordinates */
427  finger->x = x;
428  finger->y = y;
429  finger->pressure = pressure;
430 
431  /* Post the event, if desired */
432  posted = 0;
435  event.tfinger.type = SDL_FINGERMOTION;
436  event.tfinger.touchId = id;
437  event.tfinger.fingerId = fingerid;
438  event.tfinger.x = x;
439  event.tfinger.y = y;
440  event.tfinger.dx = xrel;
441  event.tfinger.dy = yrel;
442  event.tfinger.pressure = pressure;
443  posted = (SDL_PushEvent(&event) > 0);
444  }
445  return posted;
446 }
447 
448 void
450 {
451  int i;
452  int index = SDL_GetTouchIndex(id);
453  SDL_Touch *touch = SDL_GetTouch(id);
454 
455  if (!touch) {
456  return;
457  }
458 
459  for (i = 0; i < touch->max_fingers; ++i) {
460  SDL_free(touch->fingers[i]);
461  }
462  SDL_free(touch->fingers);
463  SDL_free(touch);
464 
465  SDL_num_touch--;
467 
468  /* Delete this touch device for gestures */
470 }
471 
472 void
474 {
475  int i;
476 
477  for (i = SDL_num_touch; i--; ) {
479  }
481 
484  SDL_GestureQuit();
485 }
486 
487 /* 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