Skip to content

Commit de95567

Browse files
dos1SiegeLord
authored andcommitted
SDL: implement touch subsystem
1 parent 22f59eb commit de95567

File tree

4 files changed

+268
-1
lines changed

4 files changed

+268
-1
lines changed

cmake/FileList.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ set(ALLEGRO_SRC_SDL_FILES
205205
src/sdl/sdl_display.c
206206
src/sdl/sdl_keyboard.c
207207
src/sdl/sdl_mouse.c
208+
src/sdl/sdl_touch.c
208209
src/sdl/sdl_joystick.c
209210
src/sdl/sdl_event_hack.c
210211
)

include/allegro5/platform/allegro_internal_sdl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@ ALLEGRO_SYSTEM_INTERFACE *_al_sdl_system_driver(void);
2727
ALLEGRO_DISPLAY_INTERFACE *_al_sdl_display_driver(void);
2828
ALLEGRO_KEYBOARD_DRIVER *_al_sdl_keyboard_driver(void);
2929
ALLEGRO_MOUSE_DRIVER *_al_sdl_mouse_driver(void);
30+
ALLEGRO_TOUCH_INPUT_DRIVER *_al_sdl_touch_input_driver(void);
3031
ALLEGRO_JOYSTICK_DRIVER *_al_sdl_joystick_driver(void);
3132
ALLEGRO_BITMAP_INTERFACE *_al_sdl_bitmap_driver(void);
3233

3334
void _al_sdl_keyboard_event(SDL_Event *e);
3435
void _al_sdl_mouse_event(SDL_Event *e);
36+
void _al_sdl_touch_input_event(SDL_Event *e);
3537
void _al_sdl_display_event(SDL_Event *e);
3638
void _al_sdl_joystick_event(SDL_Event *e);
3739

src/sdl/sdl_system.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ static void sdl_heartbeat(void)
7373
case SDL_MOUSEWHEEL:
7474
_al_sdl_mouse_event(&event);
7575
break;
76+
case SDL_FINGERDOWN:
77+
case SDL_FINGERMOTION:
78+
case SDL_FINGERUP:
79+
_al_sdl_touch_input_event(&event);
80+
break;
7681
case SDL_JOYAXISMOTION:
7782
case SDL_JOYBUTTONDOWN:
7883
case SDL_JOYBUTTONUP:
@@ -191,6 +196,11 @@ static ALLEGRO_MOUSE_DRIVER *sdl_get_mouse_driver(void)
191196
return _al_sdl_mouse_driver();
192197
}
193198

