96ea1d43de0a24b4b545008fe81087e3d3f927f2
[platform/upstream/ecore.git] / src / lib / ecore_evas / ecore_evas_cocoa.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include "Ecore.h"
6 #include "ecore_private.h"
7 #include "Ecore_Input.h"
8 #include "Ecore_Input_Evas.h"
9
10 #ifdef BUILD_ECORE_EVAS_OPENGL_COCOA
11 #include <Ecore_Cocoa.h>
12 #include <Evas_Engine_GL_Cocoa.h>
13 #endif
14
15 #include "ecore_evas_private.h"
16 #include "Ecore_Evas.h"
17
18
19 #ifdef BUILD_ECORE_EVAS_OPENGL_COCOA
20
21 // FIXME: this engine has lots of problems. only 1 window at a time, drawRect looks wrong, doesnt handle resizes and more
22
23 static int                      _ecore_evas_init_count = 0;
24 static Ecore_Evas               *ecore_evases = NULL;
25 static Ecore_Event_Handler      *ecore_evas_event_handlers[4] = {
26   NULL, NULL, NULL, NULL
27 };
28 static Ecore_Idle_Enterer       *ecore_evas_idle_enterer = NULL;
29 static Ecore_Poller             *ecore_evas_event = NULL;
30
31 static const char               *ecore_evas_cocoa_default = "EFL Cocoa";
32
33
34 static int
35 _ecore_evas_cocoa_render(Ecore_Evas *ee)
36 {
37    int rend = 0;
38    Eina_List *updates = NULL;
39    Eina_List *ll;
40    Ecore_Evas *ee2;
41
42    DBG("Render");
43
44    EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
45      {
46         if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
47         if (ee2->engine.func->fn_render)
48           rend |= ee2->engine.func->fn_render(ee2);
49         if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
50      }
51
52    if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
53    updates = evas_render_updates(ee->evas);
54    if (ee->prop.avoid_damage)
55      {
56         updates = evas_render_updates(ee->evas);
57         if (updates) evas_render_updates_free(updates);
58      }
59    else if ((ee->visible) ||
60             ((ee->should_be_visible) && (ee->prop.fullscreen)) ||
61             ((ee->should_be_visible) && (ee->prop.override)))
62      {
63         if (ee->shaped)
64           {
65              updates = evas_render_updates(ee->evas);
66              if (updates) evas_render_updates_free(updates);
67           }
68         else
69           {
70              updates = evas_render_updates(ee->evas);
71              if (updates) evas_render_updates_free(updates);
72           }
73      }
74    else
75      evas_norender(ee->evas);
76    if (updates) rend = 1;
77    if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
78
79    if (rend)
80      {
81         static int frames = 0;
82         static double t0 = 0.0;
83         double t, td;
84
85         t = ecore_time_get();
86         frames++;
87         if ((t - t0) > 1.0)
88           {
89              td = t - t0;
90              printf("FPS: %3.3f\n", (double)frames / td);
91              frames = 0;
92              t0 = t;
93           }
94      }
95
96    return rend;
97 }
98
99
100 static Ecore_Evas *
101 _ecore_evas_cocoa_match(void)
102 {
103   DBG("Match");
104   return ecore_evases;
105 }
106
107 static int
108 _ecore_evas_cocoa_event_got_focus(void *data __UNUSED__, int type __UNUSED__, void *event)
109 {
110   Ecore_Evas                   *ee;
111
112   DBG("Got Focus");
113
114   ee = _ecore_evas_cocoa_match();
115
116   if (!ee) return ECORE_CALLBACK_PASS_ON;
117   ee->prop.focused = 1;
118   evas_focus_in(ee->evas);
119   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
120    
121   return ECORE_CALLBACK_PASS_ON;
122 }
123
124 static int
125 _ecore_evas_cocoa_event_lost_focus(void *data __UNUSED__, int type __UNUSED__, void *event)
126 {
127   Ecore_Evas                   *ee;
128
129   DBG("Lost Focus");
130
131   ee = _ecore_evas_cocoa_match();
132
133   if (!ee) return ECORE_CALLBACK_PASS_ON;
134   evas_focus_out(ee->evas);
135   ee->prop.focused = 0;
136   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
137
138   return ECORE_CALLBACK_PASS_ON;
139 }
140
141 static int
142 _ecore_evas_cocoa_event_video_resize(void *data __UNUSED__, int type __UNUSED__, void *event)
143 {
144   /*Ecore_Cocoa_Event_Video_Resize *e;
145    Ecore_Evas                   *ee;
146
147    e = event;
148    ee = _ecore_evas_cocoa_match();
149
150    if (!ee) return 1; // pass on event
151    evas_output_size_set(ee->evas, e->w, e->h);
152
153    return 0;*/
154
155   DBG("Video Resize");
156   return ECORE_CALLBACK_PASS_ON;
157 }
158
159 static int
160 _ecore_evas_cocoa_event_video_expose(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
161 {
162   Ecore_Evas                   *ee;
163   int                          w;
164   int                          h;
165
166   DBG("Video Expose");
167
168   ee = _ecore_evas_cocoa_match();
169
170   if (!ee) return ECORE_CALLBACK_PASS_ON;
171   evas_output_size_get(ee->evas, &w, &h);
172   evas_damage_rectangle_add(ee->evas, 0, 0, w, h);
173
174   return ECORE_CALLBACK_PASS_ON;
175 }
176
177 static int
178 _ecore_evas_idle_enter(void *data __UNUSED__)
179 {
180   Ecore_Evas  *ee;
181   double       t1 = 0.;
182   double       t2 = 0.;
183
184   DBG("Idle enter");
185
186   EINA_INLIST_FOREACH(ecore_evases, ee)
187     {
188       if (ee->visible)
189         evas_render(ee->evas);
190       else
191         evas_norender(ee->evas);
192     }
193
194   return EINA_TRUE;
195 }
196
197 static int
198 _ecore_evas_cocoa_event(void *data)
199 {
200   //  ecore_cocoa_feed_events();
201
202   DBG("Cocoa Event");
203
204   return 1;
205 }
206
207 static int
208 _ecore_evas_cocoa_init(void)
209 {
210   DBG("Cocoa Init");
211   _ecore_evas_init_count++;
212   if (_ecore_evas_init_count > 1) 
213     return _ecore_evas_init_count;
214
215   ecore_evas_event_handlers[0] = ecore_event_handler_add(ECORE_COCOA_EVENT_GOT_FOCUS, _ecore_evas_cocoa_event_got_focus, NULL);
216   ecore_evas_event_handlers[1] = ecore_event_handler_add(ECORE_COCOA_EVENT_LOST_FOCUS, _ecore_evas_cocoa_event_lost_focus, NULL);
217   ecore_evas_event_handlers[2] = ecore_event_handler_add(ECORE_COCOA_EVENT_RESIZE, _ecore_evas_cocoa_event_video_resize, NULL);
218   ecore_evas_event_handlers[3] = ecore_event_handler_add(ECORE_COCOA_EVENT_EXPOSE, _ecore_evas_cocoa_event_video_expose, NULL);
219
220   ecore_event_evas_init();  
221   return _ecore_evas_init_count;
222 }
223
224 static int
225 _ecore_evas_cocoa_shutdown(void)
226 {
227   DBG("Cocoa SHutodwn");
228   _ecore_evas_init_count--;
229   if (_ecore_evas_init_count == 0)
230     {
231       int i;
232
233       while (ecore_evases) _ecore_evas_free(ecore_evases);
234
235       for (i = 0; i < sizeof (ecore_evas_event_handlers) / sizeof (Ecore_Event_Handler*); i++)
236         ecore_event_handler_del(ecore_evas_event_handlers[i]);
237       ecore_event_evas_shutdown();
238       ecore_idle_enterer_del(ecore_evas_idle_enterer);
239       ecore_evas_idle_enterer = NULL;
240       ecore_poller_del(ecore_evas_event);
241       ecore_evas_event = NULL;
242
243       ecore_event_evas_shutdown();
244     }
245   if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
246   return _ecore_evas_init_count;
247 }
248
249 static void
250 _ecore_evas_cocoa_free(Ecore_Evas *ee)
251 {
252   DBG("Cocoa Free");
253   ecore_evases = (Ecore_Evas *) eina_inlist_remove(EINA_INLIST_GET(ecore_evases), EINA_INLIST_GET(ee));
254   ecore_event_window_unregister(0);
255   _ecore_evas_cocoa_shutdown();
256   ecore_cocoa_shutdown();
257 }
258
259 static void
260 _ecore_evas_resize(Ecore_Evas *ee, int w, int h)
261 {
262   DBG("Resize");
263   if ((w == ee->w) && (h == ee->h)) return;
264   ee->w = w;
265   ee->h = h;
266
267   printf("Ecore_Evas Resize %d %d\n", w, h);
268
269   ecore_cocoa_window_resize(ee->prop.window, w, h);
270
271   evas_output_size_set(ee->evas, ee->w, ee->h);
272   evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
273   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
274
275   if (ee->func.fn_resize) ee->func.fn_resize(ee);
276 }
277
278 static void
279 _ecore_evas_move_resize(Ecore_Evas *ee, int x, int y, int w, int h)
280 {
281   DBG("Move Resize");
282   if ((w == ee->w) && (h == ee->h)) return;
283   ee->w = w;
284   ee->h = h;
285
286   ecore_cocoa_window_move_resize(ee->prop.window, x, y, w, h);
287
288   evas_output_size_set(ee->evas, ee->w, ee->h);
289   evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
290   evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
291
292   if (ee->func.fn_resize) ee->func.fn_resize(ee);
293 }
294
295
296 static void
297 _ecore_evas_show(Ecore_Evas *ee, int x, int y, int w, int h)
298 {
299   DBG("Show");
300    ee->should_be_visible = 1;
301    if (ee->prop.avoid_damage)
302      _ecore_evas_cocoa_render(ee);
303
304    ecore_cocoa_window_show(ee->prop.window);
305    evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
306 }
307
308
309 static void
310 _ecore_evas_hide(Ecore_Evas *ee, int x, int y, int w, int h)
311 {
312   DBG("Hide");
313
314    ecore_cocoa_window_hide(ee->prop.window);
315    ee->should_be_visible = 0;
316 }
317
318 static void
319 _ecore_evas_title_set(Ecore_Evas *ee, const char *title)
320 {
321    INF("ecore evas title set");
322
323    if (ee->prop.title) free(ee->prop.title);
324    ee->prop.title = NULL;
325    if (title) ee->prop.title = strdup(title);
326    ecore_cocoa_window_title_set(ee->prop.window,
327                                 ee->prop.title);
328 }
329
330 static void
331 _ecore_evas_object_cursor_del(void *data, Evas *e, Evas_Object *obj, void *event_info)
332 {
333   Ecore_Evas *ee;
334
335   DBG("Cursor DEL");
336
337   ee = data;
338   if (ee)
339     ee->prop.cursor.object = NULL;
340 }
341
342 static void
343 _ecore_evas_object_cursor_set(Ecore_Evas *ee, Evas_Object *obj, int layer, int hot_x, int hot_y)
344 {
345   int x, y;
346   DBG("Cursor Set");
347   if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object);
348
349   if (obj == NULL)
350     {
351       ee->prop.cursor.object = NULL;
352       ee->prop.cursor.layer = 0;
353       ee->prop.cursor.hot.x = 0;
354       ee->prop.cursor.hot.y = 0;
355       return;
356     }
357
358   ee->prop.cursor.object = obj;
359   ee->prop.cursor.layer = layer;
360   ee->prop.cursor.hot.x = hot_x;
361   ee->prop.cursor.hot.y = hot_y;
362
363   evas_pointer_output_xy_get(ee->evas, &x, &y);
364   evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer);
365   evas_object_move(ee->prop.cursor.object,
366                    x - ee->prop.cursor.hot.x,
367                    y - ee->prop.cursor.hot.y);
368
369   evas_object_pass_events_set(ee->prop.cursor.object, 1);
370
371   if (evas_pointer_inside_get(ee->evas))
372     evas_object_show(ee->prop.cursor.object);
373
374   evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _ecore_evas_object_cursor_del, ee);
375 }
376
377 static int
378 _ecore_evas_engine_cocoa_init(Ecore_Evas *ee)
379 {
380    Evas_Engine_Info_GL_Cocoa *einfo;
381    const char                *driver;
382    int                        rmethod;
383
384    DBG("Cocoa Init");
385
386    driver = "gl_cocoa";
387
388    rmethod = evas_render_method_lookup(driver);
389    if (!rmethod)
390      return 0;
391
392    ee->driver = driver;
393    evas_output_method_set(ee->evas, rmethod);
394
395    einfo = (Evas_Engine_Info_GL_Cocoa *)evas_engine_info_get(ee->evas);
396    if (einfo)
397      {
398         /* FIXME: REDRAW_DEBUG missing for now */
399         einfo->window = ee->prop.window;
400         //einfo->info.depth = ecore_win32_screen_depth_get();
401         //einfo->info.rotation = 0;
402         if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
403           {
404              ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
405              return 0;
406           }
407         ecore_cocoa_window_view_set(einfo->window, einfo->view);
408      }
409    else
410      {
411         ERR("evas_engine_info_set() init engine '%s' failed.", ee->driver);
412         return 0;
413      }
414
415    return 1;
416 }
417
418 static Ecore_Evas_Engine_Func _ecore_cocoa_engine_func =
419   {
420     _ecore_evas_cocoa_free,
421     NULL,
422     NULL,
423     NULL,
424     NULL,
425     NULL,
426     NULL,
427     NULL,
428     NULL,
429     NULL,
430     NULL,
431     NULL,
432     NULL,
433     NULL,
434     NULL,
435     NULL, //move
436     NULL,
437     _ecore_evas_resize,
438     _ecore_evas_move_resize,
439     NULL, //rotation
440     NULL, //shaped
441     _ecore_evas_show,
442     _ecore_evas_hide,
443     NULL, //raise
444     NULL, //lower
445     NULL, //activate
446     _ecore_evas_title_set,
447     NULL,
448     NULL,
449     NULL,
450     NULL,
451     NULL,
452     _ecore_evas_object_cursor_set,
453     NULL,
454     NULL,
455     NULL,
456     NULL,
457     NULL,
458     NULL,
459     NULL,
460     NULL,
461     NULL,
462     NULL,
463     NULL,
464     NULL,
465     NULL, //transparent    
466     NULL, // profiles_set
467      
468      NULL,
469      NULL,
470      NULL,
471      NULL,
472      NULL,
473      NULL,
474
475      NULL, // render
476      NULL,
477      NULL  // screen_dpi_get
478   };
479 #endif
480
481 EAPI Ecore_Evas *
482 ecore_evas_cocoa_new(Ecore_Cocoa_Window *parent, int x, int y, int w, int h)
483 {
484 #ifdef BUILD_ECORE_EVAS_OPENGL_COCOA
485   Evas_Engine_Info_GL_Cocoa *einfo;
486   Ecore_Evas           *ee;
487   int                  rmethod;
488
489   DBG("Cocoa new");
490
491   if (!ecore_cocoa_init())
492     return NULL;
493
494   ee = calloc(1, sizeof(Ecore_Evas));
495   if (!ee)
496     goto shutdown_ecore_cocoa;
497
498   ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
499
500   _ecore_evas_cocoa_init();
501
502   ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_cocoa_engine_func;
503
504   if (w < 1) w = 1;
505   if (h < 1) h = 1;
506   ee->visible = 1;
507   ee->x = x;
508   ee->y = y;
509   ee->w = w;
510   ee->h = h;
511   ee->req.x = ee->x;
512   ee->req.y = ee->y;
513   ee->req.w = ee->w;
514   ee->req.h = ee->h;
515
516   ee->semi_sync = 1;
517
518
519   ee->prop.max.w = 32767;
520   ee->prop.max.h = 32767;
521   ee->prop.layer = 4;
522   ee->prop.request_pos = 0;
523   ee->prop.sticky = 0;
524   ee->prop.window = 0;
525
526   printf("Create New Evas\n");
527
528   ee->evas = evas_new();
529   
530   if (!ee->evas)
531     goto free_name;
532
533   evas_data_attach_set(ee->evas, ee);
534   evas_output_method_set(ee->evas, rmethod);
535   evas_output_size_set(ee->evas, w, h);
536   evas_output_viewport_set(ee->evas, 0, 0, w, h);
537
538   printf("Create New Cocoa Window\n");
539   ee->prop.window = (Ecore_Cocoa_Window*)ecore_cocoa_window_new(x, y, w, h);
540   printf("Window Created %p\n", ee->prop.window);
541   if (!ee->prop.window)
542     {
543       _ecore_evas_cocoa_shutdown();
544       free(ee);
545       return NULL;
546     }
547
548   printf("Init Evas engine cocoa\n");
549   if (!_ecore_evas_engine_cocoa_init(ee))
550     {
551       _ecore_evas_cocoa_shutdown();
552       free(ee);
553       return NULL;
554     }
555   
556   
557   ee->engine.func->fn_render = _ecore_evas_cocoa_render;
558   _ecore_evas_register(ee);
559   ecore_event_window_register(0, ee, ee->evas, NULL, NULL, NULL, NULL);
560   
561   evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
562   printf("Ecore Evas returned : %p\n", ee);
563   return ee;
564   
565  free_window:
566   /* FIXME: free window here */
567  free_evas:
568   free(ee->evas);
569  free_name:
570   free(ee->name);
571  free_ee:
572   _ecore_evas_cocoa_shutdown();
573   free(ee);
574  shutdown_ecore_cocoa:
575   ecore_cocoa_shutdown();
576   
577   return NULL;
578 #else
579   ERR("Cocoa support in ecore-evas not enabled");
580   return NULL;
581   (void) parent;
582   (void) x; (void) y; (void) w; (void) h;
583 #endif
584 }