1d08322084933bf9cfc951f890ba87275a3ed83a
[profile/ivi/ecore.git] / src / lib / ecore_evas / ecore_evas_sdl.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <Ecore.h>
6 #include <Ecore_Input.h>
7 #include <Ecore_Input_Evas.h>
8 #if defined(BUILD_ECORE_EVAS_SOFTWARE_SDL) || defined(BUILD_ECORE_EVAS_OPENGL_SDL)
9 # include <Ecore_Sdl.h>
10 # ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
11 #  include <Evas_Engine_SDL.h>
12 # endif
13 # ifdef BUILD_ECORE_EVAS_OPENGL_SDL
14 #  include <Evas_Engine_GL_SDL.h>
15 # endif
16 #endif
17
18 #include "ecore_evas_private.h"
19 #include "Ecore_Evas.h"
20
21 // fixme: 1 sdl window only at a time? seems wrong
22
23 #if defined(BUILD_ECORE_EVAS_SOFTWARE_SDL) || defined(BUILD_ECORE_EVAS_OPENGL_SDL)
24
25 /* static char *ecore_evas_default_display = "0"; */
26 /* static Ecore_List *ecore_evas_input_devices = NULL; */
27
28 static int                      _ecore_evas_init_count = 0;
29
30 static Ecore_Evas               *sdl_ee = NULL;
31 static Ecore_Event_Handler      *ecore_evas_event_handlers[4] = {
32    NULL, NULL, NULL, NULL
33 };
34
35 static const char               *ecore_evas_sdl_default = "EFL SDL";
36 static int                      _ecore_evas_fps_debug = 0;
37 static Ecore_Poller             *ecore_evas_event;
38 static Ecore_Evas                *ecore_evases = NULL;
39
40 static Ecore_Evas *
41 _ecore_evas_sdl_match(void)
42 {
43    return sdl_ee;
44 }
45
46 static Eina_Bool
47 _ecore_evas_sdl_event_got_focus(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
48 {
49    Ecore_Evas                   *ee;
50
51    ee = _ecore_evas_sdl_match();
52
53    if (!ee) return ECORE_CALLBACK_PASS_ON;
54    /* pass on event */
55    ee->prop.focused = 1;
56
57    return ECORE_CALLBACK_DONE;
58 }
59
60 static Eina_Bool
61 _ecore_evas_sdl_event_lost_focus(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
62 {
63    Ecore_Evas                   *ee;
64
65    ee = _ecore_evas_sdl_match();
66
67    if (!ee) return ECORE_CALLBACK_PASS_ON;
68    /* pass on event */
69    ee->prop.focused = 0;
70
71    return ECORE_CALLBACK_DONE;
72 }
73
74 static Eina_Bool
75 _ecore_evas_sdl_event_video_resize(void *data __UNUSED__, int type __UNUSED__, void *event)
76 {
77    Ecore_Sdl_Event_Video_Resize *e;
78    Ecore_Evas                   *ee;
79
80    e = event;
81    ee = _ecore_evas_sdl_match();
82
83    if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */
84    evas_output_size_set(ee->evas, e->w, e->h);
85
86    return ECORE_CALLBACK_DONE;
87 }
88
89 static Eina_Bool
90 _ecore_evas_sdl_event_video_expose(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
91 {
92    Ecore_Evas                   *ee;
93    int                          w;
94    int                          h;
95
96    ee = _ecore_evas_sdl_match();
97
98    if (!ee) return ECORE_CALLBACK_PASS_ON;
99    evas_output_size_get(ee->evas, &w, &h);
100    evas_damage_rectangle_add(ee->evas, 0, 0, w, h);
101
102    return ECORE_CALLBACK_DONE;
103 }
104
105 static int
106 _ecore_evas_render(Ecore_Evas *ee)
107 {
108    Eina_List *updates;
109
110    updates = evas_render_updates(ee->evas);
111    if (updates)
112      {
113         evas_render_updates_free(updates);
114         _ecore_evas_idle_timeout_update(ee);
115      }
116    return updates ? 1 : 0;
117 }
118
119 static int
120 _ecore_evas_sdl_render(Ecore_Evas *ee)
121 {
122    int rend = 0;
123
124 #ifdef BUILD_ECORE_EVAS_SOFTWARE_BUFFER
125    Eina_List *ll;
126    Ecore_Evas *ee2;
127
128    EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
129      {
130         if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
131         rend |= _ecore_evas_buffer_render(ee2);
132         if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
133      }
134 #endif
135
136    if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
137
138    if (ee->prop.avoid_damage) rend = _ecore_evas_render(ee);
139    else if ((ee->visible) ||
140             ((ee->should_be_visible) && (ee->prop.fullscreen)) ||
141             ((ee->should_be_visible) && (ee->prop.override)))
142      rend |= _ecore_evas_render(ee);
143    else
144      evas_norender(ee->evas);
145
146    if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
147    return rend;
148 }
149
150 static Eina_Bool
151 _ecore_evas_sdl_event(void *data __UNUSED__)
152 {
153    ecore_sdl_feed_events();
154    return ECORE_CALLBACK_RENEW;
155 }
156
157 static int
158 _ecore_evas_sdl_init(int w __UNUSED__, int h __UNUSED__)
159 {
160    _ecore_evas_init_count++;
161    if (_ecore_evas_init_count > 1) return _ecore_evas_init_count;
162
163 #ifndef _WIN32
164    if (getenv("ECORE_EVAS_FPS_DEBUG")) _ecore_evas_fps_debug = 1;
165 #endif /* _WIN32 */
166    // this is pretty bad: poller? and set poll time? pol time is meant to be 
167    // adjustable for things like polling battery state, or amoutn of spare
168    // memory etc.
169    // 
170    ecore_evas_event = ecore_poller_add(ECORE_POLLER_CORE, 1, _ecore_evas_sdl_event, NULL);
171    ecore_poller_poll_interval_set(ECORE_POLLER_CORE, 0.006);
172 #ifndef _WIN32
173    if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_init();
174 #endif /* _WIN32 */
175
176    ecore_event_evas_init();
177
178    ecore_evas_event_handlers[0] = ecore_event_handler_add(ECORE_SDL_EVENT_GOT_FOCUS, _ecore_evas_sdl_event_got_focus, NULL);
179    ecore_evas_event_handlers[1] = ecore_event_handler_add(ECORE_SDL_EVENT_LOST_FOCUS, _ecore_evas_sdl_event_lost_focus, NULL);
180    ecore_evas_event_handlers[2] = ecore_event_handler_add(ECORE_SDL_EVENT_RESIZE, _ecore_evas_sdl_event_video_resize, NULL);
181    ecore_evas_event_handlers[3] = ecore_event_handler_add(ECORE_SDL_EVENT_EXPOSE, _ecore_evas_sdl_event_video_expose, NULL);
182
183    return _ecore_evas_init_count;
184 }
185
186 static int
187 _ecore_evas_sdl_shutdown(void)
188 {
189    _ecore_evas_init_count--;
190    if (_ecore_evas_init_count == 0)
191      {
192         int i;
193
194         for (i = 0; i < sizeof (ecore_evas_event_handlers) / sizeof (Ecore_Event_Handler*); i++)
195           ecore_event_handler_del(ecore_evas_event_handlers[i]);
196         ecore_event_evas_shutdown();
197         ecore_poller_del(ecore_evas_event);
198         ecore_evas_event = NULL;
199 #ifndef _WIN32
200         if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_shutdown();
201 #endif /* _WIN32 */
202      }
203    if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
204    return _ecore_evas_init_count;
205 }
206
207 static void
208 _ecore_evas_sdl_free(Ecore_Evas *ee)
209 {
210    if (sdl_ee == ee) sdl_ee = NULL;
211    
212    ecore_event_window_unregister(0);
213    _ecore_evas_sdl_shutdown();
214    ecore_sdl_shutdown();
215 }
216
217 static void
218 _ecore_evas_resize(Ecore_Evas *ee, int w, int h)
219 {
220    if ((w == ee->w) && (h == ee->h)) return;
221    ee->w = w;
222    ee->h = h;
223
224    evas_output_size_set(ee->evas, ee->w, ee->h);
225    evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
226    evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
227
228    if (ee->func.fn_resize) ee->func.fn_resize(ee);
229 }
230
231 static void
232 _ecore_evas_move_resize(Ecore_Evas *ee, int x __UNUSED__, int y __UNUSED__, int w, int h)
233 {
234    if ((w == ee->w) && (h == ee->h)) return;
235    ee->w = w;
236    ee->h = h;
237
238    evas_output_size_set(ee->evas, ee->w, ee->h);
239    evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
240    evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
241
242    if (ee->func.fn_resize) ee->func.fn_resize(ee);
243 }
244
245 static void
246 _ecore_evas_object_cursor_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
247 {
248    Ecore_Evas *ee;
249
250    ee = data;
251    if (ee)
252      ee->prop.cursor.object = NULL;
253 }
254
255 static void
256 _ecore_evas_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
257 {
258    int x, y;
259
260    if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
261
262    if (!obj)
263      {
264         ee->prop.cursor.object = NULL;
265         ee->prop.cursor.layer = 0;
266         ee->prop.cursor.hot.x = 0;
267         ee->prop.cursor.hot.y = 0;
268         return;
269      }
270
271    ee->prop.cursor.object = obj;
272    ee->prop.cursor.layer = layer;
273    ee->prop.cursor.hot.x = hot_x;
274    ee->prop.cursor.hot.y = hot_y;
275    evas_pointer_output_xy_get(ee->evas, &x, &y);
276    evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
277    evas_object_move(ee->prop.cursor.object,
278                     x - ee->prop.cursor.hot.x,
279                     y - ee->prop.cursor.hot.y);
280    evas_object_pass_events_set(ee->prop.cursor.object, 1);
281    if (evas_pointer_inside_get(ee->evas))
282      evas_object_show(ee->prop.cursor.object);
283
284    evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
285 }
286
287 static Ecore_Evas_Engine_Func _ecore_sdl_engine_func =
288 {
289    _ecore_evas_sdl_free,
290    NULL,
291    NULL,
292    NULL,
293    NULL,
294    NULL,
295    NULL,
296    NULL,
297    NULL,
298    NULL,
299    NULL,
300    NULL,
301    NULL,
302    NULL,
303    NULL,
304    NULL,
305    NULL,
306    _ecore_evas_resize,
307    _ecore_evas_move_resize,
308    NULL,
309    NULL,
310    NULL,
311    NULL,
312    NULL,
313    NULL,
314    NULL,
315    NULL,
316    NULL,
317    NULL,
318    NULL,
319    NULL,
320    NULL,
321    _ecore_evas_object_cursor_set,
322    NULL,
323    NULL,
324    NULL,
325    NULL,
326    NULL,
327    NULL,
328    NULL,
329    NULL,
330    NULL,
331    NULL,
332    NULL,
333    NULL,
334    NULL, //transparent
335      
336      NULL // render
337 };
338
339 static Ecore_Evas*
340 _ecore_evas_internal_sdl_new(int rmethod, const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
341 {
342    void                 *einfo;
343    Ecore_Evas           *ee;
344
345    if (!name)
346      name = ecore_evas_sdl_default;
347
348    if (ecore_evases) return NULL;
349
350    ee = calloc(1, sizeof(Ecore_Evas));
351    if (!ee) return NULL;
352
353    ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
354
355    ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_sdl_engine_func;
356
357    ee->driver = "sdl";
358    if (name) ee->name = strdup(name);
359
360    if (w < 1) w = 1;
361    if (h < 1) h = 1;
362    ee->visible = 1;
363    ee->w = w;
364    ee->h = h;
365
366    ee->prop.max.w = 0;
367    ee->prop.max.h = 0;
368    ee->prop.layer = 0;
369    ee->prop.focused = 1;
370    ee->prop.borderless = 1;
371    ee->prop.override = 1;
372    ee->prop.maximized = 1;
373    ee->prop.fullscreen = fullscreen;
374    ee->prop.withdrawn = 0;
375    ee->prop.sticky = 0;
376    ee->prop.window = 0;
377
378    /* init evas here */
379    ee->evas = evas_new();
380    evas_data_attach_set(ee->evas, ee);
381    evas_output_method_set(ee->evas, rmethod);
382
383    evas_output_size_set(ee->evas, w, h);
384    evas_output_viewport_set(ee->evas, 0, 0, w, h);
385
386    if (rmethod == evas_render_method_lookup("software_sdl"))
387      {
388 #ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
389         einfo = evas_engine_info_get(ee->evas);
390         if (einfo)
391           {
392              ((Evas_Engine_Info_SDL *)einfo)->info.rotation = 0;
393              ((Evas_Engine_Info_SDL *)einfo)->info.fullscreen = fullscreen;
394              ((Evas_Engine_Info_SDL *)einfo)->info.hwsurface = hwsurface;
395              ((Evas_Engine_Info_SDL *)einfo)->info.noframe = noframe;
396              ((Evas_Engine_Info_SDL *)einfo)->info.alpha = alpha;
397              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
398                {
399                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
400                }
401           }
402 #endif
403      }
404    else if (rmethod == evas_render_method_lookup("gl_sdl"))
405      {
406 #ifdef BUILD_ECORE_EVAS_OPENGL_SDL
407         einfo = evas_engine_info_get(ee->evas);
408         if (einfo)
409           {
410              ((Evas_Engine_Info_GL_SDL *)einfo)->flags.fullscreen = fullscreen;
411              ((Evas_Engine_Info_GL_SDL *)einfo)->flags.noframe = noframe;
412              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
413                {
414                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
415                }
416           }
417 #endif
418      }
419
420    if (!ecore_sdl_init(name))
421      {
422         evas_free(ee->evas);
423         if (ee->name) free(ee->name);
424         free(ee);
425         return NULL;
426      }
427
428    _ecore_evas_sdl_init(w, h);
429
430    ecore_event_window_register(0, ee, ee->evas,
431                                (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
432                                (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
433                                (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
434                                (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
435
436    SDL_ShowCursor(SDL_DISABLE);
437
438    ee->engine.func->fn_render = _ecore_evas_sdl_render;
439    _ecore_evas_register(ee);
440    
441    sdl_ee = ee;
442    
443    evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
444    evas_focus_in(ee->evas);
445
446    return ee;
447 }
448 #endif
449
450 #ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
451 EAPI Ecore_Evas*
452 ecore_evas_sdl_new(const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
453 {
454    Ecore_Evas          *ee;
455    int                  rmethod;
456
457    rmethod = evas_render_method_lookup("software_sdl");
458    if (!rmethod) return NULL;
459
460    ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, hwsurface, noframe, alpha);
461    ee->driver = "sdl";
462    return ee;
463 }
464 #else
465 EAPI Ecore_Evas*
466 ecore_evas_sdl_new(const char* name __UNUSED__, int w __UNUSED__, int h __UNUSED__, int fullscreen __UNUSED__, int hwsurface __UNUSED__, int noframe __UNUSED__, int alpha __UNUSED__)
467 {
468    ERR("OUTCH !");
469    return NULL;
470 }
471 #endif
472
473 #ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
474 EAPI Ecore_Evas*
475 ecore_evas_sdl16_new(const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
476 {
477    Ecore_Evas          *ee;
478    int                  rmethod;
479
480    rmethod = evas_render_method_lookup("software_16_sdl");
481    if (!rmethod) return NULL;
482
483    ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, hwsurface, noframe, alpha);
484    ee->driver = "software_16_sdl";
485    return ee;
486 }
487 #else
488 EAPI Ecore_Evas*
489 ecore_evas_sdl16_new(const char* name __UNUSED__, int w __UNUSED__, int h __UNUSED__, int fullscreen __UNUSED__, int hwsurface __UNUSED__, int noframe __UNUSED__, int alpha __UNUSED__)
490 {
491    ERR("OUTCH !");
492    return NULL;
493 }
494 #endif
495
496 #ifdef BUILD_ECORE_EVAS_OPENGL_SDL
497 EAPI Ecore_Evas*
498 ecore_evas_gl_sdl_new(const char* name, int w, int h, int fullscreen, int noframe)
499 {
500    Ecore_Evas          *ee;
501    int                  rmethod;
502
503    rmethod = evas_render_method_lookup("gl_sdl");
504    if (!rmethod) return NULL;
505
506    ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, 0, noframe, 0);
507    ee->driver = "gl_sdl";
508    return ee;
509 }
510 #else
511 EAPI Ecore_Evas*
512 ecore_evas_gl_sdl_new(const char* name __UNUSED__, int w __UNUSED__, int h __UNUSED__, int fullscreen __UNUSED__, int noframe __UNUSED__)
513 {
514    ERR("OUTCH !");
515    return NULL;
516 }
517 #endif
518