Skip to content

Latest commit

 

History

History
479 lines (414 loc) · 13.3 KB

SDL_touch.c

File metadata and controls

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