svn update: 60286 (latest:60286)
[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    NULL  // screen_geometry_get
338 };
339
340 static Ecore_Evas*
341 _ecore_evas_internal_sdl_new(int rmethod, const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
342 {
343    void                 *einfo;
344    Ecore_Evas           *ee;
345
346    if (!name)
347      name = ecore_evas_sdl_default;
348
349    if (ecore_evases) return NULL;
350
351    ee = calloc(1, sizeof(Ecore_Evas));
352    if (!ee) return NULL;
353
354    ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
355
356    ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_sdl_engine_func;
357
358    ee->driver = "sdl";
359    if (name) ee->name = strdup(name);
360
361    if (w < 1) w = 1;
362    if (h < 1) h = 1;
363    ee->visible = 1;
364    ee->w = w;
365    ee->h = h;
366
367    ee->prop.max.w = 0;
368    ee->prop.max.h = 0;
369    ee->prop.layer = 0;
370    ee->prop.focused = 1;
371    ee->prop.borderless = 1;
372    ee->prop.override = 1;
373    ee->prop.maximized = 1;
374    ee->prop.fullscreen = fullscreen;
375    ee->prop.withdrawn = 0;
376    ee->prop.sticky = 0;
377    ee->prop.window = 0;
378
379    /* init evas here */
380    ee->evas = evas_new();
381    evas_data_attach_set(ee->evas, ee);
382    evas_output_method_set(ee->evas, rmethod);
383
384    evas_output_size_set(ee->evas, w, h);
385    evas_output_viewport_set(ee->evas, 0, 0, w, h);
386
387    if (rmethod == evas_render_method_lookup("software_sdl"))
388      {
389 #ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
390         einfo = evas_engine_info_get(ee->evas);
391         if (einfo)
392           {
393              ((Evas_Engine_Info_SDL *)einfo)->info.rotation = 0;
394              ((Evas_Engine_Info_SDL *)einfo)->info.fullscreen = fullscreen;
395              ((Evas_Engine_Info_SDL *)einfo)->info.hwsurface = hwsurface;
396              ((Evas_Engine_Info_SDL *)einfo)->info.noframe = noframe;
397              ((Evas_Engine_Info_SDL *)einfo)->info.alpha = alpha;
398              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
399                {
400                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
401                }
402           }
403 #endif
404      }
405    else if (rmethod == evas_render_method_lookup("gl_sdl"))
406      {
407 #ifdef BUILD_ECORE_EVAS_OPENGL_SDL
408         einfo = evas_engine_info_get(ee->evas);
409         if (einfo)
410           {
411              ((Evas_Engine_Info_GL_SDL *)einfo)->flags.fullscreen = fullscreen;
412              ((Evas_Engine_Info_GL_SDL *)einfo)->flags.noframe = noframe;
413              if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
414                {
415                   ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
416                }
417           }
418 #endif
419      }
420
421    if (!ecore_sdl_init(name))
422      {
423         evas_free(ee->evas);
424         if (ee->name) free(ee->name);
425         free(ee);
426         return NULL;
427      }
428
429    _ecore_evas_sdl_init(w, h);
430
431    ecore_event_window_register(0, ee, ee->evas,
432                                (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
433                                (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
434                                (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
435                                (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
436
437    SDL_ShowCursor(SDL_DISABLE);
438
439    ee->engine.func->fn_render = _ecore_evas_sdl_render;
440    _ecore_evas_register(ee);
441
442    sdl_ee = ee;
443
444    evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
445    evas_focus_in(ee->evas);
446
447    return ee;
448 }
449 #endif
450
451 #ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
452 EAPI Ecore_Evas*
453 ecore_evas_sdl_new(const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
454 {
455    Ecore_Evas          *ee;
456    int                  rmethod;
457
458    rmethod = evas_render_method_lookup("software_sdl");
459    if (!rmethod) return NULL;
460
461    ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, hwsurface, noframe, alpha);
462    ee->driver = "sdl";
463    return ee;
464 }
465 #else
466 EAPI Ecore_Evas*
467 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__)
468 {
469    ERR("OUTCH !");
470    return NULL;
471 }
472 #endif
473
474 #ifdef BUILD_ECORE_EVAS_SOFTWARE_SDL
475 EAPI Ecore_Evas*
476 ecore_evas_sdl16_new(const char* name, int w, int h, int fullscreen, int hwsurface, int noframe, int alpha)
477 {
478    Ecore_Evas          *ee;
479    int                  rmethod;
480
481    rmethod = evas_render_method_lookup("software_16_sdl");
482    if (!rmethod) return NULL;
483
484    ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, hwsurface, noframe, alpha);
485    ee->driver = "software_16_sdl";
486    return ee;
487 }
488 #else
489 EAPI Ecore_Evas*
490 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__)
491 {
492    ERR("OUTCH !");
493    return NULL;
494 }
495 #endif
496
497 #ifdef BUILD_ECORE_EVAS_OPENGL_SDL
498 EAPI Ecore_Evas*
499 ecore_evas_gl_sdl_new(const char* name, int w, int h, int fullscreen, int noframe)
500 {
501    Ecore_Evas          *ee;
502    int                  rmethod;
503
504    rmethod = evas_render_method_lookup("gl_sdl");
505    if (!rmethod) return NULL;
506
507    ee = _ecore_evas_internal_sdl_new(rmethod, name, w, h, fullscreen, 0, noframe, 0);
508    ee->driver = "gl_sdl";
509    return ee;
510 }
511 #else
512 EAPI Ecore_Evas*
513 ecore_evas_gl_sdl_new(const char* name __UNUSED__, int w __UNUSED__, int h __UNUSED__, int fullscreen __UNUSED__, int noframe __UNUSED__)
514 {
515    ERR("OUTCH !");
516    return NULL;
517 }
518 #endif
519