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