1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <SDL2/SDL.h>
6
7 #include <Eina.h>
8 #include <Ecore.h>
9 #include <ecore_private.h>
10 #include <Ecore_Input.h>
11 #include "Ecore_Sdl.h"
12 #include "Ecore_Sdl_Keys.h"
13 #include "ecore_sdl_private.h"
14
15 int _ecore_sdl_log_dom = -1;
16
17 typedef struct _Ecore_SDL_Pressed Ecore_SDL_Pressed;
18 struct _Ecore_SDL_Pressed
19 {
20 EINA_RBTREE;
21
22 SDL_Keycode key;
23 };
24
25 EAPI int ECORE_SDL_EVENT_GOT_FOCUS = 0;
26 EAPI int ECORE_SDL_EVENT_LOST_FOCUS = 0;
27 EAPI int ECORE_SDL_EVENT_RESIZE = 0;
28 EAPI int ECORE_SDL_EVENT_EXPOSE = 0;
29
30 static int _ecore_sdl_init_count = 0;
31 static Eina_Rbtree *repeat = NULL;
32
33 static Eina_Rbtree_Direction
_ecore_sdl_pressed_key(const Ecore_SDL_Pressed * left,const Ecore_SDL_Pressed * right,EINA_UNUSED void * data)34 _ecore_sdl_pressed_key(const Ecore_SDL_Pressed *left,
35 const Ecore_SDL_Pressed *right,
36 EINA_UNUSED void *data)
37 {
38 return left->key < right->key ? EINA_RBTREE_LEFT : EINA_RBTREE_RIGHT;
39 }
40
41 static int
_ecore_sdl_pressed_node(const Ecore_SDL_Pressed * node,const SDL_Keycode * key,EINA_UNUSED int length,EINA_UNUSED void * data)42 _ecore_sdl_pressed_node(const Ecore_SDL_Pressed *node,
43 const SDL_Keycode *key,
44 EINA_UNUSED int length,
45 EINA_UNUSED void *data)
46 {
47 return node->key - *key;
48 }
49
50 /**
51 * @defgroup Ecore_Sdl_Library_Group SDL Library Functions
52 * @ingroup Ecore
53 *
54 * Functions used to set up and shut down the Ecore_Sdl functions.
55 */
56
57 /**
58 * Sets up the Ecore_Sdl library.
59 * @param name device target name
60 * @return @c 0 on failure. Otherwise, the number of times the library has
61 * been initialised without being shut down.
62 * @ingroup Ecore_SDL_Library_Group
63 */
64 EAPI int
ecore_sdl_init(const char * name EINA_UNUSED)65 ecore_sdl_init(const char *name EINA_UNUSED)
66 {
67 if(++_ecore_sdl_init_count != 1)
68 return _ecore_sdl_init_count;
69 _ecore_sdl_log_dom = eina_log_domain_register
70 ("ecore_sdl", ECORE_SDL_DEFAULT_LOG_COLOR);
71 if(_ecore_sdl_log_dom < 0)
72 {
73 EINA_LOG_ERR("Impossible to create a log domain for the Ecore SDL module.");
74 return --_ecore_sdl_init_count;
75 }
76 if (!ecore_event_init())
77 return --_ecore_sdl_init_count;
78
79 SDL_Init(SDL_INIT_EVENTS);
80
81 ECORE_SDL_EVENT_GOT_FOCUS = ecore_event_type_new();
82 ECORE_SDL_EVENT_LOST_FOCUS = ecore_event_type_new();
83 ECORE_SDL_EVENT_RESIZE = ecore_event_type_new();
84 ECORE_SDL_EVENT_EXPOSE = ecore_event_type_new();
85
86 return _ecore_sdl_init_count;
87 }
88
89 /**
90 * Shuts down the Ecore_Sdl library.
91 * @return @c The number of times the system has been initialised without
92 * being shut down.
93 * @ingroup Ecore_SDL_Library_Group
94 */
95 EAPI int
ecore_sdl_shutdown(void)96 ecore_sdl_shutdown(void)
97 {
98 if (--_ecore_sdl_init_count != 0)
99 return _ecore_sdl_init_count;
100
101 SDL_Quit();
102
103 ecore_event_type_flush(ECORE_SDL_EVENT_GOT_FOCUS,
104 ECORE_SDL_EVENT_LOST_FOCUS,
105 ECORE_SDL_EVENT_RESIZE,
106 ECORE_SDL_EVENT_EXPOSE);
107
108 ecore_event_shutdown();
109 eina_log_domain_unregister(_ecore_sdl_log_dom);
110 _ecore_sdl_log_dom = -1;
111 return _ecore_sdl_init_count;
112 }
113
114 static unsigned int
_ecore_sdl_event_modifiers(int mod)115 _ecore_sdl_event_modifiers(int mod)
116 {
117 unsigned int modifiers = 0;
118
119 if(mod & KMOD_LSHIFT) modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
120 if(mod & KMOD_RSHIFT) modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
121 if(mod & KMOD_LCTRL) modifiers |= ECORE_EVENT_MODIFIER_CTRL;
122 if(mod & KMOD_RCTRL) modifiers |= ECORE_EVENT_MODIFIER_CTRL;
123 if(mod & KMOD_LALT) modifiers |= ECORE_EVENT_MODIFIER_ALT;
124 if(mod & KMOD_RALT) modifiers |= ECORE_EVENT_MODIFIER_ALT;
125 if(mod & KMOD_NUM) modifiers |= ECORE_EVENT_LOCK_NUM;
126 if(mod & KMOD_CAPS) modifiers |= ECORE_EVENT_LOCK_CAPS;
127
128 return modifiers;
129 }
130
131 static Ecore_Event_Key*
_ecore_sdl_event_key(SDL_Event * event,double timestamp)132 _ecore_sdl_event_key(SDL_Event *event, double timestamp)
133 {
134 Ecore_Event_Key *ev;
135 unsigned int i;
136
137 ev = calloc(1, sizeof(Ecore_Event_Key));
138 if (!ev) return NULL;
139
140 ev->timestamp = timestamp;
141 ev->window = event->key.windowID;
142 ev->event_window = 0;
143 ev->modifiers = _ecore_sdl_event_modifiers(SDL_GetModState());
144 ev->key = NULL;
145 ev->compose = NULL;
146
147 for (i = 0; i < EINA_C_ARRAY_LENGTH(keystable); ++i)
148 if (keystable[i].code == event->key.keysym.sym)
149 {
150 ev->keyname = keystable[i].name;
151 ev->string = keystable[i].compose;
152
153 return ev;
154 }
155
156 free(ev);
157 return NULL;
158 }
159
160 /**
161 * Poll SDL for mouse, keyboard, and window events, and add corresponding events to ecore.
162 * @ingroup Ecore_SDL_Library_Group
163 */
164 EAPI void
ecore_sdl_feed_events(void)165 ecore_sdl_feed_events(void)
166 {
167 SDL_Event event;
168 unsigned int timestamp;
169
170 while(SDL_PollEvent(&event))
171 {
172 timestamp = (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff);
173 switch(event.type)
174 {
175 case SDL_MOUSEMOTION:
176 {
177 Ecore_Event_Mouse_Move *ev;
178
179 ev = calloc(1, sizeof(Ecore_Event_Mouse_Move));
180 if (!ev) return;
181
182 ev->timestamp = timestamp;
183 ev->window = event.motion.windowID;
184 ev->event_window = event.motion.windowID;
185 ev->modifiers = 0; /* FIXME: keep modifier around. */
186 ev->x = event.motion.x;
187 ev->y = event.motion.y;
188 ev->root.x = ev->x;
189 ev->root.y = ev->y;
190
191 /* Must set multi touch device to 0 or it will get ignored */
192 ev->multi.device = 0;
193 ev->multi.radius = ev->multi.radius_x = ev->multi.radius_y = 0;
194 ev->multi.pressure = ev->multi.angle = 0;
195 ev->multi.x = ev->multi.y = ev->multi.root.x = ev->multi.root.y = 0;
196
197 ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
198 break;
199 }
200 case SDL_MOUSEBUTTONDOWN:
201 {
202 Ecore_Event_Mouse_Button *ev;
203
204 ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
205 if (!ev) return;
206
207 ev->timestamp = timestamp;
208 ev->window = event.button.windowID;
209 ev->event_window = event.button.windowID;
210 ev->modifiers = 0; /* FIXME: keep modifier around. */
211 ev->buttons = event.button.button;
212 ev->double_click = 0;
213 ev->triple_click = 0;
214
215 /* Must set multi touch device to 0 or it will get ignored */
216 ev->multi.device = 0;
217 ev->multi.radius = ev->multi.radius_x = ev->multi.radius_y = 0;
218 ev->multi.pressure = ev->multi.angle = 0;
219 ev->multi.x = ev->multi.y = ev->multi.root.x = ev->multi.root.y = 0;
220
221 ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
222 break;
223 }
224 case SDL_MOUSEWHEEL:
225 {
226 Ecore_Event_Mouse_Wheel *ev;
227
228 ev = calloc(1, sizeof(Ecore_Event_Mouse_Wheel));
229 if (!ev) return;
230
231 ev->timestamp = timestamp;
232 ev->window = event.wheel.windowID;
233 ev->event_window = event.wheel.windowID;
234 ev->modifiers = 0; /* FIXME: keep modifier around. */
235 ev->direction = 0;
236 ev->z = event.wheel.x != 0 ? event.wheel.x : event.wheel.y;
237 ev->direction = event.wheel.x != 0 ? 0 : 1;
238
239 ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
240 break;
241 }
242 case SDL_MOUSEBUTTONUP:
243 {
244 Ecore_Event_Mouse_Button *ev;
245
246 ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
247 if (!ev) return;
248 ev->timestamp = timestamp;
249 ev->window = event.button.windowID;
250 ev->event_window = event.button.windowID;
251 ev->modifiers = 0; /* FIXME: keep modifier around. */
252 ev->buttons = event.button.button;
253 ev->double_click = 0;
254 ev->triple_click = 0;
255
256 /* Must set multi touch device to 0 or it will get ignored */
257 ev->multi.device = 0;
258 ev->multi.radius = ev->multi.radius_x = ev->multi.radius_y = 0;
259 ev->multi.pressure = ev->multi.angle = 0;
260 ev->multi.x = ev->multi.y = ev->multi.root.x = ev->multi.root.y = 0;
261
262 ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
263 break;
264 }
265 case SDL_QUIT:
266 ecore_main_loop_quit();
267 break;
268
269 case SDL_KEYDOWN:
270 {
271 Ecore_SDL_Pressed *entry;
272 Ecore_Event_Key *ev;
273
274 entry = (Ecore_SDL_Pressed*) eina_rbtree_inline_lookup(repeat, &event.key.keysym.sym, sizeof (event.key.keysym.sym),
275 EINA_RBTREE_CMP_KEY_CB(_ecore_sdl_pressed_node), NULL);
276 if (entry)
277 {
278 ev = _ecore_sdl_event_key(&event, timestamp);
279 if (ev) ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL);
280 }
281
282 ev = _ecore_sdl_event_key(&event, timestamp);
283 if (ev) ecore_event_add(ECORE_EVENT_KEY_DOWN, ev, NULL, NULL);
284
285 if (!entry)
286 {
287 entry = malloc(sizeof (Ecore_SDL_Pressed));
288 if (!entry) break;
289
290 entry->key = event.key.keysym.sym;
291
292 repeat = eina_rbtree_inline_insert(repeat, EINA_RBTREE_GET(entry),
293 EINA_RBTREE_CMP_NODE_CB(_ecore_sdl_pressed_key), NULL);
294 }
295 break;
296 }
297 case SDL_KEYUP:
298 {
299 Ecore_Event_Key *ev;
300 Ecore_SDL_Pressed *entry;
301
302 entry = (Ecore_SDL_Pressed*) eina_rbtree_inline_lookup(repeat, &event.key.keysym.sym, sizeof (event.key.keysym.sym),
303 EINA_RBTREE_CMP_KEY_CB(_ecore_sdl_pressed_node), NULL);
304 if (entry)
305 {
306 repeat = eina_rbtree_inline_remove(repeat, EINA_RBTREE_GET(entry),
307 EINA_RBTREE_CMP_NODE_CB(_ecore_sdl_pressed_key), NULL);
308 free(entry);
309 }
310
311 ev = _ecore_sdl_event_key(&event, timestamp);
312 if (ev) ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL);
313 break;
314 }
315 case SDL_WINDOWEVENT:
316 switch (event.window.event)
317 {
318 case SDL_WINDOWEVENT_RESIZED:
319 {
320 Ecore_Sdl_Event_Video_Resize *ev;
321
322 ev = calloc(1, sizeof (Ecore_Sdl_Event_Video_Resize));
323 ev->windowID = event.window.windowID;
324 ev->w = event.window.data1;
325 ev->h = event.window.data2;
326
327 ecore_event_add(ECORE_SDL_EVENT_RESIZE, ev, NULL, NULL);
328 break;
329 }
330 case SDL_WINDOWEVENT_EXPOSED:
331 {
332 Ecore_Sdl_Event_Window *ev;
333
334 ev = calloc(1, sizeof (Ecore_Sdl_Event_Window));
335 ev->windowID = event.window.windowID;
336
337 ecore_event_add(ECORE_SDL_EVENT_EXPOSE, ev, NULL, NULL);
338 break;
339 }
340 case SDL_WINDOWEVENT_ENTER:
341 case SDL_WINDOWEVENT_LEAVE:
342 {
343 Ecore_Event_Mouse_IO *ev;
344
345 ev = calloc(1, sizeof (Ecore_Event_Mouse_IO));
346 ev->window = event.window.windowID;
347 ev->event_window = event.window.windowID;
348
349 ecore_event_add(event.window.event == SDL_WINDOWEVENT_ENTER ?
350 ECORE_EVENT_MOUSE_IN : ECORE_EVENT_MOUSE_OUT,
351 ev, NULL, NULL);
352 break;
353 }
354 case SDL_WINDOWEVENT_FOCUS_GAINED:
355 case SDL_WINDOWEVENT_FOCUS_LOST:
356 {
357 Ecore_Sdl_Event_Window *ev;
358
359 ev = calloc(1, sizeof (Ecore_Sdl_Event_Window));
360 ev->windowID = event.window.windowID;
361
362 ecore_event_add(event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED ?
363 ECORE_SDL_EVENT_GOT_FOCUS : ECORE_SDL_EVENT_LOST_FOCUS,
364 ev, NULL, NULL);
365 break;
366 }
367 }
368 break;
369 case SDL_SYSWMEVENT:
370 case SDL_USEREVENT:
371 case SDL_JOYAXISMOTION:
372 case SDL_JOYBALLMOTION:
373 case SDL_JOYHATMOTION:
374 case SDL_JOYBUTTONDOWN:
375 case SDL_JOYBUTTONUP:
376 default:
377 break;
378 }
379 }
380 }
381