comparison src/events/SDL_touch.c @ 4640:f068a6dfc858

Added SDL_touch.c/SDL_touch_c.h as slightly modifeind SDL_mouse*. Made reads in touchSimp non-blocking.
author Jim Grandpre <jim.tla@gmail.com>
date Tue, 25 May 2010 23:23:23 -0400
parents
children 49a97daea6ec
comparison
equal deleted inserted replaced
4639:f5cd4b6231ba 4640:f068a6dfc858
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2010 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 /* General touch handling code for SDL */
25
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;
32 static int SDL_current_touch = -1;
33 static SDL_Touch **SDL_touch = NULL;
34
35
36 /* Public functions */
37 int
38 SDL_TouchInit(void)
39 {
40 return (0);
41 }
42
43 SDL_Touch *
44 SDL_GetTouch(int index)
45 {
46 if (index < 0 || index >= SDL_num_touch) {
47 return NULL;
48 }
49 return SDL_touch[index];
50 }
51
52 static int
53 SDL_GetTouchIndexId(int id)
54 {
55 int index;
56 SDL_Touch *touch;
57
58 for (index = 0; index < SDL_num_touch; ++index) {
59 touch = SDL_GetTouch(index);
60 if (touch->id == id) {
61 return index;
62 }
63 }
64 return -1;
65 }
66
67 int
68 SDL_AddTouch(const SDL_Touch * touch, char *name, int pressure_max,
69 int pressure_min, int ends)
70 {
71 SDL_Touch **touch;
72 int selected_touch;
73 int index;
74 size_t length;
75
76 if (SDL_GetTouchIndexId(touch->id) != -1) {
77 SDL_SetError("Touch ID already in use");
78 }
79
80 /* Add the touch to the list of touch */
81 touch = (SDL_Touch **) SDL_realloc(SDL_touch,
82 (SDL_num_touch + 1) * sizeof(*touch));
83 if (!touch) {
84 SDL_OutOfMemory();
85 return -1;
86 }
87
88 SDL_touch = touch;
89 index = SDL_num_touch++;
90
91 SDL_touch[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touch[index]));
92 if (!SDL_touch[index]) {
93 SDL_OutOfMemory();
94 return -1;
95 }
96 *SDL_touch[index] = *touch;
97
98 /* we're setting the touch properties */
99 length = 0;
100 length = SDL_strlen(name);
101 SDL_touch[index]->focus = 0;
102 SDL_touch[index]->name = SDL_malloc((length + 2) * sizeof(char));
103 SDL_strlcpy(SDL_touch[index]->name, name, length + 1);
104 SDL_touch[index]->pressure_max = pressure_max;
105 SDL_touch[index]->pressure_min = pressure_min;
106 SDL_touch[index]->cursor_shown = SDL_TRUE;
107 selected_touch = SDL_SelectTouch(index);
108 SDL_touch[index]->cur_cursor = NULL;
109 SDL_touch[index]->def_cursor =
110 /* we're assuming that all touch are in the computer sensing zone */
111 SDL_touch[index]->proximity = SDL_TRUE;
112 /* we're assuming that all touch are working in the absolute position mode
113 thanx to that, the users that don't want to use many touch don't have to
114 worry about anything */
115 SDL_touch[index]->relative_mode = SDL_FALSE;
116 SDL_touch[index]->current_end = 0;
117 SDL_touch[index]->total_ends = ends;
118 SDL_SelectTouch(selected_touch);
119
120 return index;
121 }
122
123 void
124 SDL_DelTouch(int index)
125 {
126 SDL_Touch *touch = SDL_GetTouch(index);
127
128 if (!touch) {
129 return;
130 }
131
132 touch->def_cursor = NULL;
133 SDL_free(touch->name);
134
135 if (touch->FreeTouch) {
136 touch->FreeTouch(touch);
137 }
138 SDL_free(touch);
139
140 SDL_touch[index] = NULL;
141 }
142
143 void
144 SDL_ResetTouch(int index)
145 {
146 SDL_Touch *touch = SDL_GetTouch(index);
147
148 if (!touch) {
149 return;
150 }
151
152 /* FIXME */
153 }
154
155 void
156 SDL_TouchQuit(void)
157 {
158 int i;
159
160 for (i = 0; i < SDL_num_touch; ++i) {
161 SDL_DelTouch(i);
162 }
163 SDL_num_touch = 0;
164 SDL_current_touch = -1;
165
166 if (SDL_touch) {
167 SDL_free(SDL_touch);
168 SDL_touch = NULL;
169 }
170 }
171
172 int
173 SDL_GetNumTouch(void)
174 {
175 return SDL_num_touch;
176 }
177
178 int
179 SDL_SelectTouch(int index)
180 {
181 if (index >= 0 && index < SDL_num_touch) {
182 SDL_current_touch = index;
183 }
184 return SDL_current_touch;
185 }
186
187 SDL_Window *
188 SDL_GetTouchFocusWindow(int index)
189 {
190 SDL_Touch *touch = SDL_GetTouch(index);
191
192 if (!touch) {
193 return 0;
194 }
195 return touch->focus;
196 }
197
198 static int SDLCALL
199 FlushTouchMotion(void *param, SDL_Event * event)
200 {
201 if (event->type == SDL_TOUCHMOTION
202 && event->motion.which == (Uint8) SDL_current_touch) {
203 return 0;
204 } else {
205 return 1;
206 }
207 }
208
209 int
210 SDL_SetRelativeTouchMode(int index, SDL_bool enabled)
211 {
212 SDL_Touch *touch = SDL_GetTouch(index);
213
214 if (!touch) {
215 return -1;
216 }
217
218 /* Flush pending touch motion */
219 touch->flush_motion = SDL_TRUE;
220 SDL_PumpEvents();
221 touch->flush_motion = SDL_FALSE;
222 SDL_FilterEvents(FlushTouchMotion, touch);
223
224 /* Set the relative mode */
225 touch->relative_mode = enabled;
226
227
228
229 if (!enabled) {
230 /* Restore the expected touch position */
231 SDL_WarpTouchInWindow(touch->focus, touch->x, touch->y);
232 }
233 return 0;
234 }
235
236 SDL_bool
237 SDL_GetRelativeTouchMode(int index)
238 {
239 SDL_Touch *touch = SDL_GetTouch(index);
240
241 if (!touch) {
242 return SDL_FALSE;
243 }
244 return touch->relative_mode;
245 }
246
247 Uint8
248 SDL_GetTouchState(int *x, int *y)
249 {
250 SDL_Touch *touch = SDL_GetTouch(SDL_current_touch);
251
252 if (!touch) {
253 if (x) {
254 *x = 0;
255 }
256 if (y) {
257 *y = 0;
258 }
259 return 0;
260 }
261
262 if (x) {
263 *x = touch->x;
264 }
265 if (y) {
266 *y = touch->y;
267 }
268 return touch->buttonstate;
269 }
270
271 Uint8
272 SDL_GetRelativeTouchState(int index, int *x, int *y)
273 {
274 SDL_Touch *touch = SDL_GetTouch(index);
275
276 if (!touch) {
277 if (x) {
278 *x = 0;
279 }
280 if (y) {
281 *y = 0;
282 }
283 return 0;
284 }
285
286 if (x) {
287 *x = touch->xdelta;
288 }
289 if (y) {
290 *y = touch->ydelta;
291 }
292 touch->xdelta = 0;
293 touch->ydelta = 0;
294 return touch->buttonstate;
295 }
296
297 void
298 SDL_SetTouchFocus(int id, SDL_Window * window)
299 {
300 int index = SDL_GetTouchIndexId(id);
301 SDL_Touch *touch = SDL_GetTouch(index);
302 int i;
303 SDL_bool focus;
304
305 if (!touch || (touch->focus == window)) {
306 return;
307 }
308
309 /* See if the current window has lost focus */
310 if (touch->focus) {
311 focus = SDL_FALSE;
312 for (i = 0; i < SDL_num_touch; ++i) {
313 SDL_Touch *check;
314 if (i != index) {
315 check = SDL_GetTouch(i);
316 if (check && check->focus == touch->focus) {
317 focus = SDL_TRUE;
318 break;
319 }
320 }
321 }
322 if (!focus) {
323 SDL_SendWindowEvent(touch->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
324 }
325 }
326
327 touch->focus = window;
328
329 if (touch->focus) {
330 focus = SDL_FALSE;
331 for (i = 0; i < SDL_num_touch; ++i) {
332 SDL_Touch *check;
333 if (i != index) {
334 check = SDL_GetTouch(i);
335 if (check && check->focus == touch->focus) {
336 focus = SDL_TRUE;
337 break;
338 }
339 }
340 }
341 if (!focus) {
342 SDL_SendWindowEvent(touch->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
343 }
344 }
345 }
346
347 int
348 SDL_SendProximity(int id, int x, int y, int type)
349 {
350 int index = SDL_GetTouchIndexId(id);
351 SDL_Touch *touch = SDL_GetTouch(index);
352 int posted = 0;
353
354 if (!touch) {
355 return 0;
356 }
357
358 touch->last_x = x;
359 touch->last_y = y;
360 if (SDL_GetEventState(type) == SDL_ENABLE) {
361 SDL_Event event;
362 event.proximity.which = (Uint8) index;
363 event.proximity.x = x;
364 event.proximity.y = y;
365 event.proximity.cursor = touch->current_end;
366 event.proximity.type = type;
367 /* FIXME: is this right? */
368 event.proximity.windowID = touch->focus ? touch->focus->id : 0;
369 posted = (SDL_PushEvent(&event) > 0);
370 if (type == SDL_PROXIMITYIN) {
371 touch->proximity = SDL_TRUE;
372 } else {
373 touch->proximity = SDL_FALSE;
374 }
375 }
376 return posted;
377 }
378
379 int
380 SDL_SendTouchMotion(int id, int relative, int x, int y, int pressure)
381 {
382 int index = SDL_GetTouchIndexId(id);
383 SDL_Touch *touch = SDL_GetTouch(index);
384 int posted;
385 int xrel;
386 int yrel;
387 int x_max = 0, y_max = 0;
388
389 if (!touch || touch->flush_motion) {
390 return 0;
391 }
392
393 /* if the touch is out of proximity we don't to want to have any motion from it */
394 if (touch->proximity == SDL_FALSE) {
395 touch->last_x = x;
396 touch->last_y = y;
397 return 0;
398 }
399
400 /* the relative motion is calculated regarding the system cursor last position */
401 if (relative) {
402 xrel = x;
403 yrel = y;
404 x = (touch->last_x + x);
405 y = (touch->last_y + y);
406 } else {
407 xrel = x - touch->last_x;
408 yrel = y - touch->last_y;
409 }
410
411 /* Drop events that don't change state */
412 if (!xrel && !yrel) {
413 #if 0
414 printf("Touch event didn't change state - dropped!\n");
415 #endif
416 return 0;
417 }
418
419 /* Update internal touch coordinates */
420 if (touch->relative_mode == SDL_FALSE) {
421 touch->x = x;
422 touch->y = y;
423 } else {
424 touch->x += xrel;
425 touch->y += yrel;
426 }
427
428 SDL_GetWindowSize(touch->focus, &x_max, &y_max);
429
430 /* make sure that the pointers find themselves inside the windows */
431 /* only check if touch->xmax is set ! */
432 if (x_max && touch->x > x_max) {
433 touch->x = x_max;
434 } else if (touch->x < 0) {
435 touch->x = 0;
436 }
437
438 if (y_max && touch->y > y_max) {
439 touch->y = y_max;
440 } else if (touch->y < 0) {
441 touch->y = 0;
442 }
443
444 touch->xdelta += xrel;
445 touch->ydelta += yrel;
446 touch->pressure = pressure;
447
448
449
450 /* Post the event, if desired */
451 posted = 0;
452 if (SDL_GetEventState(SDL_TOUCHMOTION) == SDL_ENABLE &&
453 touch->proximity == SDL_TRUE) {
454 SDL_Event event;
455 event.motion.type = SDL_TOUCHMOTION;
456 event.motion.which = (Uint8) index;
457 event.motion.state = touch->buttonstate;
458 event.motion.x = touch->x;
459 event.motion.y = touch->y;
460 event.motion.z = touch->z;
461 event.motion.pressure = touch->pressure;
462 event.motion.pressure_max = touch->pressure_max;
463 event.motion.pressure_min = touch->pressure_min;
464 event.motion.rotation = 0;
465 event.motion.tilt_x = 0;
466 event.motion.tilt_y = 0;
467 event.motion.cursor = touch->current_end;
468 event.motion.xrel = xrel;
469 event.motion.yrel = yrel;
470 event.motion.windowID = touch->focus ? touch->focus->id : 0;
471 posted = (SDL_PushEvent(&event) > 0);
472 }
473 touch->last_x = touch->x;
474 touch->last_y = touch->y;
475 return posted;
476 }
477
478 int
479 SDL_SendTouchButton(int id, Uint8 state, Uint8 button)
480 {
481 int index = SDL_GetTouchIndexId(id);
482 SDL_Touch *touch = SDL_GetTouch(index);
483 int posted;
484 Uint32 type;
485
486 if (!touch) {
487 return 0;
488 }
489
490 /* Figure out which event to perform */
491 switch (state) {
492 case SDL_PRESSED:
493 if (touch->buttonstate & SDL_BUTTON(button)) {
494 /* Ignore this event, no state change */
495 return 0;
496 }
497 type = SDL_TOUCHBUTTONDOWN;
498 touch->buttonstate |= SDL_BUTTON(button);
499 break;
500 case SDL_RELEASED:
501 if (!(touch->buttonstate & SDL_BUTTON(button))) {
502 /* Ignore this event, no state change */
503 return 0;
504 }
505 type = SDL_TOUCHBUTTONUP;
506 touch->buttonstate &= ~SDL_BUTTON(button);
507 break;
508 default:
509 /* Invalid state -- bail */
510 return 0;
511 }
512
513 /* Post the event, if desired */
514 posted = 0;
515 if (SDL_GetEventState(type) == SDL_ENABLE) {
516 SDL_Event event;
517 event.type = type;
518 event.button.which = (Uint8) index;
519 event.button.state = state;
520 event.button.button = button;
521 event.button.x = touch->x;
522 event.button.y = touch->y;
523 event.button.windowID = touch->focus ? touch->focus->id : 0;
524 posted = (SDL_PushEvent(&event) > 0);
525 }
526 return posted;
527 }
528
529 int
530 SDL_SendTouchWheel(int index, int x, int y)
531 {
532 SDL_Touch *touch = SDL_GetTouch(index);
533 int posted;
534
535 if (!touch || (!x && !y)) {
536 return 0;
537 }
538
539 /* Post the event, if desired */
540 posted = 0;
541 if (SDL_GetEventState(SDL_TOUCHWHEEL) == SDL_ENABLE) {
542 SDL_Event event;
543 event.type = SDL_TOUCHWHEEL;
544 event.wheel.which = (Uint8) index;
545 event.wheel.x = x;
546 event.wheel.y = y;
547 event.wheel.windowID = touch->focus ? touch->focus->id : 0;
548 posted = (SDL_PushEvent(&event) > 0);
549 }
550 return posted;
551 }
552
553
554 char *
555 SDL_GetTouchName(int index)
556 {
557 SDL_Touch *touch = SDL_GetTouch(index);
558 if (!touch) {
559 return NULL;
560 }
561 return touch->name;
562 }
563
564 void
565 SDL_ChangeEnd(int id, int end)
566 {
567 int index = SDL_GetTouchIndexId(id);
568 SDL_Touch *touch = SDL_GetTouch(index);
569
570 if (touch) {
571 touch->current_end = end;
572 }
573 }
574
575 /* vi: set ts=4 sw=4 expandtab: */