gabomdq@7753
|
1 |
/*
|
gabomdq@7753
|
2 |
Simple DirectMedia Layer
|
slouken@12503
|
3 |
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
|
gabomdq@7753
|
4 |
|
gabomdq@7753
|
5 |
This software is provided 'as-is', without any express or implied
|
gabomdq@7753
|
6 |
warranty. In no event will the authors be held liable for any damages
|
gabomdq@7753
|
7 |
arising from the use of this software.
|
gabomdq@7753
|
8 |
|
gabomdq@7753
|
9 |
Permission is granted to anyone to use this software for any purpose,
|
gabomdq@7753
|
10 |
including commercial applications, and to alter it and redistribute it
|
gabomdq@7753
|
11 |
freely, subject to the following restrictions:
|
gabomdq@7753
|
12 |
|
gabomdq@7753
|
13 |
1. The origin of this software must not be misrepresented; you must not
|
gabomdq@7753
|
14 |
claim that you wrote the original software. If you use this software
|
gabomdq@7753
|
15 |
in a product, an acknowledgment in the product documentation would be
|
gabomdq@7753
|
16 |
appreciated but is not required.
|
gabomdq@7753
|
17 |
2. Altered source versions must be plainly marked as such, and must not be
|
gabomdq@7753
|
18 |
misrepresented as being the original software.
|
gabomdq@7753
|
19 |
3. This notice may not be removed or altered from any source distribution.
|
gabomdq@7753
|
20 |
*/
|
icculus@8093
|
21 |
#include "../../SDL_internal.h"
|
gabomdq@7753
|
22 |
|
gabomdq@7753
|
23 |
#ifdef SDL_INPUT_LINUXEV
|
gabomdq@7753
|
24 |
|
gabomdq@7753
|
25 |
/* This is based on the linux joystick driver */
|
gabomdq@7753
|
26 |
/* References: https://www.kernel.org/doc/Documentation/input/input.txt
|
gabomdq@7753
|
27 |
* https://www.kernel.org/doc/Documentation/input/event-codes.txt
|
gabomdq@7753
|
28 |
* /usr/include/linux/input.h
|
gabomdq@7753
|
29 |
* The evtest application is also useful to debug the protocol
|
gabomdq@7753
|
30 |
*/
|
gabomdq@7753
|
31 |
|
gabomdq@7753
|
32 |
#include "SDL_evdev.h"
|
slouken@10797
|
33 |
#include "SDL_evdev_kbd.h"
|
gabomdq@7753
|
34 |
|
gabomdq@7753
|
35 |
#include <sys/stat.h>
|
gabomdq@7753
|
36 |
#include <unistd.h>
|
gabomdq@7753
|
37 |
#include <fcntl.h>
|
gabomdq@7753
|
38 |
#include <sys/ioctl.h>
|
gabomdq@7778
|
39 |
#include <linux/input.h>
|
gabomdq@7809
|
40 |
|
gabomdq@7753
|
41 |
#include "SDL.h"
|
gabomdq@7753
|
42 |
#include "SDL_assert.h"
|
gabomdq@7753
|
43 |
#include "SDL_endian.h"
|
gabomdq@7753
|
44 |
#include "SDL_scancode.h"
|
gabomdq@7753
|
45 |
#include "../../events/SDL_events_c.h"
|
slouken@10433
|
46 |
#include "../../events/scancodes_linux.h" /* adds linux_scancode_table */
|
slouken@10797
|
47 |
#include "../../core/linux/SDL_udev.h"
|
gabomdq@7753
|
48 |
|
slouken@10785
|
49 |
/* These are not defined in older Linux kernel headers */
|
gabomdq@7753
|
50 |
#ifndef SYN_DROPPED
|
gabomdq@7753
|
51 |
#define SYN_DROPPED 3
|
gabomdq@7753
|
52 |
#endif
|
slouken@10566
|
53 |
#ifndef ABS_MT_SLOT
|
slouken@10566
|
54 |
#define ABS_MT_SLOT 0x2f
|
slouken@10566
|
55 |
#define ABS_MT_POSITION_X 0x35
|
slouken@10566
|
56 |
#define ABS_MT_POSITION_Y 0x36
|
slouken@10566
|
57 |
#define ABS_MT_TRACKING_ID 0x39
|
icculus@12547
|
58 |
#define ABS_MT_PRESSURE 0x3a
|
slouken@10566
|
59 |
#endif
|
slouken@10566
|
60 |
|
slouken@10433
|
61 |
typedef struct SDL_evdevlist_item
|
slouken@10433
|
62 |
{
|
slouken@10433
|
63 |
char *path;
|
slouken@10433
|
64 |
int fd;
|
slouken@10797
|
65 |
|
slouken@10433
|
66 |
/* TODO: use this for every device, not just touchscreen */
|
slouken@10433
|
67 |
int out_of_sync;
|
slouken@10797
|
68 |
|
slouken@10433
|
69 |
/* TODO: expand on this to have data for every possible class (mouse,
|
slouken@10433
|
70 |
keyboard, touchpad, etc.). Also there's probably some things in here we
|
slouken@10433
|
71 |
can pull out to the SDL_evdevlist_item i.e. name */
|
slouken@10433
|
72 |
int is_touchscreen;
|
slouken@10433
|
73 |
struct {
|
slouken@10433
|
74 |
char* name;
|
slouken@10797
|
75 |
|
slouken@10433
|
76 |
int min_x, max_x, range_x;
|
slouken@10433
|
77 |
int min_y, max_y, range_y;
|
icculus@12547
|
78 |
int min_pressure, max_pressure, range_pressure;
|
slouken@10797
|
79 |
|
slouken@10433
|
80 |
int max_slots;
|
slouken@10433
|
81 |
int current_slot;
|
slouken@10433
|
82 |
struct {
|
slouken@10433
|
83 |
enum {
|
slouken@10433
|
84 |
EVDEV_TOUCH_SLOTDELTA_NONE = 0,
|
slouken@10433
|
85 |
EVDEV_TOUCH_SLOTDELTA_DOWN,
|
slouken@10433
|
86 |
EVDEV_TOUCH_SLOTDELTA_UP,
|
slouken@10433
|
87 |
EVDEV_TOUCH_SLOTDELTA_MOVE
|
slouken@10433
|
88 |
} delta;
|
slouken@10433
|
89 |
int tracking_id;
|
icculus@12547
|
90 |
int x, y, pressure;
|
slouken@10433
|
91 |
} * slots;
|
icculus@12547
|
92 |
|
slouken@10433
|
93 |
} * touchscreen_data;
|
slouken@10797
|
94 |
|
slouken@10433
|
95 |
struct SDL_evdevlist_item *next;
|
slouken@10433
|
96 |
} SDL_evdevlist_item;
|
slouken@10433
|
97 |
|
slouken@10433
|
98 |
typedef struct SDL_EVDEV_PrivateData
|
slouken@10433
|
99 |
{
|
slouken@10797
|
100 |
int ref_count;
|
slouken@10797
|
101 |
int num_devices;
|
slouken@10433
|
102 |
SDL_evdevlist_item *first;
|
slouken@10433
|
103 |
SDL_evdevlist_item *last;
|
slouken@10797
|
104 |
SDL_EVDEV_keyboard_state *kbd;
|
slouken@10433
|
105 |
} SDL_EVDEV_PrivateData;
|
slouken@10433
|
106 |
|
sezeroz@12160
|
107 |
#undef _THIS
|
slouken@10433
|
108 |
#define _THIS SDL_EVDEV_PrivateData *_this
|
slouken@10433
|
109 |
static _THIS = NULL;
|
slouken@10433
|
110 |
|
gabomdq@7755
|
111 |
static SDL_Scancode SDL_EVDEV_translate_keycode(int keycode);
|
gabomdq@7755
|
112 |
static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item);
|
slouken@10433
|
113 |
static int SDL_EVDEV_device_removed(const char *dev_path);
|
gabomdq@7753
|
114 |
|
gabomdq@7755
|
115 |
#if SDL_USE_LIBUDEV
|
slouken@10445
|
116 |
static int SDL_EVDEV_device_added(const char *dev_path, int udev_class);
|
philipp@11094
|
117 |
static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class,
|
slouken@10445
|
118 |
const char *dev_path);
|
gabomdq@7755
|
119 |
#endif /* SDL_USE_LIBUDEV */
|
gabomdq@7753
|
120 |
|
gabomdq@7753
|
121 |
static Uint8 EVDEV_MouseButtons[] = {
|
gabomdq@7753
|
122 |
SDL_BUTTON_LEFT, /* BTN_LEFT 0x110 */
|
gabomdq@7753
|
123 |
SDL_BUTTON_RIGHT, /* BTN_RIGHT 0x111 */
|
gabomdq@7753
|
124 |
SDL_BUTTON_MIDDLE, /* BTN_MIDDLE 0x112 */
|
gabomdq@7753
|
125 |
SDL_BUTTON_X1, /* BTN_SIDE 0x113 */
|
gabomdq@7753
|
126 |
SDL_BUTTON_X2, /* BTN_EXTRA 0x114 */
|
gabomdq@7753
|
127 |
SDL_BUTTON_X2 + 1, /* BTN_FORWARD 0x115 */
|
gabomdq@7753
|
128 |
SDL_BUTTON_X2 + 2, /* BTN_BACK 0x116 */
|
gabomdq@7753
|
129 |
SDL_BUTTON_X2 + 3 /* BTN_TASK 0x117 */
|
gabomdq@7753
|
130 |
};
|
gabomdq@7753
|
131 |
|
slouken@12927
|
132 |
static int
|
slouken@12927
|
133 |
SDL_EVDEV_SetRelativeMouseMode(SDL_bool enabled)
|
slouken@12927
|
134 |
{
|
slouken@12927
|
135 |
/* Mice already send relative events through this interface */
|
slouken@12927
|
136 |
return 0;
|
slouken@12927
|
137 |
}
|
slouken@12927
|
138 |
|
slouken@12927
|
139 |
|
gabomdq@7753
|
140 |
int
|
gabomdq@7753
|
141 |
SDL_EVDEV_Init(void)
|
gabomdq@7753
|
142 |
{
|
slouken@10445
|
143 |
if (_this == NULL) {
|
slouken@10445
|
144 |
_this = (SDL_EVDEV_PrivateData*)SDL_calloc(1, sizeof(*_this));
|
slouken@10445
|
145 |
if (_this == NULL) {
|
gabomdq@7753
|
146 |
return SDL_OutOfMemory();
|
gabomdq@7753
|
147 |
}
|
gabomdq@7753
|
148 |
|
gabomdq@7753
|
149 |
#if SDL_USE_LIBUDEV
|
slouken@10445
|
150 |
if (SDL_UDEV_Init() < 0) {
|
slouken@10445
|
151 |
SDL_free(_this);
|
gabomdq@7753
|
152 |
_this = NULL;
|
gabomdq@7753
|
153 |
return -1;
|
gabomdq@7753
|
154 |
}
|
gabomdq@7753
|
155 |
|
gabomdq@7753
|
156 |
/* Set up the udev callback */
|
slouken@9780
|
157 |
if (SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback) < 0) {
|
slouken@10433
|
158 |
SDL_UDEV_Quit();
|
slouken@10445
|
159 |
SDL_free(_this);
|
slouken@10433
|
160 |
_this = NULL;
|
gabomdq@7753
|
161 |
return -1;
|
gabomdq@7753
|
162 |
}
|
slouken@10797
|
163 |
|
gabomdq@7753
|
164 |
/* Force a scan to build the initial device list */
|
gabomdq@7753
|
165 |
SDL_UDEV_Scan();
|
gabomdq@7753
|
166 |
#else
|
gabomdq@7753
|
167 |
/* TODO: Scan the devices manually, like a caveman */
|
gabomdq@7753
|
168 |
#endif /* SDL_USE_LIBUDEV */
|
slouken@10784
|
169 |
|
slouken@10797
|
170 |
_this->kbd = SDL_EVDEV_kbd_init();
|
slouken@10797
|
171 |
}
|
slouken@10784
|
172 |
|
slouken@12927
|
173 |
SDL_GetMouse()->SetRelativeMouseMode = SDL_EVDEV_SetRelativeMouseMode;
|
slouken@12927
|
174 |
|
gabomdq@7753
|
175 |
_this->ref_count += 1;
|
slouken@10797
|
176 |
|
slouken@10433
|
177 |
return 0;
|
gabomdq@7753
|
178 |
}
|
gabomdq@7753
|
179 |
|
gabomdq@7753
|
180 |
void
|
gabomdq@7753
|
181 |
SDL_EVDEV_Quit(void)
|
gabomdq@7753
|
182 |
{
|
slouken@10445
|
183 |
if (_this == NULL) {
|
gabomdq@7753
|
184 |
return;
|
gabomdq@7753
|
185 |
}
|
slouken@10797
|
186 |
|
gabomdq@7753
|
187 |
_this->ref_count -= 1;
|
slouken@10797
|
188 |
|
slouken@10445
|
189 |
if (_this->ref_count < 1) {
|
gabomdq@7753
|
190 |
#if SDL_USE_LIBUDEV
|
slouken@10445
|
191 |
SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback);
|
gabomdq@7753
|
192 |
SDL_UDEV_Quit();
|
gabomdq@7753
|
193 |
#endif /* SDL_USE_LIBUDEV */
|
slouken@10797
|
194 |
|
slouken@10797
|
195 |
SDL_EVDEV_kbd_quit(_this->kbd);
|
slouken@10797
|
196 |
|
gabomdq@7753
|
197 |
/* Remove existing devices */
|
gabomdq@7753
|
198 |
while(_this->first != NULL) {
|
slouken@10445
|
199 |
SDL_EVDEV_device_removed(_this->first->path);
|
gabomdq@7753
|
200 |
}
|
slouken@10797
|
201 |
|
slouken@10445
|
202 |
SDL_assert(_this->first == NULL);
|
slouken@10445
|
203 |
SDL_assert(_this->last == NULL);
|
slouken@10445
|
204 |
SDL_assert(_this->num_devices == 0);
|
slouken@10797
|
205 |
|
slouken@10445
|
206 |
SDL_free(_this);
|
gabomdq@7753
|
207 |
_this = NULL;
|
gabomdq@7753
|
208 |
}
|
gabomdq@7753
|
209 |
}
|
gabomdq@7753
|
210 |
|
gabomdq@7755
|
211 |
#if SDL_USE_LIBUDEV
|
philipp@11094
|
212 |
static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class,
|
slouken@10445
|
213 |
const char* dev_path)
|
gabomdq@7753
|
214 |
{
|
slouken@10445
|
215 |
if (dev_path == NULL) {
|
gabomdq@7753
|
216 |
return;
|
gabomdq@7753
|
217 |
}
|
slouken@10797
|
218 |
|
slouken@10445
|
219 |
switch(udev_event) {
|
slouken@7788
|
220 |
case SDL_UDEV_DEVICEADDED:
|
slouken@10445
|
221 |
if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD |
|
slouken@10445
|
222 |
SDL_UDEV_DEVICE_TOUCHSCREEN)))
|
slouken@9779
|
223 |
return;
|
slouken@10433
|
224 |
|
slouken@10445
|
225 |
SDL_EVDEV_device_added(dev_path, udev_class);
|
slouken@10433
|
226 |
break;
|
slouken@10433
|
227 |
case SDL_UDEV_DEVICEREMOVED:
|
slouken@10445
|
228 |
SDL_EVDEV_device_removed(dev_path);
|
slouken@7788
|
229 |
break;
|
slouken@7788
|
230 |
default:
|
slouken@7788
|
231 |
break;
|
gabomdq@7753
|
232 |
}
|
gabomdq@7753
|
233 |
}
|
slouken@10433
|
234 |
#endif /* SDL_USE_LIBUDEV */
|
gabomdq@7753
|
235 |
|
gabomdq@7753
|
236 |
void
|
gabomdq@7753
|
237 |
SDL_EVDEV_Poll(void)
|
gabomdq@7753
|
238 |
{
|
gabomdq@7753
|
239 |
struct input_event events[32];
|
slouken@10433
|
240 |
int i, j, len;
|
gabomdq@7753
|
241 |
SDL_evdevlist_item *item;
|
gabomdq@7753
|
242 |
SDL_Scancode scan_code;
|
gabomdq@7753
|
243 |
int mouse_button;
|
gabomdq@7753
|
244 |
SDL_Mouse *mouse;
|
icculus@12547
|
245 |
float norm_x, norm_y, norm_pressure;
|
gabomdq@7778
|
246 |
|
slouken@9159
|
247 |
if (!_this) {
|
slouken@9159
|
248 |
return;
|
slouken@9159
|
249 |
}
|
slouken@9159
|
250 |
|
gabomdq@7753
|
251 |
#if SDL_USE_LIBUDEV
|
gabomdq@7753
|
252 |
SDL_UDEV_Poll();
|
gabomdq@7753
|
253 |
#endif
|
gabomdq@7778
|
254 |
|
slouken@7788
|
255 |
mouse = SDL_GetMouse();
|
slouken@7788
|
256 |
|
gabomdq@7753
|
257 |
for (item = _this->first; item != NULL; item = item->next) {
|
gabomdq@7753
|
258 |
while ((len = read(item->fd, events, (sizeof events))) > 0) {
|
gabomdq@7753
|
259 |
len /= sizeof(events[0]);
|
gabomdq@7753
|
260 |
for (i = 0; i < len; ++i) {
|
slouken@10433
|
261 |
/* special handling for touchscreen, that should eventually be
|
slouken@10433
|
262 |
used for all devices */
|
slouken@10445
|
263 |
if (item->out_of_sync && item->is_touchscreen &&
|
slouken@10445
|
264 |
events[i].type == EV_SYN && events[i].code != SYN_REPORT) {
|
slouken@10433
|
265 |
break;
|
slouken@10433
|
266 |
}
|
slouken@10797
|
267 |
|
slouken@7788
|
268 |
switch (events[i].type) {
|
slouken@7788
|
269 |
case EV_KEY:
|
slouken@7788
|
270 |
if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) {
|
slouken@7788
|
271 |
mouse_button = events[i].code - BTN_MOUSE;
|
slouken@7788
|
272 |
if (events[i].value == 0) {
|
slouken@7788
|
273 |
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]);
|
slouken@7788
|
274 |
} else if (events[i].value == 1) {
|
slouken@7788
|
275 |
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]);
|
slouken@7788
|
276 |
}
|
slouken@7788
|
277 |
break;
|
slouken@7788
|
278 |
}
|
slouken@7788
|
279 |
|
icculus@12547
|
280 |
/* BTH_TOUCH event value 1 indicates there is contact with
|
icculus@12547
|
281 |
a touchscreen or trackpad (earlist finger's current
|
icculus@12547
|
282 |
position is sent in EV_ABS ABS_X/ABS_Y, switching to
|
sylvain@12687
|
283 |
next finger after earlist is released) */
|
icculus@12547
|
284 |
if (item->is_touchscreen && events[i].code == BTN_TOUCH) {
|
slouken@12845
|
285 |
if (item->touchscreen_data->max_slots == 1) {
|
slouken@12845
|
286 |
if (events[i].value)
|
slouken@12845
|
287 |
item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
|
slouken@12845
|
288 |
else
|
slouken@12845
|
289 |
item->touchscreen_data->slots[0].delta = EVDEV_TOUCH_SLOTDELTA_UP;
|
slouken@12845
|
290 |
}
|
icculus@12547
|
291 |
break;
|
icculus@12547
|
292 |
}
|
icculus@12547
|
293 |
|
slouken@7788
|
294 |
/* Probably keyboard */
|
slouken@7788
|
295 |
scan_code = SDL_EVDEV_translate_keycode(events[i].code);
|
slouken@7788
|
296 |
if (scan_code != SDL_SCANCODE_UNKNOWN) {
|
slouken@7788
|
297 |
if (events[i].value == 0) {
|
slouken@7788
|
298 |
SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
|
slouken@10445
|
299 |
} else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) {
|
slouken@7788
|
300 |
SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
|
gabomdq@7753
|
301 |
}
|
slouken@7788
|
302 |
}
|
slouken@10797
|
303 |
SDL_EVDEV_kbd_keycode(_this->kbd, events[i].code, events[i].value);
|
slouken@7788
|
304 |
break;
|
slouken@7788
|
305 |
case EV_ABS:
|
slouken@7788
|
306 |
switch(events[i].code) {
|
slouken@10433
|
307 |
case ABS_MT_SLOT:
|
slouken@10445
|
308 |
if (!item->is_touchscreen) /* FIXME: temp hack */
|
slouken@10433
|
309 |
break;
|
slouken@10433
|
310 |
item->touchscreen_data->current_slot = events[i].value;
|
slouken@10433
|
311 |
break;
|
slouken@10433
|
312 |
case ABS_MT_TRACKING_ID:
|
slouken@10445
|
313 |
if (!item->is_touchscreen) /* FIXME: temp hack */
|
slouken@10433
|
314 |
break;
|
slouken@10445
|
315 |
if (events[i].value >= 0) {
|
slouken@10433
|
316 |
item->touchscreen_data->slots[item->touchscreen_data->current_slot].tracking_id = events[i].value;
|
slouken@10433
|
317 |
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
|
slouken@10433
|
318 |
} else {
|
slouken@10433
|
319 |
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_UP;
|
slouken@10433
|
320 |
}
|
slouken@10433
|
321 |
break;
|
slouken@10433
|
322 |
case ABS_MT_POSITION_X:
|
slouken@10445
|
323 |
if (!item->is_touchscreen) /* FIXME: temp hack */
|
slouken@10433
|
324 |
break;
|
slouken@10433
|
325 |
item->touchscreen_data->slots[item->touchscreen_data->current_slot].x = events[i].value;
|
slouken@10445
|
326 |
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
|
slouken@10433
|
327 |
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
|
slouken@10433
|
328 |
}
|
slouken@10433
|
329 |
break;
|
slouken@10433
|
330 |
case ABS_MT_POSITION_Y:
|
slouken@10445
|
331 |
if (!item->is_touchscreen) /* FIXME: temp hack */
|
slouken@10433
|
332 |
break;
|
slouken@10433
|
333 |
item->touchscreen_data->slots[item->touchscreen_data->current_slot].y = events[i].value;
|
slouken@10445
|
334 |
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
|
slouken@10433
|
335 |
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
|
slouken@10433
|
336 |
}
|
slouken@10433
|
337 |
break;
|
icculus@12547
|
338 |
case ABS_MT_PRESSURE:
|
icculus@12547
|
339 |
if (!item->is_touchscreen) /* FIXME: temp hack */
|
icculus@12547
|
340 |
break;
|
icculus@12547
|
341 |
item->touchscreen_data->slots[item->touchscreen_data->current_slot].pressure = events[i].value;
|
icculus@12547
|
342 |
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
|
icculus@12547
|
343 |
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
|
icculus@12547
|
344 |
}
|
icculus@12547
|
345 |
break;
|
slouken@7788
|
346 |
case ABS_X:
|
slouken@12845
|
347 |
if (item->is_touchscreen) {
|
slouken@12845
|
348 |
if (item->touchscreen_data->max_slots != 1)
|
slouken@12845
|
349 |
break;
|
slouken@12845
|
350 |
item->touchscreen_data->slots[0].x = events[i].value;
|
slouken@12845
|
351 |
} else
|
slouken@12845
|
352 |
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
|
slouken@7788
|
353 |
break;
|
slouken@7788
|
354 |
case ABS_Y:
|
slouken@12845
|
355 |
if (item->is_touchscreen) {
|
slouken@12845
|
356 |
if (item->touchscreen_data->max_slots != 1)
|
slouken@12845
|
357 |
break;
|
slouken@12845
|
358 |
item->touchscreen_data->slots[0].y = events[i].value;
|
slouken@12845
|
359 |
} else
|
slouken@12845
|
360 |
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
|
slouken@7788
|
361 |
break;
|
gabomdq@7753
|
362 |
default:
|
gabomdq@7753
|
363 |
break;
|
slouken@7788
|
364 |
}
|
slouken@7788
|
365 |
break;
|
slouken@7788
|
366 |
case EV_REL:
|
slouken@7788
|
367 |
switch(events[i].code) {
|
slouken@7788
|
368 |
case REL_X:
|
slouken@7788
|
369 |
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, events[i].value, 0);
|
slouken@7788
|
370 |
break;
|
slouken@7788
|
371 |
case REL_Y:
|
slouken@7788
|
372 |
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value);
|
slouken@7788
|
373 |
break;
|
slouken@7788
|
374 |
case REL_WHEEL:
|
urkle@9257
|
375 |
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value, SDL_MOUSEWHEEL_NORMAL);
|
slouken@7788
|
376 |
break;
|
slouken@7788
|
377 |
case REL_HWHEEL:
|
urkle@9257
|
378 |
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
|
slouken@7788
|
379 |
break;
|
slouken@7788
|
380 |
default:
|
slouken@7788
|
381 |
break;
|
slouken@7788
|
382 |
}
|
slouken@7788
|
383 |
break;
|
slouken@7788
|
384 |
case EV_SYN:
|
slouken@7788
|
385 |
switch (events[i].code) {
|
slouken@10433
|
386 |
case SYN_REPORT:
|
slouken@10445
|
387 |
if (!item->is_touchscreen) /* FIXME: temp hack */
|
slouken@10433
|
388 |
break;
|
slouken@10797
|
389 |
|
slouken@10445
|
390 |
for(j = 0; j < item->touchscreen_data->max_slots; j++) {
|
slouken@10433
|
391 |
norm_x = (float)(item->touchscreen_data->slots[j].x - item->touchscreen_data->min_x) /
|
slouken@10433
|
392 |
(float)item->touchscreen_data->range_x;
|
slouken@10433
|
393 |
norm_y = (float)(item->touchscreen_data->slots[j].y - item->touchscreen_data->min_y) /
|
slouken@10433
|
394 |
(float)item->touchscreen_data->range_y;
|
slouken@10797
|
395 |
|
icculus@12547
|
396 |
if (item->touchscreen_data->range_pressure > 0) {
|
icculus@12547
|
397 |
norm_pressure = (float)(item->touchscreen_data->slots[j].pressure - item->touchscreen_data->min_pressure) /
|
icculus@12547
|
398 |
(float)item->touchscreen_data->range_pressure;
|
icculus@12547
|
399 |
} else {
|
icculus@12547
|
400 |
/* This touchscreen does not support pressure */
|
icculus@12547
|
401 |
norm_pressure = 1.0f;
|
icculus@12547
|
402 |
}
|
icculus@12547
|
403 |
|
slime73@12996
|
404 |
/* FIXME: the touch's window shouldn't be null, but
|
slime73@12996
|
405 |
* the coordinate space of touch positions needs to
|
slime73@12996
|
406 |
* be window-relative in that case. */
|
slouken@10445
|
407 |
switch(item->touchscreen_data->slots[j].delta) {
|
slouken@10433
|
408 |
case EVDEV_TOUCH_SLOTDELTA_DOWN:
|
slime73@12996
|
409 |
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_TRUE, norm_x, norm_y, norm_pressure);
|
slouken@10433
|
410 |
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
|
slouken@10433
|
411 |
break;
|
slouken@10433
|
412 |
case EVDEV_TOUCH_SLOTDELTA_UP:
|
slime73@12996
|
413 |
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_FALSE, norm_x, norm_y, norm_pressure);
|
slouken@10433
|
414 |
item->touchscreen_data->slots[j].tracking_id = -1;
|
slouken@10433
|
415 |
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
|
slouken@10433
|
416 |
break;
|
slouken@10433
|
417 |
case EVDEV_TOUCH_SLOTDELTA_MOVE:
|
slime73@12996
|
418 |
SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, norm_x, norm_y, norm_pressure);
|
slouken@10433
|
419 |
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
|
slouken@10433
|
420 |
break;
|
slouken@10433
|
421 |
default:
|
slouken@10433
|
422 |
break;
|
slouken@10433
|
423 |
}
|
slouken@10433
|
424 |
}
|
slouken@10797
|
425 |
|
slouken@10445
|
426 |
if (item->out_of_sync)
|
slouken@10433
|
427 |
item->out_of_sync = 0;
|
slouken@10433
|
428 |
break;
|
slouken@7788
|
429 |
case SYN_DROPPED:
|
slouken@10445
|
430 |
if (item->is_touchscreen)
|
slouken@10433
|
431 |
item->out_of_sync = 1;
|
slouken@7788
|
432 |
SDL_EVDEV_sync_device(item);
|
slouken@7788
|
433 |
break;
|
slouken@7788
|
434 |
default:
|
slouken@7788
|
435 |
break;
|
slouken@7788
|
436 |
}
|
slouken@7788
|
437 |
break;
|
gabomdq@7753
|
438 |
}
|
gabomdq@7753
|
439 |
}
|
gabomdq@7753
|
440 |
}
|
gabomdq@7753
|
441 |
}
|
gabomdq@7753
|
442 |
}
|
gabomdq@7753
|
443 |
|
gabomdq@7753
|
444 |
static SDL_Scancode
|
slouken@10445
|
445 |
SDL_EVDEV_translate_keycode(int keycode)
|
gabomdq@7753
|
446 |
{
|
gabomdq@7753
|
447 |
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
|
gabomdq@7753
|
448 |
|
slouken@10445
|
449 |
if (keycode < SDL_arraysize(linux_scancode_table))
|
slouken@10433
|
450 |
scancode = linux_scancode_table[keycode];
|
slouken@10433
|
451 |
|
slouken@10445
|
452 |
if (scancode == SDL_SCANCODE_UNKNOWN) {
|
icculus@12548
|
453 |
/* BTN_TOUCH is handled elsewhere, but we might still end up here if
|
icculus@12548
|
454 |
you get an unexpected BTN_TOUCH from something SDL believes is not
|
icculus@12548
|
455 |
a touch device. In this case, we'd rather not get a misleading
|
icculus@12548
|
456 |
SDL_Log message about an unknown key. */
|
icculus@12548
|
457 |
if (keycode != BTN_TOUCH) {
|
icculus@12548
|
458 |
SDL_Log("The key you just pressed is not recognized by SDL. To help "
|
icculus@12548
|
459 |
"get this fixed, please report this to the SDL forums/mailing list "
|
icculus@12548
|
460 |
"<https://discourse.libsdl.org/> EVDEV KeyCode %d", keycode);
|
icculus@12548
|
461 |
}
|
slouken@10433
|
462 |
}
|
slouken@10433
|
463 |
|
slouken@10433
|
464 |
return scancode;
|
slouken@10433
|
465 |
}
|
slouken@10433
|
466 |
|
slouken@10445
|
467 |
#ifdef SDL_USE_LIBUDEV
|
slouken@10433
|
468 |
static int
|
slouken@10445
|
469 |
SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
|
slouken@10445
|
470 |
{
|
slouken@10433
|
471 |
int ret, i;
|
slouken@12845
|
472 |
unsigned long xreq, yreq;
|
slouken@10433
|
473 |
char name[64];
|
slouken@10433
|
474 |
struct input_absinfo abs_info;
|
slouken@10797
|
475 |
|
slouken@10445
|
476 |
if (!item->is_touchscreen)
|
slouken@10433
|
477 |
return 0;
|
slouken@10797
|
478 |
|
slouken@10445
|
479 |
item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data));
|
slouken@10445
|
480 |
if (item->touchscreen_data == NULL)
|
slouken@10433
|
481 |
return SDL_OutOfMemory();
|
slouken@10797
|
482 |
|
slouken@10445
|
483 |
ret = ioctl(item->fd, EVIOCGNAME(sizeof(name)), name);
|
slouken@10445
|
484 |
if (ret < 0) {
|
slouken@10445
|
485 |
SDL_free(item->touchscreen_data);
|
slouken@10445
|
486 |
return SDL_SetError("Failed to get evdev touchscreen name");
|
slouken@10433
|
487 |
}
|
slouken@10797
|
488 |
|
slouken@10445
|
489 |
item->touchscreen_data->name = SDL_strdup(name);
|
slouken@10445
|
490 |
if (item->touchscreen_data->name == NULL) {
|
slouken@10445
|
491 |
SDL_free(item->touchscreen_data);
|
slouken@10433
|
492 |
return SDL_OutOfMemory();
|
slouken@10433
|
493 |
}
|
slouken@10797
|
494 |
|
slouken@12845
|
495 |
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
|
slouken@12845
|
496 |
if (ret < 0) {
|
slouken@12845
|
497 |
SDL_free(item->touchscreen_data->name);
|
slouken@12845
|
498 |
SDL_free(item->touchscreen_data);
|
slouken@12845
|
499 |
return SDL_SetError("Failed to get evdev touchscreen limits");
|
slouken@12845
|
500 |
}
|
slouken@12845
|
501 |
|
slouken@12845
|
502 |
if (abs_info.maximum == 0) {
|
slouken@12845
|
503 |
item->touchscreen_data->max_slots = 1;
|
slouken@12845
|
504 |
xreq = EVIOCGABS(ABS_X);
|
slouken@12845
|
505 |
yreq = EVIOCGABS(ABS_Y);
|
slouken@12845
|
506 |
} else {
|
slouken@12845
|
507 |
item->touchscreen_data->max_slots = abs_info.maximum + 1;
|
slouken@12845
|
508 |
xreq = EVIOCGABS(ABS_MT_POSITION_X);
|
slouken@12845
|
509 |
yreq = EVIOCGABS(ABS_MT_POSITION_Y);
|
slouken@12845
|
510 |
}
|
slouken@12845
|
511 |
|
slouken@12845
|
512 |
ret = ioctl(item->fd, xreq, &abs_info);
|
slouken@10445
|
513 |
if (ret < 0) {
|
slouken@10445
|
514 |
SDL_free(item->touchscreen_data->name);
|
slouken@10445
|
515 |
SDL_free(item->touchscreen_data);
|
slouken@10445
|
516 |
return SDL_SetError("Failed to get evdev touchscreen limits");
|
gabomdq@7753
|
517 |
}
|
slouken@10433
|
518 |
item->touchscreen_data->min_x = abs_info.minimum;
|
slouken@10433
|
519 |
item->touchscreen_data->max_x = abs_info.maximum;
|
slouken@10433
|
520 |
item->touchscreen_data->range_x = abs_info.maximum - abs_info.minimum;
|
slouken@10797
|
521 |
|
slouken@12845
|
522 |
ret = ioctl(item->fd, yreq, &abs_info);
|
slouken@10445
|
523 |
if (ret < 0) {
|
slouken@10445
|
524 |
SDL_free(item->touchscreen_data->name);
|
slouken@10445
|
525 |
SDL_free(item->touchscreen_data);
|
slouken@10445
|
526 |
return SDL_SetError("Failed to get evdev touchscreen limits");
|
slouken@10433
|
527 |
}
|
slouken@10433
|
528 |
item->touchscreen_data->min_y = abs_info.minimum;
|
slouken@10433
|
529 |
item->touchscreen_data->max_y = abs_info.maximum;
|
slouken@10433
|
530 |
item->touchscreen_data->range_y = abs_info.maximum - abs_info.minimum;
|
slouken@10797
|
531 |
|
icculus@12547
|
532 |
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_PRESSURE), &abs_info);
|
icculus@12547
|
533 |
if (ret < 0) {
|
icculus@12547
|
534 |
SDL_free(item->touchscreen_data->name);
|
icculus@12547
|
535 |
SDL_free(item->touchscreen_data);
|
icculus@12547
|
536 |
return SDL_SetError("Failed to get evdev touchscreen limits");
|
icculus@12547
|
537 |
}
|
icculus@12547
|
538 |
item->touchscreen_data->min_pressure = abs_info.minimum;
|
icculus@12547
|
539 |
item->touchscreen_data->max_pressure = abs_info.maximum;
|
icculus@12547
|
540 |
item->touchscreen_data->range_pressure = abs_info.maximum - abs_info.minimum;
|
icculus@12547
|
541 |
|
slouken@10433
|
542 |
item->touchscreen_data->slots = SDL_calloc(
|
slouken@10433
|
543 |
item->touchscreen_data->max_slots,
|
slouken@10445
|
544 |
sizeof(*item->touchscreen_data->slots));
|
slouken@10445
|
545 |
if (item->touchscreen_data->slots == NULL) {
|
slouken@10445
|
546 |
SDL_free(item->touchscreen_data->name);
|
slouken@10445
|
547 |
SDL_free(item->touchscreen_data);
|
slouken@10433
|
548 |
return SDL_OutOfMemory();
|
slouken@10433
|
549 |
}
|
slouken@10797
|
550 |
|
slouken@10445
|
551 |
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
|
slouken@10433
|
552 |
item->touchscreen_data->slots[i].tracking_id = -1;
|
slouken@10433
|
553 |
}
|
slouken@10797
|
554 |
|
slouken@10445
|
555 |
ret = SDL_AddTouch(item->fd, /* I guess our fd is unique enough */
|
slime73@12404
|
556 |
SDL_TOUCH_DEVICE_DIRECT,
|
slouken@10445
|
557 |
item->touchscreen_data->name);
|
slouken@10445
|
558 |
if (ret < 0) {
|
slouken@10445
|
559 |
SDL_free(item->touchscreen_data->slots);
|
slouken@10445
|
560 |
SDL_free(item->touchscreen_data->name);
|
slouken@10445
|
561 |
SDL_free(item->touchscreen_data);
|
slouken@10433
|
562 |
return ret;
|
slouken@10433
|
563 |
}
|
slouken@10797
|
564 |
|
slouken@10433
|
565 |
return 0;
|
slouken@10433
|
566 |
}
|
slouken@10445
|
567 |
#endif /* SDL_USE_LIBUDEV */
|
slouken@10433
|
568 |
|
slouken@10433
|
569 |
static void
|
slouken@10445
|
570 |
SDL_EVDEV_destroy_touchscreen(SDL_evdevlist_item* item) {
|
slouken@10445
|
571 |
if (!item->is_touchscreen)
|
slouken@10433
|
572 |
return;
|
slouken@10797
|
573 |
|
slouken@10445
|
574 |
SDL_DelTouch(item->fd);
|
slouken@10445
|
575 |
SDL_free(item->touchscreen_data->slots);
|
slouken@10445
|
576 |
SDL_free(item->touchscreen_data->name);
|
slouken@10445
|
577 |
SDL_free(item->touchscreen_data);
|
gabomdq@7753
|
578 |
}
|
gabomdq@7753
|
579 |
|
gabomdq@7753
|
580 |
static void
|
gabomdq@7753
|
581 |
SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
|
gabomdq@7753
|
582 |
{
|
slouken@10446
|
583 |
#ifdef EVIOCGMTSLOTS
|
slouken@10433
|
584 |
int i, ret;
|
slouken@10433
|
585 |
struct input_absinfo abs_info;
|
slouken@10433
|
586 |
/*
|
slouken@10433
|
587 |
* struct input_mt_request_layout {
|
slouken@10433
|
588 |
* __u32 code;
|
slouken@10433
|
589 |
* __s32 values[num_slots];
|
slouken@10433
|
590 |
* };
|
slouken@10433
|
591 |
*
|
slouken@10433
|
592 |
* this is the structure we're trying to emulate
|
slouken@10433
|
593 |
*/
|
slouken@12761
|
594 |
Uint32* mt_req_code;
|
slouken@12761
|
595 |
Sint32* mt_req_values;
|
slouken@10433
|
596 |
size_t mt_req_size;
|
slouken@10797
|
597 |
|
slouken@10433
|
598 |
/* TODO: sync devices other than touchscreen */
|
slouken@10445
|
599 |
if (!item->is_touchscreen)
|
slouken@10433
|
600 |
return;
|
slouken@10797
|
601 |
|
slouken@10445
|
602 |
mt_req_size = sizeof(*mt_req_code) +
|
slouken@10445
|
603 |
sizeof(*mt_req_values) * item->touchscreen_data->max_slots;
|
slouken@10797
|
604 |
|
slouken@10445
|
605 |
mt_req_code = SDL_calloc(1, mt_req_size);
|
slouken@10445
|
606 |
if (mt_req_code == NULL) {
|
slouken@10433
|
607 |
return;
|
slouken@10433
|
608 |
}
|
slouken@10797
|
609 |
|
slouken@12761
|
610 |
mt_req_values = (Sint32*)mt_req_code + 1;
|
slouken@10797
|
611 |
|
slouken@10433
|
612 |
*mt_req_code = ABS_MT_TRACKING_ID;
|
slouken@10445
|
613 |
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
|
slouken@10445
|
614 |
if (ret < 0) {
|
slouken@10445
|
615 |
SDL_free(mt_req_code);
|
slouken@10433
|
616 |
return;
|
slouken@10433
|
617 |
}
|
slouken@10445
|
618 |
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
|
slouken@10433
|
619 |
/*
|
slouken@10433
|
620 |
* This doesn't account for the very edge case of the user removing their
|
slouken@10433
|
621 |
* finger and replacing it on the screen during the time we're out of sync,
|
slouken@10433
|
622 |
* which'll mean that we're not going from down -> up or up -> down, we're
|
slouken@10433
|
623 |
* going from down -> down but with a different tracking id, meaning we'd
|
slouken@10433
|
624 |
* have to tell SDL of the two events, but since we wait till SYN_REPORT in
|
slouken@10433
|
625 |
* SDL_EVDEV_Poll to tell SDL, the current structure of this code doesn't
|
slouken@10433
|
626 |
* allow it. Lets just pray to God it doesn't happen.
|
slouken@10433
|
627 |
*/
|
slouken@10445
|
628 |
if (item->touchscreen_data->slots[i].tracking_id < 0 &&
|
slouken@10445
|
629 |
mt_req_values[i] >= 0) {
|
slouken@10433
|
630 |
item->touchscreen_data->slots[i].tracking_id = mt_req_values[i];
|
slouken@10433
|
631 |
item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
|
slouken@10445
|
632 |
} else if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
|
slouken@10445
|
633 |
mt_req_values[i] < 0) {
|
slouken@10433
|
634 |
item->touchscreen_data->slots[i].tracking_id = -1;
|
slouken@10433
|
635 |
item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_UP;
|
slouken@10433
|
636 |
}
|
slouken@10433
|
637 |
}
|
slouken@10797
|
638 |
|
slouken@10433
|
639 |
*mt_req_code = ABS_MT_POSITION_X;
|
slouken@10445
|
640 |
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
|
slouken@10445
|
641 |
if (ret < 0) {
|
slouken@10445
|
642 |
SDL_free(mt_req_code);
|
slouken@10433
|
643 |
return;
|
slouken@10433
|
644 |
}
|
slouken@10445
|
645 |
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
|
slouken@10445
|
646 |
if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
|
slouken@10445
|
647 |
item->touchscreen_data->slots[i].x != mt_req_values[i]) {
|
slouken@10433
|
648 |
item->touchscreen_data->slots[i].x = mt_req_values[i];
|
slouken@10445
|
649 |
if (item->touchscreen_data->slots[i].delta ==
|
slouken@10445
|
650 |
EVDEV_TOUCH_SLOTDELTA_NONE) {
|
slouken@10433
|
651 |
item->touchscreen_data->slots[i].delta =
|
slouken@10433
|
652 |
EVDEV_TOUCH_SLOTDELTA_MOVE;
|
slouken@10433
|
653 |
}
|
slouken@10433
|
654 |
}
|
slouken@10433
|
655 |
}
|
slouken@10797
|
656 |
|
slouken@10433
|
657 |
*mt_req_code = ABS_MT_POSITION_Y;
|
slouken@10445
|
658 |
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
|
slouken@10445
|
659 |
if (ret < 0) {
|
slouken@10445
|
660 |
SDL_free(mt_req_code);
|
slouken@10433
|
661 |
return;
|
slouken@10433
|
662 |
}
|
slouken@10445
|
663 |
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
|
slouken@10445
|
664 |
if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
|
slouken@10445
|
665 |
item->touchscreen_data->slots[i].y != mt_req_values[i]) {
|
slouken@10433
|
666 |
item->touchscreen_data->slots[i].y = mt_req_values[i];
|
slouken@10445
|
667 |
if (item->touchscreen_data->slots[i].delta ==
|
slouken@10445
|
668 |
EVDEV_TOUCH_SLOTDELTA_NONE) {
|
slouken@10433
|
669 |
item->touchscreen_data->slots[i].delta =
|
slouken@10433
|
670 |
EVDEV_TOUCH_SLOTDELTA_MOVE;
|
slouken@10433
|
671 |
}
|
slouken@10433
|
672 |
}
|
slouken@10433
|
673 |
}
|
slouken@10797
|
674 |
|
icculus@12547
|
675 |
*mt_req_code = ABS_MT_PRESSURE;
|
icculus@12547
|
676 |
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
|
icculus@12547
|
677 |
if (ret < 0) {
|
icculus@12547
|
678 |
SDL_free(mt_req_code);
|
icculus@12547
|
679 |
return;
|
icculus@12547
|
680 |
}
|
icculus@12547
|
681 |
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
|
icculus@12547
|
682 |
if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
|
icculus@12547
|
683 |
item->touchscreen_data->slots[i].pressure != mt_req_values[i]) {
|
icculus@12547
|
684 |
item->touchscreen_data->slots[i].pressure = mt_req_values[i];
|
icculus@12547
|
685 |
if (item->touchscreen_data->slots[i].delta ==
|
icculus@12547
|
686 |
EVDEV_TOUCH_SLOTDELTA_NONE) {
|
icculus@12547
|
687 |
item->touchscreen_data->slots[i].delta =
|
icculus@12547
|
688 |
EVDEV_TOUCH_SLOTDELTA_MOVE;
|
icculus@12547
|
689 |
}
|
icculus@12547
|
690 |
}
|
icculus@12547
|
691 |
}
|
icculus@12547
|
692 |
|
slouken@10445
|
693 |
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
|
slouken@10445
|
694 |
if (ret < 0) {
|
slouken@10445
|
695 |
SDL_free(mt_req_code);
|
slouken@10433
|
696 |
return;
|
slouken@10433
|
697 |
}
|
slouken@10433
|
698 |
item->touchscreen_data->current_slot = abs_info.value;
|
slouken@10797
|
699 |
|
slouken@10445
|
700 |
SDL_free(mt_req_code);
|
slouken@10446
|
701 |
|
slouken@10446
|
702 |
#endif /* EVIOCGMTSLOTS */
|
gabomdq@7753
|
703 |
}
|
gabomdq@7753
|
704 |
|
gabomdq@7755
|
705 |
#if SDL_USE_LIBUDEV
|
gabomdq@7753
|
706 |
static int
|
slouken@10433
|
707 |
SDL_EVDEV_device_added(const char *dev_path, int udev_class)
|
gabomdq@7753
|
708 |
{
|
slouken@10433
|
709 |
int ret;
|
gabomdq@7753
|
710 |
SDL_evdevlist_item *item;
|
gabomdq@7753
|
711 |
|
gabomdq@7753
|
712 |
/* Check to make sure it's not already in list. */
|
gabomdq@7753
|
713 |
for (item = _this->first; item != NULL; item = item->next) {
|
slouken@10433
|
714 |
if (SDL_strcmp(dev_path, item->path) == 0) {
|
gabomdq@7753
|
715 |
return -1; /* already have this one */
|
gabomdq@7753
|
716 |
}
|
gabomdq@7753
|
717 |
}
|
slouken@10797
|
718 |
|
gabomdq@7753
|
719 |
item = (SDL_evdevlist_item *) SDL_calloc(1, sizeof (SDL_evdevlist_item));
|
gabomdq@7753
|
720 |
if (item == NULL) {
|
gabomdq@7753
|
721 |
return SDL_OutOfMemory();
|
gabomdq@7753
|
722 |
}
|
gabomdq@7753
|
723 |
|
slouken@10445
|
724 |
item->fd = open(dev_path, O_RDONLY | O_NONBLOCK);
|
gabomdq@7753
|
725 |
if (item->fd < 0) {
|
gabomdq@7753
|
726 |
SDL_free(item);
|
slouken@10433
|
727 |
return SDL_SetError("Unable to open %s", dev_path);
|
gabomdq@7753
|
728 |
}
|
slouken@10797
|
729 |
|
slouken@10433
|
730 |
item->path = SDL_strdup(dev_path);
|
gabomdq@7753
|
731 |
if (item->path == NULL) {
|
gabomdq@7753
|
732 |
close(item->fd);
|
gabomdq@7753
|
733 |
SDL_free(item);
|
gabomdq@7753
|
734 |
return SDL_OutOfMemory();
|
gabomdq@7753
|
735 |
}
|
slouken@10797
|
736 |
|
slouken@10445
|
737 |
if (udev_class & SDL_UDEV_DEVICE_TOUCHSCREEN) {
|
slouken@10433
|
738 |
item->is_touchscreen = 1;
|
slouken@10797
|
739 |
|
slouken@10445
|
740 |
if ((ret = SDL_EVDEV_init_touchscreen(item)) < 0) {
|
slouken@10433
|
741 |
close(item->fd);
|
slouken@10433
|
742 |
SDL_free(item);
|
slouken@10433
|
743 |
return ret;
|
slouken@10433
|
744 |
}
|
slouken@10433
|
745 |
}
|
slouken@10797
|
746 |
|
gabomdq@7753
|
747 |
if (_this->last == NULL) {
|
gabomdq@7753
|
748 |
_this->first = _this->last = item;
|
gabomdq@7753
|
749 |
} else {
|
gabomdq@7753
|
750 |
_this->last->next = item;
|
gabomdq@7753
|
751 |
_this->last = item;
|
gabomdq@7753
|
752 |
}
|
slouken@10797
|
753 |
|
gabomdq@7753
|
754 |
SDL_EVDEV_sync_device(item);
|
slouken@10797
|
755 |
|
slouken@10433
|
756 |
return _this->num_devices++;
|
gabomdq@7753
|
757 |
}
|
gabomdq@7767
|
758 |
#endif /* SDL_USE_LIBUDEV */
|
gabomdq@7753
|
759 |
|
gabomdq@7753
|
760 |
static int
|
slouken@10433
|
761 |
SDL_EVDEV_device_removed(const char *dev_path)
|
gabomdq@7753
|
762 |
{
|
gabomdq@7753
|
763 |
SDL_evdevlist_item *item;
|
gabomdq@7753
|
764 |
SDL_evdevlist_item *prev = NULL;
|
gabomdq@7753
|
765 |
|
gabomdq@7753
|
766 |
for (item = _this->first; item != NULL; item = item->next) {
|
gabomdq@7753
|
767 |
/* found it, remove it. */
|
slouken@10433
|
768 |
if (SDL_strcmp(dev_path, item->path) == 0) {
|
gabomdq@7753
|
769 |
if (prev != NULL) {
|
gabomdq@7753
|
770 |
prev->next = item->next;
|
gabomdq@7753
|
771 |
} else {
|
gabomdq@7753
|
772 |
SDL_assert(_this->first == item);
|
gabomdq@7753
|
773 |
_this->first = item->next;
|
gabomdq@7753
|
774 |
}
|
gabomdq@7753
|
775 |
if (item == _this->last) {
|
gabomdq@7753
|
776 |
_this->last = prev;
|
gabomdq@7753
|
777 |
}
|
slouken@10445
|
778 |
if (item->is_touchscreen) {
|
slouken@10445
|
779 |
SDL_EVDEV_destroy_touchscreen(item);
|
slouken@10433
|
780 |
}
|
gabomdq@7753
|
781 |
close(item->fd);
|
gabomdq@7753
|
782 |
SDL_free(item->path);
|
gabomdq@7753
|
783 |
SDL_free(item);
|
slouken@10433
|
784 |
_this->num_devices--;
|
gabomdq@7753
|
785 |
return 0;
|
gabomdq@7753
|
786 |
}
|
gabomdq@7753
|
787 |
prev = item;
|
gabomdq@7753
|
788 |
}
|
gabomdq@7753
|
789 |
|
gabomdq@7753
|
790 |
return -1;
|
gabomdq@7753
|
791 |
}
|
gabomdq@7767
|
792 |
|
gabomdq@7753
|
793 |
|
gabomdq@7753
|
794 |
#endif /* SDL_INPUT_LINUXEV */
|
gabomdq@7753
|
795 |
|
gabomdq@7753
|
796 |
/* vi: set ts=4 sw=4 expandtab: */
|