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