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_events.h"
26 #include "SDL_events_c.h"
27 #include "../video/SDL_sysvideo.h"
28 
29 
30 static int SDL_num_touch = 0;
32 
33 /* for mapping touch events to mice */
34 
35 #define SYNTHESIZE_TOUCH_TO_MOUSE 1
36 
37 #if SYNTHESIZE_TOUCH_TO_MOUSE
41 #endif
42 
43 /* Public functions */
44 int
46 {
47  return (0);
48 }
49 
50 int
52 {
53  return SDL_num_touch;
54 }
55 
58 {
60  SDL_SetError("Unknown touch device index %d", index);
61  return 0;
62  }
63  return SDL_touchDevices[index]->id;
64 }
65 
66 static int
68 {
69  int index;
70  SDL_Touch *touch;
71 
72  for (index = 0; index < SDL_num_touch; ++index) {
73  touch = SDL_touchDevices[index];
74  if (touch->id == id) {
75  return index;
76  }
77  }
78  return -1;
79 }
80 
81 SDL_Touch *
83 {
84  int index = SDL_GetTouchIndex(id);
86  if (SDL_GetVideoDevice()->ResetTouch != NULL) {
87  SDL_SetError("Unknown touch id %d, resetting", (int) id);
89  } else {
90  SDL_SetError("Unknown touch device id %d, cannot reset", (int) id);
91  }
92  return NULL;
93  }
94  return SDL_touchDevices[index];
95 }
96 
99 {
100  SDL_Touch *touch = SDL_GetTouch(id);
101  if (touch) {
102  return touch->type;
103  }
105 }
106 
107 static int
108 SDL_GetFingerIndex(const SDL_Touch * touch, SDL_FingerID fingerid)
109 {
110  int index;
111  for (index = 0; index < touch->num_fingers; ++index) {
112  if (touch->fingers[index]->id == fingerid) {
113  return index;
114  }
115  }
116  return -1;
117 }
118 
119 static SDL_Finger *
121 {
122  int index = SDL_GetFingerIndex(touch, id);
123  if (index < 0 || index >= touch->num_fingers) {
124  return NULL;
125  }
126  return touch->fingers[index];
127 }
128 
129 int
131 {
132  SDL_Touch *touch = SDL_GetTouch(touchID);
133  if (touch) {
134  return touch->num_fingers;
135  }
136  return 0;
137 }
138 
139 SDL_Finger *
141 {
142  SDL_Touch *touch = SDL_GetTouch(touchID);
143  if (!touch) {
144  return NULL;
145  }
146  if (index < 0 || index >= touch->num_fingers) {
147  SDL_SetError("Unknown touch finger");
148  return NULL;
149  }
150  return touch->fingers[index];
151 }
152 
153 int
155 {
156  SDL_Touch **touchDevices;
157  int index;
158 
159  index = SDL_GetTouchIndex(touchID);
160  if (index >= 0) {
161  return index;
162  }
163 
164  /* Add the touch to the list of touch */
165  touchDevices = (SDL_Touch **) SDL_realloc(SDL_touchDevices,
166  (SDL_num_touch + 1) * sizeof(*touchDevices));
167  if (!touchDevices) {
168  return SDL_OutOfMemory();
169  }
170 
171  SDL_touchDevices = touchDevices;
173 
175  if (!SDL_touchDevices[index]) {
176  return SDL_OutOfMemory();
177  }
178 
179  /* Added touch to list */
180  ++SDL_num_touch;
181 
182  /* we're setting the touch properties */
183  SDL_touchDevices[index]->id = touchID;
188 
189  /* Record this touch device for gestures */
190  /* We could do this on the fly in the gesture code if we wanted */
191  SDL_GestureAddTouch(touchID);
192 
193  return index;
194 }
195 
196 static int
197 SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
198 {
199  SDL_Finger *finger;
200 
201  if (touch->num_fingers == touch->max_fingers) {
202  SDL_Finger **new_fingers;
203  new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers+1)*sizeof(*touch->fingers));
204  if (!new_fingers) {
205  return SDL_OutOfMemory();
206  }
207  touch->fingers = new_fingers;
208  touch->fingers[touch->max_fingers] = (SDL_Finger *)SDL_malloc(sizeof(*finger));
209  if (!touch->fingers[touch->max_fingers]) {
210  return SDL_OutOfMemory();
211  }
212  touch->max_fingers++;
213  }
214 
215  finger = touch->fingers[touch->num_fingers++];
216  finger->id = fingerid;
217  finger->x = x;
218  finger->y = y;
219  finger->pressure = pressure;
220  return 0;
221 }
222 
223 static int
225 {
226  SDL_Finger *temp;
227 
228  int index = SDL_GetFingerIndex(touch, fingerid);
229  if (index < 0) {
230  return -1;
231  }
232 
233  touch->num_fingers--;
234  temp = touch->fingers[index];
235  touch->fingers[index] = touch->fingers[touch->num_fingers];
236  touch->fingers[touch->num_fingers] = temp;
237  return 0;
238 }
239 
240 int
242  SDL_bool down, float x, float y, float pressure)
243 {
244  int posted;
245  SDL_Finger *finger;
246  SDL_Mouse *mouse;
247 
248  SDL_Touch* touch = SDL_GetTouch(id);
249  if (!touch) {
250  return -1;
251  }
252 
253  mouse = SDL_GetMouse();
254 
255 #if SYNTHESIZE_TOUCH_TO_MOUSE
256  /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
257  {
258  if (mouse->touch_mouse_events) {
259  /* FIXME: maybe we should only restrict to a few SDL_TouchDeviceType */
260  if (id != SDL_MOUSE_TOUCHID) {
261  if (window) {
262  if (down) {
263  if (finger_touching == SDL_FALSE) {
264  int pos_x = (int)(x * (float)window->w);
265  int pos_y = (int)(y * (float)window->h);
266  if (pos_x < 0) pos_x = 0;
267  if (pos_x > window->w - 1) pos_x = window->w - 1;
268  if (pos_y < 0) pos_y = 0;
269  if (pos_y > window->h - 1) pos_y = window->h - 1;
270  SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
272  }
273  } else {
274  if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
276  }
277  }
278  }
279  if (down) {
280  if (finger_touching == SDL_FALSE) {
282  track_touchid = id;
283  track_fingerid = fingerid;
284  }
285  } else {
286  if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
288  }
289  }
290  }
291  }
292  }
293 #endif
294 
295  /* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */
296  if (mouse->mouse_touch_events == 0) {
297  if (id == SDL_MOUSE_TOUCHID) {
298  return 0;
299  }
300  }
301 
302  finger = SDL_GetFinger(touch, fingerid);
303  if (down) {
304  if (finger) {
305  /* This finger is already down */
306  return 0;
307  }
308 
309  if (SDL_AddFinger(touch, fingerid, x, y, pressure) < 0) {
310  return 0;
311  }
312 
313  posted = 0;
316  event.tfinger.type = SDL_FINGERDOWN;
317  event.tfinger.touchId = id;
318  event.tfinger.fingerId = fingerid;
319  event.tfinger.x = x;
320  event.tfinger.y = y;
321  event.tfinger.dx = 0;
322  event.tfinger.dy = 0;
323  event.tfinger.pressure = pressure;
324  event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
325  posted = (SDL_PushEvent(&event) > 0);
326  }
327  } else {
328  if (!finger) {
329  /* This finger is already up */
330  return 0;
331  }
332 
333  posted = 0;
336  event.tfinger.type = SDL_FINGERUP;
337  event.tfinger.touchId = id;
338  event.tfinger.fingerId = fingerid;
339  /* I don't trust the coordinates passed on fingerUp */
340  event.tfinger.x = finger->x;
341  event.tfinger.y = finger->y;
342  event.tfinger.dx = 0;
343  event.tfinger.dy = 0;
344  event.tfinger.pressure = pressure;
345  event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
346  posted = (SDL_PushEvent(&event) > 0);
347  }
348 
349  SDL_DelFinger(touch, fingerid);
350  }
351  return posted;
352 }
353 
354 int
356  float x, float y, float pressure)
357 {
358  SDL_Touch *touch;
359  SDL_Finger *finger;
360  SDL_Mouse *mouse;
361  int posted;
362  float xrel, yrel, prel;
363 
364  touch = SDL_GetTouch(id);
365  if (!touch) {
366  return -1;
367  }
368 
369  mouse = SDL_GetMouse();
370 
371 #if SYNTHESIZE_TOUCH_TO_MOUSE
372  /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */
373  {
374  if (mouse->touch_mouse_events) {
375  if (id != SDL_MOUSE_TOUCHID) {
376  if (window) {
377  if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) {
378  int pos_x = (int)(x * (float)window->w);
379  int pos_y = (int)(y * (float)window->h);
380  if (pos_x < 0) pos_x = 0;
381  if (pos_x > window->w - 1) pos_x = window->w - 1;
382  if (pos_y < 0) pos_y = 0;
383  if (pos_y > window->h - 1) pos_y = window->h - 1;
384  SDL_SendMouseMotion(window, SDL_TOUCH_MOUSEID, 0, pos_x, pos_y);
385  }
386  }
387  }
388  }
389  }
390 #endif
391 
392  /* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */
393  if (mouse->mouse_touch_events == 0) {
394  if (id == SDL_MOUSE_TOUCHID) {
395  return 0;
396  }
397  }
398 
399  finger = SDL_GetFinger(touch,fingerid);
400  if (!finger) {
401  return SDL_SendTouch(id, fingerid, window, SDL_TRUE, x, y, pressure);
402  }
403 
404  xrel = x - finger->x;
405  yrel = y - finger->y;
406  prel = pressure - finger->pressure;
407 
408  /* Drop events that don't change state */
409  if (xrel == 0.0f && yrel == 0.0f && prel == 0.0f) {
410 #if 0
411  printf("Touch event didn't change state - dropped!\n");
412 #endif
413  return 0;
414  }
415 
416  /* Update internal touch coordinates */
417  finger->x = x;
418  finger->y = y;
419  finger->pressure = pressure;
420 
421  /* Post the event, if desired */
422  posted = 0;
425  event.tfinger.type = SDL_FINGERMOTION;
426  event.tfinger.touchId = id;
427  event.tfinger.fingerId = fingerid;
428  event.tfinger.x = x;
429  event.tfinger.y = y;
430  event.tfinger.dx = xrel;
431  event.tfinger.dy = yrel;
432  event.tfinger.pressure = pressure;
433  event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0;
434  posted = (SDL_PushEvent(&event) > 0);
435  }
436  return posted;
437 }
438 
439 void
441 {
442  int i;
443  int index = SDL_GetTouchIndex(id);
444  SDL_Touch *touch = SDL_GetTouch(id);
445 
446  if (!touch) {
447  return;
448  }
449 
450  for (i = 0; i < touch->max_fingers; ++i) {
451  SDL_free(touch->fingers[i]);
452  }
453  SDL_free(touch->fingers);
454  SDL_free(touch);
455 
456  SDL_num_touch--;
458 
459  /* Delete this touch device for gestures */
461 }
462 
463 void
465 {
466  int i;
467 
468  for (i = SDL_num_touch; i--; ) {
470  }
472 
475  SDL_GestureQuit();
476 }
477 
478 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_assert(condition)
Definition: SDL_assert.h:171
#define SDL_SetError
#define SDL_PushEvent
#define SDL_GetWindowID
#define SDL_malloc
#define SDL_realloc
#define SDL_free
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
@ SDL_FINGERMOTION
Definition: SDL_events.h:136
@ SDL_FINGERUP
Definition: SDL_events.h:135
@ SDL_FINGERDOWN
Definition: SDL_events.h:134
#define SDL_GetEventState(type)
Definition: SDL_events.h:808
#define SDL_RELEASED
Definition: SDL_events.h:49
#define SDL_ENABLE
Definition: SDL_events.h:795
#define SDL_PRESSED
Definition: SDL_events.h:50
int SDL_GestureAddTouch(SDL_TouchID touchId)
Definition: SDL_gesture.c:454
int SDL_GestureDelTouch(SDL_TouchID touchId)
Definition: SDL_gesture.c:472
void SDL_GestureQuit()
Definition: SDL_gesture.c:106
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:599
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:175
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:298
#define SDL_BUTTON_LEFT
Definition: SDL_mouse.h:282
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
struct _cl_event * event
GLuint index
GLuint id
GLuint const GLchar * name
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:587
static int SDL_DelFinger(SDL_Touch *touch, SDL_FingerID fingerid)
Definition: SDL_touch.c:224
SDL_TouchDeviceType SDL_GetTouchDeviceType(SDL_TouchID id)
Get the type of the given touch device.
Definition: SDL_touch.c:98
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:241
void SDL_DelTouch(SDL_TouchID id)
Definition: SDL_touch.c:440
static SDL_TouchID track_touchid
Definition: SDL_touch.c:40
int SDL_GetNumTouchDevices(void)
Get the number of registered touch devices.
Definition: SDL_touch.c:51
SDL_Touch * SDL_GetTouch(SDL_TouchID id)
Definition: SDL_touch.c:82
static SDL_Touch ** SDL_touchDevices
Definition: SDL_touch.c:31
static int SDL_GetTouchIndex(SDL_TouchID id)
Definition: SDL_touch.c:67
void SDL_TouchQuit(void)
Definition: SDL_touch.c:464
static int SDL_num_touch
Definition: SDL_touch.c:30
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:57
static int SDL_GetFingerIndex(const SDL_Touch *touch, SDL_FingerID fingerid)
Definition: SDL_touch.c:108
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:140
static SDL_FingerID track_fingerid
Definition: SDL_touch.c:39
int SDL_GetNumTouchFingers(SDL_TouchID touchID)
Get the number of active fingers for a given touch device.
Definition: SDL_touch.c:130
static int SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:197
static SDL_bool finger_touching
Definition: SDL_touch.c:38
int SDL_TouchInit(void)
Definition: SDL_touch.c:45
int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
Definition: SDL_touch.c:154
static SDL_Finger * SDL_GetFinger(const SDL_Touch *touch, SDL_FingerID id)
Definition: SDL_touch.c:120
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, float x, float y, float pressure)
Definition: SDL_touch.c:355
#define SDL_MOUSE_TOUCHID
Definition: SDL_touch.h:64
Sint64 SDL_FingerID
Definition: SDL_touch.h:42
SDL_TouchDeviceType
Definition: SDL_touch.h:45
@ SDL_TOUCH_DEVICE_INVALID
Definition: SDL_touch.h:46
Sint64 SDL_TouchID
Definition: SDL_touch.h:41
#define SDL_TOUCH_MOUSEID
Definition: SDL_touch.h:61
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 NULL
Definition: begin_code.h:163
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
float y
Definition: SDL_touch.h:56
float pressure
Definition: SDL_touch.h:57
SDL_FingerID id
Definition: SDL_touch.h:54
float x
Definition: SDL_touch.h:55
SDL_bool touch_mouse_events
Definition: SDL_mouse_c.h:95
SDL_bool mouse_touch_events
Definition: SDL_mouse_c.h:96
int max_fingers
Definition: SDL_touch_c.h:32
SDL_Finger ** fingers
Definition: SDL_touch_c.h:33
SDL_TouchID id
Definition: SDL_touch_c.h:29
SDL_TouchDeviceType type
Definition: SDL_touch_c.h:30
int num_fingers
Definition: SDL_touch_c.h:31
void(* ResetTouch)(_THIS)
Definition: SDL_sysvideo.h:173
The type used to identify a window.
Definition: SDL_sysvideo.h:75
General event structure.
Definition: SDL_events.h:592
typedef int(__stdcall *FARPROC)()