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