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
31static 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 */
45int
47{
48 return (0);
49}
50
51int
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
67static 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
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
108static int
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
120static 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
130int
132{
133 SDL_Touch *touch = SDL_GetTouch(touchID);
134 if (touch) {
135 return touch->num_fingers;
136 }
137 return 0;
138}
139
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
154int
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 */
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
197static int
198SDL_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
224static 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
241int
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;
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) {
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
363int
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;
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
448void
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
467
468 /* Delete this touch device for gestures */
470}
471
472void
474{
475 int i;
476
477 for (i = SDL_num_touch; i--; ) {
479 }
481
485}
486
487/* vi: set ts=4 sw=4 expandtab: */
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define SDL_SetError
#define SDL_PushEvent
#define SDL_GetKeyboardFocus
#define SDL_malloc
#define SDL_realloc
#define SDL_free
#define SDL_GetMouseFocus
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
@ SDL_FINGERMOTION
Definition: SDL_events.h:130
@ SDL_FINGERUP
Definition: SDL_events.h:129
@ SDL_FINGERDOWN
Definition: SDL_events.h:128
#define SDL_GetEventState(type)
Definition: SDL_events.h:772
#define SDL_RELEASED
Definition: SDL_events.h:49
#define SDL_ENABLE
Definition: SDL_events.h:759
#define SDL_PRESSED
Definition: SDL_events.h:50
int SDL_GestureAddTouch(SDL_TouchID touchId)
Definition: SDL_gesture.c:450
int SDL_GestureDelTouch(SDL_TouchID touchId)
Definition: SDL_gesture.c:468
void SDL_GestureQuit()
Definition: SDL_gesture.c:104
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:605
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:178
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
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:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:583
static int SDL_DelFinger(SDL_Touch *touch, SDL_FingerID fingerid)
Definition: SDL_touch.c:225
SDL_TouchDeviceType SDL_GetTouchDeviceType(SDL_TouchID id)
Get the type of the given touch device.
Definition: SDL_touch.c:99
static SDL_Finger * SDL_GetFinger(const SDL_Touch *touch, SDL_FingerID id)
Definition: SDL_touch.c:121
void SDL_DelTouch(SDL_TouchID id)
Definition: SDL_touch.c:449
static SDL_TouchID track_touchid
Definition: SDL_touch.c:41
int SDL_GetNumTouchDevices(void)
Get the number of registered touch devices.
Definition: SDL_touch.c:52
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_Touch ** SDL_touchDevices
Definition: SDL_touch.c:32
static int SDL_GetTouchIndex(SDL_TouchID id)
Definition: SDL_touch.c:68
void SDL_TouchQuit(void)
Definition: SDL_touch.c:473
static int SDL_num_touch
Definition: SDL_touch.c:31
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
static int SDL_GetFingerIndex(const SDL_Touch *touch, SDL_FingerID fingerid)
Definition: SDL_touch.c:109
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:364
static SDL_FingerID track_fingerid
Definition: SDL_touch.c:40
int SDL_GetNumTouchFingers(SDL_TouchID touchID)
Get the number of active fingers for a given touch device.
Definition: SDL_touch.c:131
static int SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure)
Definition: SDL_touch.c:198
static SDL_bool finger_touching
Definition: SDL_touch.c:39
int SDL_TouchInit(void)
Definition: SDL_touch.c:46
SDL_Touch * SDL_GetTouch(SDL_TouchID id)
Definition: SDL_touch.c:83
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
int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name)
Definition: SDL_touch.c:155
#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:167
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:172
The type used to identify a window.
Definition: SDL_sysvideo.h:74
General event structure.
Definition: SDL_events.h:558