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;
173  index = SDL_num_touch;
174 
175  SDL_touchDevices[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touchDevices[index]));
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;
185  SDL_touchDevices[index]->type = type;
186  SDL_touchDevices[index]->num_fingers = 0;
187  SDL_touchDevices[index]->max_fingers = 0;
188  SDL_touchDevices[index]->fingers = NULL;
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. */
270  window = SDL_GetKeyboardFocus();
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--;
466  SDL_touchDevices[index] = SDL_touchDevices[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--; ) {
478  SDL_DelTouch(SDL_touchDevices[i]->id);
479  }
481 
482  SDL_free(SDL_touchDevices);
483  SDL_touchDevices = NULL;
484  SDL_GestureQuit();
485 }
486 
487 /* vi: set ts=4 sw=4 expandtab: */
static int SDL_num_touch
Definition: SDL_touch.c:31
GLuint id
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:178
int max_fingers
Definition: SDL_touch_c.h:32
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
int SDL_GestureDelTouch(SDL_TouchID touchId)
Definition: SDL_gesture.c:468
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
Sint64 SDL_FingerID
Definition: SDL_touch.h:42
static int SDL_DelFinger(SDL_Touch *touch, SDL_FingerID fingerid)
Definition: SDL_touch.c:225
SDL_Finger ** fingers
Definition: SDL_touch_c.h:33
int SDL_SendTouch(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down, float x, float y, float pressure)
Definition: SDL_touch.c:242
static SDL_Finger * SDL_GetFinger(const SDL_Touch *touch, SDL_FingerID id)
Definition: SDL_touch.c:121
#define SDL_ENABLE
Definition: SDL_events.h:759
static SDL_FingerID track_fingerid
Definition: SDL_touch.c:40
GLfloat f
#define SDL_GetKeyboardFocus
#define SDL_realloc
SDL_TouchID id
Definition: SDL_touch_c.h:29
static SDL_bool finger_touching
Definition: SDL_touch.c:39
#define SDL_TOUCH_MOUSEID
Definition: SDL_touch.h:61
SDL_TouchDeviceType
Definition: SDL_touch.h:44
static int SDL_GetTouchIndex(SDL_TouchID id)
Definition: SDL_touch.c:68
GLuint const GLchar * name
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:364
int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
Definition: SDL_touch.c:155
void SDL_GestureQuit()
Definition: SDL_gesture.c:104
SDL_TouchDeviceType SDL_GetTouchDeviceType(SDL_TouchID id)
Get the type of the given touch device.
Definition: SDL_touch.c:99
int SDL_GestureAddTouch(SDL_TouchID touchId)
Definition: SDL_gesture.c:450
static SDL_TouchID track_touchid
Definition: SDL_touch.c:41
#define SDL_GetEventState(type)
Definition: SDL_events.h:772
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:301
#define SDL_BUTTON_LEFT
Definition: SDL_mouse.h:282
SDL_bool touch_mouse_events
Definition: SDL_mouse_c.h:95
#define SDL_free
struct _cl_event * event
int SDL_GetNumTouchFingers(SDL_TouchID touchID)
Get the number of active fingers for a given touch device.
Definition: SDL_touch.c:131
#define SDL_PushEvent
void SDL_DelTouch(SDL_TouchID id)
Definition: SDL_touch.c:449
Sint64 SDL_TouchID
Definition: SDL_touch.h:41
static int SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:198
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
float y
Definition: SDL_touch.h:56
GLuint index
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
void(* ResetTouch)(_THIS)
Definition: SDL_sysvideo.h:172
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
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:167
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:161
#define SDL_GetMouseFocus
#define SDL_MOUSE_TOUCHID
Definition: SDL_touch.h:64
#define SDL_SetError
SDL_TouchDeviceType type
Definition: SDL_touch_c.h:30
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
The type used to identify a window.
Definition: SDL_sysvideo.h:73
int num_fingers
Definition: SDL_touch_c.h:31
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:583
SDL_FingerID id
Definition: SDL_touch.h:54
int SDL_GetNumTouchDevices(void)
Get the number of registered touch devices.
Definition: SDL_touch.c:52
General event structure.
Definition: SDL_events.h:557
#define SDL_malloc
static SDL_Touch ** SDL_touchDevices
Definition: SDL_touch.c:32
SDL_bool mouse_touch_events
Definition: SDL_mouse_c.h:96
static int SDL_GetFingerIndex(const SDL_Touch *touch, SDL_FingerID fingerid)
Definition: SDL_touch.c:109
#define SDL_PRESSED
Definition: SDL_events.h:50
float pressure
Definition: SDL_touch.h:57
#define SDL_RELEASED
Definition: SDL_events.h:49
SDL_Touch * SDL_GetTouch(SDL_TouchID id)
Definition: SDL_touch.c:83
void SDL_TouchQuit(void)
Definition: SDL_touch.c:473
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:605
int SDL_TouchInit(void)
Definition: SDL_touch.c:46
float x
Definition: SDL_touch.h:55