199+
static ALLEGRO_TOUCH_INPUT_DRIVER *sdl_get_touch_input_driver(void)
200+
{
201+
return _al_sdl_touch_input_driver();
202+
}
203+
194204
static ALLEGRO_JOYSTICK_DRIVER *sdl_get_joystick_driver(void)
195205
{
196206
return _al_sdl_joystick_driver();
@@ -275,7 +285,7 @@ ALLEGRO_SYSTEM_INTERFACE *_al_sdl_system_driver(void)
275285
vt->get_display_driver = sdl_get_display_driver;
276286
vt->get_keyboard_driver = sdl_get_keyboard_driver;
277287
vt->get_mouse_driver = sdl_get_mouse_driver;
278-
//vt->get_touch_input_driver = sdl_get_touch_input_driver;
288+
vt->get_touch_input_driver = sdl_get_touch_input_driver;
279289
vt->get_joystick_driver = sdl_get_joystick_driver;
280290
//vt->get_haptic_driver = sdl_get_haptic_driver;
281291
vt->get_num_display_modes = sdl_get_num_display_modes;

src/sdl/sdl_touch.c

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
#include "allegro5/allegro.h"
2+
#include "allegro5/internal/aintern_system.h"
3+
#include "allegro5/platform/allegro_internal_sdl.h"
4+
5+
ALLEGRO_DEBUG_CHANNEL("SDL")
6+
7+
typedef struct ALLEGRO_TOUCH_INPUT_SDL
8+
{
9+
ALLEGRO_TOUCH_INPUT touch_input;
10+
ALLEGRO_TOUCH_INPUT_STATE state;
11+
ALLEGRO_DISPLAY *display;
12+
int touches;
13+
} ALLEGRO_TOUCH_INPUT_SDL;
14+
15+
static ALLEGRO_TOUCH_INPUT_DRIVER *vt;
16+
static ALLEGRO_TOUCH_INPUT_SDL *touch_input;
17+
static ALLEGRO_MOUSE_STATE mouse_state;
18+
19+
static void generate_touch_input_event(unsigned int type, double timestamp,
20+
int id, float x, float y, float dx, float dy, bool primary,
21+
ALLEGRO_DISPLAY *disp)
22+
{
23+
ALLEGRO_EVENT event;
24+
25+
bool want_touch_event = _al_event_source_needs_to_generate_event(&touch_input->touch_input.es);
26+
bool want_mouse_emulation_event;
27+
28+
if (touch_input->touch_input.mouse_emulation_mode == ALLEGRO_MOUSE_EMULATION_5_0_x) {
29+
want_mouse_emulation_event = _al_event_source_needs_to_generate_event(&touch_input->touch_input.mouse_emulation_es) && al_is_mouse_installed();
30+
}
31+
else {
32+
want_mouse_emulation_event = _al_event_source_needs_to_generate_event(&touch_input->touch_input.mouse_emulation_es) && primary && al_is_mouse_installed();
33+
}
34+
35+
if (touch_input->touch_input.mouse_emulation_mode == ALLEGRO_MOUSE_EMULATION_NONE)
36+
want_mouse_emulation_event = false;
37+
else if (touch_input->touch_input.mouse_emulation_mode == ALLEGRO_MOUSE_EMULATION_INCLUSIVE)
38+
want_touch_event = al_is_mouse_installed() ? (want_touch_event && !primary) : want_touch_event;
39+
else if (touch_input->touch_input.mouse_emulation_mode == ALLEGRO_MOUSE_EMULATION_EXCLUSIVE)
40+
want_touch_event = al_is_mouse_installed() ? false : want_touch_event;
41+
42+
43+
if (!want_touch_event && !want_mouse_emulation_event)
44+
return;
45+
46+
if (want_touch_event) {
47+
event.touch.type = type;
48+
event.touch.display = (ALLEGRO_DISPLAY*)disp;
49+
event.touch.timestamp = timestamp;
50+
event.touch.id = id;
51+
event.touch.x = x;
52+
event.touch.y = y;
53+
event.touch.dx = dx;
54+
event.touch.dy = dy;
55+
event.touch.primary = primary;
56+
57+
_al_event_source_lock(&touch_input->touch_input.es);
58+
_al_event_source_emit_event(&touch_input->touch_input.es, &event);
59+
_al_event_source_unlock(&touch_input->touch_input.es);
60+
}
61+
62+
if (touch_input->touch_input.mouse_emulation_mode != ALLEGRO_MOUSE_EMULATION_NONE) {
63+
mouse_state.x = (int)x;
64+
mouse_state.y = (int)y;
65+
if (type == ALLEGRO_EVENT_TOUCH_BEGIN)
66+
mouse_state.buttons++;
67+
else if (type == ALLEGRO_EVENT_TOUCH_END)
68+
mouse_state.buttons--;
69+
70+
mouse_state.pressure = mouse_state.buttons ? 1.0 : 0.0; /* TODO */
71+
72+
_al_event_source_lock(&touch_input->touch_input.mouse_emulation_es);
73+
if (want_mouse_emulation_event) {
74+
75+
switch (type) {
76+
case ALLEGRO_EVENT_TOUCH_BEGIN: type = ALLEGRO_EVENT_MOUSE_BUTTON_DOWN; break;
77+
case ALLEGRO_EVENT_TOUCH_CANCEL:
78+
case ALLEGRO_EVENT_TOUCH_END: type = ALLEGRO_EVENT_MOUSE_BUTTON_UP; break;
79+
case ALLEGRO_EVENT_TOUCH_MOVE: type = ALLEGRO_EVENT_MOUSE_AXES; break;
80+
}
81+
82+
event.mouse.type = type;
83+
event.mouse.timestamp = timestamp;
84+
event.mouse.display = (ALLEGRO_DISPLAY*)disp;
85+
event.mouse.x = (int)x;
86+
event.mouse.y = (int)y;
87+
event.mouse.dx = (int)dx;
88+
event.mouse.dy = (int)dy;
89+
event.mouse.dz = 0;
90+
event.mouse.dw = 0;
91+
if (touch_input->touch_input.mouse_emulation_mode != ALLEGRO_MOUSE_EMULATION_5_0_x) {
92+
event.mouse.button = 1;
93+
}
94+
else {
95+
event.mouse.button = id;
96+
}
97+
event.mouse.pressure = mouse_state.pressure;
98+
99+
if (touch_input->touch_input.mouse_emulation_mode != ALLEGRO_MOUSE_EMULATION_5_0_x) {
100+
al_set_mouse_xy(event.mouse.display, event.mouse.x, event.mouse.y);
101+
}
102+
103+
_al_event_source_emit_event(&touch_input->touch_input.mouse_emulation_es, &event);
104+
}
105+
_al_event_source_unlock(&touch_input->touch_input.mouse_emulation_es);
106+
}
107+
}
108+
109+
void _al_sdl_touch_input_event(SDL_Event *e)
110+
{
111+
if (!touch_input)
112+
return;
113+
114+
ALLEGRO_EVENT_TYPE type;
115+
116+
ALLEGRO_DISPLAY *d = NULL;
117+
/* Use the first display as event source if we have any displays. */
118+
ALLEGRO_SYSTEM *s = al_get_system_driver();
119+
if (_al_vector_size(&s->displays) > 0) {
120+
void **v = (void **)_al_vector_ref(&s->displays, 0);
121+
d = *v;
122+
}
123+
if (!d) {
124+
return;
125+
}
126+
127+
int touchId = e->tfinger.fingerId;
128+
129+
// SDL2 only returns absolute positions of touches on the input device. This means we have to fake them
130+
// in order to make them related to the display, which is what Allegro returns in its API.
131+
// This is likely to break in lots of cases, but should work well with non-rotated fullscreen or Wayland windows.
132+
// NOTE: SDL 2.0.10 is going to have SDL_GetTouchDeviceType API which may be somewhat helpful here.
133+
134+
touch_input->state.touches[touchId].x = e->tfinger.x * al_get_display_width(d);
135+
touch_input->state.touches[touchId].y = e->tfinger.y * al_get_display_height(d);
136+
touch_input->state.touches[touchId].dx = e->tfinger.dx * al_get_display_width(d);
137+
touch_input->state.touches[touchId].dy = e->tfinger.dy * al_get_display_height(d);
138+
139+
if (e->type == SDL_FINGERDOWN) {
140+
type = ALLEGRO_EVENT_TOUCH_BEGIN;
141+
touch_input->state.touches[touchId].id = touchId;
142+
touch_input->state.touches[touchId].primary = (touch_input->touches == 0);
143+
touch_input->touches++;
144+
}
145+
else if (e->type == SDL_FINGERMOTION) {
146+
type = ALLEGRO_EVENT_TOUCH_MOVE;
147+
}
148+
else if (e->type == SDL_FINGERUP) {
149+
type = ALLEGRO_EVENT_TOUCH_END;
150+
touch_input->touches--;
151+
touch_input->state.touches[touchId].id = -1;
152+
} else {
153+
return;
154+
}
155+
156+
generate_touch_input_event(type, e->tfinger.timestamp, touchId,
157+
touch_input->state.touches[touchId].x,
158+
touch_input->state.touches[touchId].y,
159+
touch_input->state.touches[touchId].dx,
160+
touch_input->state.touches[touchId].dy,
161+
touch_input->state.touches[touchId].primary,
162+
d);
163+
}
164+
165+
static bool sdl_init_touch_input(void)
166+
{
167+
touch_input = al_calloc(1, sizeof *touch_input);
168+
_al_event_source_init(&touch_input->touch_input.es);
169+
170+
_al_event_source_init(&touch_input->touch_input.mouse_emulation_es);
171+
touch_input->touch_input.mouse_emulation_mode = ALLEGRO_MOUSE_EMULATION_TRANSPARENT;
172+
173+
int i;
174+
for (i = 0; i < ALLEGRO_TOUCH_INPUT_MAX_TOUCH_COUNT; i++) {
175+
touch_input->state.touches[i].id = -1;
176+
}
177+
178+
return true;
179+
}
180+
181+
static void sdl_exit_touch_input(void)
182+
{
183+
}
184+
185+
static ALLEGRO_TOUCH_INPUT *sdl_get_touch_input(void)
186+
{
187+
return &touch_input->touch_input;
188+
}
189+
190+
191+
static void sdl_get_touch_input_state(ALLEGRO_TOUCH_INPUT_STATE *ret_state)
192+
{
193+
_al_event_source_lock(&touch_input->touch_input.es);
194+
*ret_state = touch_input->state;
195+
_al_event_source_unlock(&touch_input->touch_input.es);
196+
}
197+
198+
static void touch_input_handle_cancel(int index, size_t timestamp, float x, float y, bool primary, ALLEGRO_DISPLAY *disp)
199+
{
200+
ALLEGRO_TOUCH_STATE* state = touch_input->state.touches + index;
201+
(void)primary;
202+
203+
if (NULL == state)
204+
return;
205+
206+
_al_event_source_lock(&touch_input->touch_input.es);
207+
state->dx = x - state->x;
208+
state->dy = y - state->y;
209+
state->x = x;
210+
state->y = y;
211+
_al_event_source_unlock(&touch_input->touch_input.es);
212+
213+
generate_touch_input_event(ALLEGRO_EVENT_TOUCH_CANCEL, timestamp,
214+
state->id, state->x, state->y, state->dx, state->dy, state->primary, disp);
215+
216+
_al_event_source_lock(&touch_input->touch_input.es);
217+
state->id = -1;
218+
_al_event_source_unlock(&touch_input->touch_input.es);
219+
}
220+
221+
static void sdl_set_mouse_emulation_mode(int mode)
222+
{
223+
if (touch_input->touch_input.mouse_emulation_mode != mode) {
224+
225+
int i;
226+
227+
for (i = 0; i < ALLEGRO_TOUCH_INPUT_MAX_TOUCH_COUNT; ++i) {
228+
229+
ALLEGRO_TOUCH_STATE* touch = touch_input->state.touches + i;
230+
231+
if (touch->id > 0) {
232+
touch_input_handle_cancel(i, al_get_time(),
233+
touch->x, touch->y, touch->primary, touch->display);
234+
}
235+
}
236+
237+
touch_input->touch_input.mouse_emulation_mode = mode;
238+
}
239+
}
240+
241+
ALLEGRO_TOUCH_INPUT_DRIVER *_al_sdl_touch_input_driver(void)
242+
{
243+
if (vt)
244+
return vt;
245+
246+
vt = al_calloc(1, sizeof *vt);
247+
vt->init_touch_input = sdl_init_touch_input;
248+
vt->exit_touch_input = sdl_exit_touch_input;
249+
vt->get_touch_input = sdl_get_touch_input;
250+
vt->get_touch_input_state = sdl_get_touch_input_state;
251+
vt->set_mouse_emulation_mode = sdl_set_mouse_emulation_mode;
252+
253+
return vt;
254+
}

0 commit comments

Comments
 (0)