Ecore_Evas (wayland_shm): Calculate shm pool size based on output size.
[framework/uifw/ecore.git] / src / lib / ecore_evas / ecore_evas_wayland_shm.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 //#define LOGFNS 1
6
7 #ifdef LOGFNS
8 # include <stdio.h>
9 # define LOGFN(fl, ln, fn) \
10    printf("-ECORE_EVAS-WL: %25s: %5i - %s\n", fl, ln, fn);
11 #else
12 # define LOGFN(fl, ln, fn)
13 #endif
14
15 #ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
16 # include <stdlib.h>
17 # include <string.h>
18 # include <unistd.h>
19 # include <sys/types.h>
20 # include <sys/mman.h>
21 #endif
22
23 #include <Eina.h>
24 #include <Evas.h>
25 #include <Ecore.h>
26
27 #include "ecore_evas_private.h"
28 #include "Ecore_Evas.h"
29
30 #ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
31 # include <Evas_Engine_Wayland_Shm.h>
32 # include <Ecore_Wayland.h>
33
34 /* local structures */
35 typedef struct _EE_Wl_Smart_Data EE_Wl_Smart_Data;
36 struct _EE_Wl_Smart_Data 
37 {
38    Evas_Object *frame;
39    Evas_Object *text;
40    Evas_Coord x, y, w, h;
41 };
42
43 /* local function prototypes */
44 static int _ecore_evas_wl_init(void);
45 static int _ecore_evas_wl_shutdown(void);
46 static void _ecore_evas_wl_pre_free(Ecore_Evas *ee);
47 static void _ecore_evas_wl_free(Ecore_Evas *ee);
48 static void _ecore_evas_wl_callback_resize_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
49 static void _ecore_evas_wl_callback_move_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
50 static void _ecore_evas_wl_callback_delete_request_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
51 static void _ecore_evas_wl_callback_focus_in_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
52 static void _ecore_evas_wl_callback_focus_out_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
53 static void _ecore_evas_wl_callback_mouse_in_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
54 static void _ecore_evas_wl_callback_mouse_out_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
55 static void _ecore_evas_wl_move(Ecore_Evas *ee, int x, int y);
56 static void _ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h);
57 static void _ecore_evas_wl_show(Ecore_Evas *ee);
58 static void _ecore_evas_wl_hide(Ecore_Evas *ee);
59 static void _ecore_evas_wl_raise(Ecore_Evas *ee);
60 static void _ecore_evas_wl_title_set(Ecore_Evas *ee, const char *title);
61 static void _ecore_evas_wl_name_class_set(Ecore_Evas *ee, const char *n, const char *c);
62 static void _ecore_evas_wl_size_min_set(Ecore_Evas *ee, int w, int h);
63 static void _ecore_evas_wl_size_max_set(Ecore_Evas *ee, int w, int h);
64 static void _ecore_evas_wl_size_base_set(Ecore_Evas *ee, int w, int h);
65 static void _ecore_evas_wl_size_step_set(Ecore_Evas *ee, int w, int h);
66 static void _ecore_evas_wl_layer_set(Ecore_Evas *ee, int layer);
67 static void _ecore_evas_wl_iconified_set(Ecore_Evas *ee, int iconify);
68 static void _ecore_evas_wl_maximized_set(Ecore_Evas *ee, int max);
69 static void _ecore_evas_wl_fullscreen_set(Ecore_Evas *ee, int full);
70 static void _ecore_evas_wl_ignore_events_set(Ecore_Evas *ee, int ignore);
71 static void _ecore_evas_wl_alpha_set(Ecore_Evas *ee, int alpha);
72 static void _ecore_evas_wl_transparent_set(Ecore_Evas *ee, int transparent);
73 static int _ecore_evas_wl_render(Ecore_Evas *ee);
74 static void _ecore_evas_wl_screen_geometry_get(const Ecore_Evas *ee __UNUSED__, int *x, int *y, int *w, int *h);
75 static struct wl_shm_pool *_ecore_evas_wl_shm_pool_create(int size, void **data);
76
77 static void _ecore_evas_wl_buffer_new(Ecore_Evas *ee, struct wl_shm_pool *pool);
78
79 static Eina_Bool _ecore_evas_wl_cb_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event);
80 static Eina_Bool _ecore_evas_wl_cb_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event);
81 static Eina_Bool _ecore_evas_wl_cb_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event);
82 static Eina_Bool _ecore_evas_wl_cb_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event);
83 static Eina_Bool _ecore_evas_wl_cb_window_configure(void *data __UNUSED__, int type __UNUSED__, void *event);
84
85 /* SMART stuff for frame */
86 static Evas_Smart *_ecore_evas_wl_smart = NULL;
87
88 static void _ecore_evas_wl_smart_init(void);
89 static void _ecore_evas_wl_smart_add(Evas_Object *obj);
90 static void _ecore_evas_wl_smart_del(Evas_Object *obj);
91 static void _ecore_evas_wl_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
92 static void _ecore_evas_wl_smart_show(Evas_Object *obj);
93 static void _ecore_evas_wl_smart_hide(Evas_Object *obj);
94
95 static Evas_Object *_ecore_evas_wl_frame_add(Evas *evas);
96
97 /* local variables */
98 static int _ecore_evas_wl_init_count = 0;
99 static Ecore_Event_Handler *_ecore_evas_wl_event_hdls[5];
100
101 static Ecore_Evas_Engine_Func _ecore_wl_engine_func = 
102 {
103    _ecore_evas_wl_free,
104    _ecore_evas_wl_callback_resize_set,
105    _ecore_evas_wl_callback_move_set,
106    NULL, 
107    NULL,
108    _ecore_evas_wl_callback_delete_request_set,
109    NULL,
110    _ecore_evas_wl_callback_focus_in_set,
111    _ecore_evas_wl_callback_focus_out_set,
112    _ecore_evas_wl_callback_mouse_in_set,
113    _ecore_evas_wl_callback_mouse_out_set,
114    NULL, // sticky_set
115    NULL, // unsticky_set
116    NULL, // pre_render_set
117    NULL, // post_render_set
118    _ecore_evas_wl_move,
119    NULL, // managed_move
120    _ecore_evas_wl_resize,
121    NULL, // move_resize
122    NULL, // rotation_set
123    NULL, // shaped_set
124    _ecore_evas_wl_show,
125    _ecore_evas_wl_hide,
126    _ecore_evas_wl_raise,
127    NULL, // lower
128    NULL, // activate
129    _ecore_evas_wl_title_set,
130    _ecore_evas_wl_name_class_set,
131    _ecore_evas_wl_size_min_set,
132    _ecore_evas_wl_size_max_set,
133    _ecore_evas_wl_size_base_set,
134    _ecore_evas_wl_size_step_set,
135    NULL, // object_cursor_set
136    _ecore_evas_wl_layer_set,
137    NULL, // focus set
138    _ecore_evas_wl_iconified_set,
139    NULL, // borderless set
140    NULL, // override set
141    _ecore_evas_wl_maximized_set,
142    _ecore_evas_wl_fullscreen_set,
143    NULL, // func avoid_damage set
144    NULL, // func withdrawn set
145    NULL, // func sticky set
146    _ecore_evas_wl_ignore_events_set,
147    _ecore_evas_wl_alpha_set,
148    _ecore_evas_wl_transparent_set,
149    NULL,
150    NULL,
151    NULL,
152    NULL,
153    NULL,
154    NULL,
155    _ecore_evas_wl_render, 
156    _ecore_evas_wl_screen_geometry_get
157 };
158
159 /* external variables */
160
161 /* external functions */
162 EAPI Ecore_Evas *
163 ecore_evas_wayland_shm_new(const char *disp_name, unsigned int parent, int x, int y, int w, int h, Eina_Bool frame)
164 {
165    Ecore_Wl_Window *p = NULL;
166    Evas_Engine_Info_Wayland_Shm *einfo;
167    Ecore_Evas *ee;
168    int method = 0, count = 0;
169
170    LOGFN(__FILE__, __LINE__, __FUNCTION__);
171
172    if (!(method = evas_render_method_lookup("wayland_shm")))
173      {
174         ERR("Render method lookup failed for Wayland_Shm");
175         return NULL;
176      }
177
178    count = ecore_wl_init(disp_name);
179    if (!count)
180      {
181         ERR("Failed to initialize Ecore_Wayland");
182         return NULL;
183      }
184    else if (count == 1)
185      ecore_wl_display_iterate();
186
187    if (!(ee = calloc(1, sizeof(Ecore_Evas))))
188      {
189         ERR("Failed to allocate Ecore_Evas");
190         ecore_wl_shutdown();
191         return NULL;
192      }
193
194    ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
195
196    _ecore_evas_wl_init();
197
198    ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_wl_engine_func;
199
200    ee->driver = "wayland_shm";
201    if (disp_name) ee->name = strdup(disp_name);
202
203    if (w < 1) w = 1;
204    if (h < 1) h = 1;
205
206    ee->x = x;
207    ee->y = y;
208    ee->w = w;
209    ee->h = h;
210    ee->req.x = ee->x;
211    ee->req.y = ee->y;
212    ee->req.w = ee->w;
213    ee->req.h = ee->h;
214    ee->rotation = 0;
215    ee->prop.max.w = 32767;
216    ee->prop.max.h = 32767;
217    ee->prop.layer = 4;
218    ee->prop.request_pos = 0;
219    ee->prop.sticky = 0;
220    ee->prop.draw_frame = frame;
221
222    ee->evas = evas_new();
223    evas_data_attach_set(ee->evas, ee);
224    evas_output_method_set(ee->evas, method);
225    evas_output_size_set(ee->evas, ee->w, ee->h);
226    evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
227
228    /* FIXME: This needs to be set based on theme & scale */
229    if (ee->prop.draw_frame)
230      evas_output_framespace_set(ee->evas, 4, 18, 8, 22);
231
232    if (parent)
233      p = ecore_wl_window_find(parent);
234
235    /* FIXME: Get if parent is alpha, and set */
236
237    ee->engine.wl.parent = p;
238    ee->engine.wl.win = 
239      ecore_wl_window_new(p, x, y, w, h, ECORE_WL_WINDOW_BUFFER_TYPE_SHM);
240    ee->prop.window = ee->engine.wl.win->id;
241
242    if ((einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas)))
243      {
244         einfo->info.rotation = ee->rotation;
245         einfo->info.debug = EINA_FALSE;
246         if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
247           {
248              ERR("Failed to set Evas Engine Info for '%s'", ee->driver);
249              ecore_evas_free(ee);
250              _ecore_evas_wl_shutdown();
251              ecore_wl_shutdown();
252              return NULL;
253           }
254      }
255    else 
256      {
257         ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
258         ecore_evas_free(ee);
259         _ecore_evas_wl_shutdown();
260         ecore_wl_shutdown();
261         return NULL;
262      }
263
264    ecore_evas_callback_pre_free_set(ee, _ecore_evas_wl_pre_free);
265
266    if (ee->prop.draw_frame) 
267      {
268         ee->engine.wl.frame = _ecore_evas_wl_frame_add(ee->evas);
269         evas_object_is_frame_object_set(ee->engine.wl.frame, EINA_TRUE);
270         evas_object_move(ee->engine.wl.frame, 0, 0);
271      }
272
273    ecore_evas_input_event_register(ee);
274    _ecore_evas_register(ee);
275
276    ecore_event_window_register(ee->prop.window, ee, ee->evas, 
277                                (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process, 
278                                (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process, 
279                                (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process, 
280                                (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
281
282    evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
283
284    return ee;
285 }
286
287 /* local functions */
288 static int 
289 _ecore_evas_wl_init(void)
290 {
291    LOGFN(__FILE__, __LINE__, __FUNCTION__);
292
293    if (++_ecore_evas_wl_init_count != 1)
294      return _ecore_evas_wl_init_count;
295
296    _ecore_evas_wl_event_hdls[0] = 
297      ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_IN, 
298                              _ecore_evas_wl_cb_mouse_in, NULL);
299    _ecore_evas_wl_event_hdls[1] = 
300      ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_OUT, 
301                              _ecore_evas_wl_cb_mouse_out, NULL);
302    _ecore_evas_wl_event_hdls[2] = 
303      ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN, 
304                              _ecore_evas_wl_cb_focus_in, NULL);
305    _ecore_evas_wl_event_hdls[3] = 
306      ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT, 
307                              _ecore_evas_wl_cb_focus_out, NULL);
308    _ecore_evas_wl_event_hdls[4] = 
309      ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_CONFIGURE, 
310                              _ecore_evas_wl_cb_window_configure, NULL);
311
312    ecore_event_evas_init();
313
314    return _ecore_evas_wl_init_count;
315 }
316
317 static int 
318 _ecore_evas_wl_shutdown(void)
319 {
320    unsigned int i = 0;
321
322    LOGFN(__FILE__, __LINE__, __FUNCTION__);
323
324    if (--_ecore_evas_wl_init_count != 0)
325      return _ecore_evas_wl_init_count;
326
327    for (i = 0; i < sizeof(_ecore_evas_wl_event_hdls) / sizeof(Ecore_Event_Handler *); i++)
328      {
329         if (_ecore_evas_wl_event_hdls[i])
330           ecore_event_handler_del(_ecore_evas_wl_event_hdls[i]);
331      }
332
333    ecore_event_evas_shutdown();
334
335    return _ecore_evas_wl_init_count;
336 }
337
338 static void 
339 _ecore_evas_wl_pre_free(Ecore_Evas *ee)
340 {
341    /* Evas_Engine_Info_Wayland_Shm *einfo; */
342
343    LOGFN(__FILE__, __LINE__, __FUNCTION__);
344
345    if (ee->engine.wl.frame) evas_object_del(ee->engine.wl.frame);
346
347    /* FIXME: */
348    /* einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas); */
349    /* if ((einfo) && (einfo->info.dest)) */
350    /*   { */
351    /*      int ret = 0; */
352
353    /*      ret = munmap(einfo->info.dest, ((ee->w * sizeof(int)) * ee->h)); */
354    /*      if (!ret) ERR("Failed to unmap engine destination: %m"); */
355    /*   } */
356 }
357
358 static void 
359 _ecore_evas_wl_free(Ecore_Evas *ee)
360 {
361    LOGFN(__FILE__, __LINE__, __FUNCTION__);
362
363    if (ee->engine.wl.buffer) wl_buffer_destroy(ee->engine.wl.buffer);
364    ee->engine.wl.buffer = NULL;
365
366    if (ee->engine.wl.win) ecore_wl_window_free(ee->engine.wl.win);
367    ee->engine.wl.win = NULL;
368
369    ecore_event_window_unregister(ee->prop.window);
370    ecore_evas_input_event_unregister(ee);
371
372    _ecore_evas_wl_shutdown();
373    ecore_wl_shutdown();
374 }
375
376 static void 
377 _ecore_evas_wl_callback_resize_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
378 {
379    LOGFN(__FILE__, __LINE__, __FUNCTION__);
380
381    if (!ee) return;
382    ee->func.fn_resize = func;
383 }
384
385 static void 
386 _ecore_evas_wl_callback_move_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
387 {
388    LOGFN(__FILE__, __LINE__, __FUNCTION__);
389
390    if (!ee) return;
391    ee->func.fn_move = func;
392 }
393
394 static void 
395 _ecore_evas_wl_callback_delete_request_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
396 {
397    LOGFN(__FILE__, __LINE__, __FUNCTION__);
398
399    if (!ee) return;
400    ee->func.fn_delete_request = func;
401 }
402
403 static void 
404 _ecore_evas_wl_callback_focus_in_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
405 {
406    LOGFN(__FILE__, __LINE__, __FUNCTION__);
407
408    if (!ee) return;
409    ee->func.fn_focus_in = func;
410 }
411
412 static void 
413 _ecore_evas_wl_callback_focus_out_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
414 {
415    LOGFN(__FILE__, __LINE__, __FUNCTION__);
416
417    if (!ee) return;
418    ee->func.fn_focus_out = func;
419 }
420
421 static void 
422 _ecore_evas_wl_callback_mouse_in_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
423 {
424    LOGFN(__FILE__, __LINE__, __FUNCTION__);
425
426    if (!ee) return;
427    ee->func.fn_mouse_in = func;
428 }
429
430 static void 
431 _ecore_evas_wl_callback_mouse_out_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
432 {
433    LOGFN(__FILE__, __LINE__, __FUNCTION__);
434
435    if (!ee) return;
436    ee->func.fn_mouse_out = func;
437 }
438
439 static void 
440 _ecore_evas_wl_move(Ecore_Evas *ee, int x, int y)
441 {
442    LOGFN(__FILE__, __LINE__, __FUNCTION__);
443
444    if (!ee) return;
445    ee->req.x = x;
446    ee->req.y = y;
447    ee->x = x;
448    ee->y = y;
449    if (ee->engine.wl.win) ecore_wl_window_move(ee->engine.wl.win, x, y);
450    if (ee->func.fn_move) ee->func.fn_move(ee);
451 }
452
453 static void 
454 _ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h)
455 {
456    /* Evas_Engine_Info_Wayland_Shm *einfo; */
457
458    if (!ee) return;
459    if (w < 1) w = 1;
460    if (h < 1) h = 1;
461 //   if ((ee->w == w) && (ee->h == h)) return;
462
463    LOGFN(__FILE__, __LINE__, __FUNCTION__);
464
465    if (ee->prop.min.w > w) w = ee->prop.min.w;
466    else if (w > ee->prop.max.w) w = ee->prop.max.w;
467    if (ee->prop.min.h > h) h = ee->prop.min.h;
468    else if (h > ee->prop.max.h) h = ee->prop.max.h;
469
470    ee->req.w = w;
471    ee->req.h = h;
472
473    ee->w = w;
474    ee->h = h;
475
476 //   ecore_wl_window_damage(ee->engine.wl.win, 0, 0, ee->w, ee->h);
477
478    /* einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas); */
479    /* if ((einfo) && (einfo->info.dest)) */
480    /*   { */
481         
482    /*   } */
483
484    /*   { */
485    /*      int ret = 0; */
486
487    /*      ret = munmap(einfo->info.dest, ((ee->w * sizeof(int)) * ee->h)); */
488    /*      if (!ret) ERR("Failed to unmap engine destination: %m"); */
489    /*   } */
490    /* else if (!einfo) */
491    /*   { */
492    /*      ERR("Failed to get Evas Engine Info for '%s'", ee->driver); */
493    /*      return; */
494    /*   } */
495
496    if (ee->engine.wl.buffer) wl_buffer_destroy(ee->engine.wl.buffer);
497    ee->engine.wl.buffer = NULL;
498
499    if (ee->engine.wl.pool)
500      _ecore_evas_wl_buffer_new(ee, ee->engine.wl.pool);
501
502    /* change evas output & viewport sizes */
503    evas_output_size_set(ee->evas, ee->w, ee->h);
504    evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
505    evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
506    if (ee->engine.wl.frame)
507      evas_object_resize(ee->engine.wl.frame, ee->w, ee->h);
508
509    /* set new engine destination */
510    /* evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); */
511
512    /* damage buffer */
513 //   wl_buffer_damage(ee->engine.wl.buffer, 0, 0, ee->w, ee->h);
514
515    if (ee->engine.wl.win)
516      {
517         ecore_wl_window_buffer_attach(ee->engine.wl.win, ee->engine.wl.buffer, 
518                                       0, 0);
519         /* ecore_wl_window_damage(ee->engine.wl.win, 0, 0, ee->w, ee->h); */
520         /* ecore_wl_flush(); */
521         ecore_wl_window_update_size(ee->engine.wl.win, ee->w, ee->h);
522      }
523
524    if (ee->func.fn_resize) ee->func.fn_resize(ee);
525 }
526
527 static void 
528 _ecore_evas_wl_show(Ecore_Evas *ee)
529 {
530    Evas_Engine_Info_Wayland_Shm *einfo;
531    struct wl_shm_pool *pool = NULL;
532    int stride = 0;
533    size_t len = 0;
534    void *data;
535
536    LOGFN(__FILE__, __LINE__, __FUNCTION__);
537
538    if ((!ee) || (ee->visible)) return;
539
540    if (ee->engine.wl.win)
541      ecore_wl_window_show(ee->engine.wl.win);
542
543    stride = ee->w * sizeof(int);
544    len = stride * ee->h;
545
546    if ((ee->engine.wl.pool) && (len < ee->engine.wl.pool_size))
547      {
548         pool = ee->engine.wl.pool;
549         data = ee->engine.wl.pool_data;
550      }
551    else
552      {
553         int w = 0, size = 0;
554
555         ecore_wl_screen_size_get(&w, NULL);
556
557         /* set a default width */
558         if (w == 0) w = 1024;
559
560         size = (6 * w * w);
561         pool = 
562           _ecore_evas_wl_shm_pool_create(size, &data);
563         ee->engine.wl.pool_size = size;
564      }
565
566    if (data != ee->engine.wl.pool_data)
567      {
568         if (ee->engine.wl.pool)
569           wl_shm_pool_destroy(ee->engine.wl.pool);
570
571         ee->engine.wl.pool = pool;
572         ee->engine.wl.pool_data = data;
573      }
574
575    _ecore_evas_wl_buffer_new(ee, pool);
576
577    einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
578    if (!einfo)
579      {
580         ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
581         return;
582      }
583
584    einfo->info.dest = data;
585    evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
586
587    /* ecore_wl_flush(); */
588
589    if (ee->engine.wl.win)
590      {
591         /* ecore_wl_window_show(ee->engine.wl.win); */
592         ecore_wl_window_buffer_attach(ee->engine.wl.win, 
593                                       ee->engine.wl.buffer, 0, 0);
594      }
595
596    if (ee->engine.wl.frame)
597      {
598         evas_object_show(ee->engine.wl.frame);
599         evas_object_resize(ee->engine.wl.frame, ee->w, ee->h);
600      }
601
602    ee->visible = 1;
603    if (ee->func.fn_show) ee->func.fn_show(ee);
604 }
605
606 static void 
607 _ecore_evas_wl_hide(Ecore_Evas *ee)
608 {
609    Evas_Engine_Info_Wayland_Shm *einfo;
610
611    LOGFN(__FILE__, __LINE__, __FUNCTION__);
612
613    if ((!ee) || (!ee->visible)) return;
614
615    if (ee->engine.wl.buffer) wl_buffer_destroy(ee->engine.wl.buffer);
616    ee->engine.wl.buffer = NULL;
617
618    munmap(ee->engine.wl.pool_data, ee->engine.wl.pool_size);
619
620    einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
621    if ((einfo) && (einfo->info.dest))
622      {
623         einfo->info.dest = NULL;
624         evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
625      }
626
627    ecore_wl_window_hide(ee->engine.wl.win);
628
629    ee->visible = 0;
630    ee->should_be_visible = 0;
631
632    if (ee->func.fn_hide) ee->func.fn_hide(ee);
633 }
634
635 static void 
636 _ecore_evas_wl_raise(Ecore_Evas *ee)
637 {
638    LOGFN(__FILE__, __LINE__, __FUNCTION__);
639
640    if ((!ee) || (!ee->visible)) return;
641    ecore_wl_window_raise(ee->engine.wl.win);
642 }
643
644 static void 
645 _ecore_evas_wl_title_set(Ecore_Evas *ee, const char *title)
646 {
647    LOGFN(__FILE__, __LINE__, __FUNCTION__);
648
649    if (!ee) return;
650    if (ee->prop.title) free(ee->prop.title);
651    ee->prop.title = NULL;
652    if (title) ee->prop.title = strdup(title);
653    if ((ee->prop.draw_frame) && (ee->engine.wl.frame)) 
654      {
655         EE_Wl_Smart_Data *sd;
656
657         if (!(sd = evas_object_smart_data_get(ee->engine.wl.frame))) return;
658         evas_object_text_text_set(sd->text, ee->prop.title);
659      }
660 }
661
662 static void 
663 _ecore_evas_wl_name_class_set(Ecore_Evas *ee, const char *n, const char *c) 
664 {
665    LOGFN(__FILE__, __LINE__, __FUNCTION__);
666
667    if (!ee) return;
668    if (ee->prop.name) free(ee->prop.name);
669    if (ee->prop.clas) free(ee->prop.clas);
670    ee->prop.name = NULL;
671    ee->prop.clas = NULL;
672    if (n) ee->prop.name = strdup(n);
673    if (c) ee->prop.clas = strdup(c);
674    /* FIXME: Forward these changes to Wayland somehow */
675 }
676
677 static void 
678 _ecore_evas_wl_size_min_set(Ecore_Evas *ee, int w, int h) 
679 {
680    LOGFN(__FILE__, __LINE__, __FUNCTION__);
681
682    if (!ee) return;
683    if (w < 0) w = 0;
684    if (h < 0) h = 0;
685    if ((ee->prop.min.w == w) && (ee->prop.min.h == h)) return;
686    ee->prop.min.w = w;
687    ee->prop.min.h = h;
688 }
689
690 static void 
691 _ecore_evas_wl_size_max_set(Ecore_Evas *ee, int w, int h) 
692 {
693    LOGFN(__FILE__, __LINE__, __FUNCTION__);
694
695    if (!ee) return;
696    if (w < 0) w = 0;
697    if (h < 0) h = 0;
698    if ((ee->prop.max.w == w) && (ee->prop.max.h == h)) return;
699    ee->prop.max.w = w;
700    ee->prop.max.h = h;
701 }
702
703 static void 
704 _ecore_evas_wl_size_base_set(Ecore_Evas *ee, int w, int h) 
705 {
706    LOGFN(__FILE__, __LINE__, __FUNCTION__);
707
708    if (!ee) return;
709    if (w < 0) w = 0;
710    if (h < 0) h = 0;
711    if ((ee->prop.base.w == w) && (ee->prop.base.h == h)) return;
712    ee->prop.base.w = w;
713    ee->prop.base.h = h;
714 }
715
716 static void 
717 _ecore_evas_wl_size_step_set(Ecore_Evas *ee, int w, int h) 
718 {
719    LOGFN(__FILE__, __LINE__, __FUNCTION__);
720
721    if (!ee) return;
722    if (w < 0) w = 0;
723    if (h < 0) h = 0;
724    if ((ee->prop.step.w == w) && (ee->prop.step.h == h)) return;
725    ee->prop.step.w = w;
726    ee->prop.step.h = h;
727 }
728
729 static void 
730 _ecore_evas_wl_layer_set(Ecore_Evas *ee, int layer)
731 {
732    LOGFN(__FILE__, __LINE__, __FUNCTION__);
733
734    if (!ee) return;
735    if (ee->prop.layer == layer) return;
736    if (layer < 1) layer = 1;
737    else if (layer > 255) layer = 255;
738    ee->prop.layer = layer;
739 }
740
741 static void 
742 _ecore_evas_wl_iconified_set(Ecore_Evas *ee, int iconify)
743 {
744    LOGFN(__FILE__, __LINE__, __FUNCTION__);
745
746    if (!ee) return;
747    if (ee->prop.iconified == iconify) return;
748    ee->prop.iconified = iconify;
749    /* FIXME: Implement this in Wayland someshow */
750 }
751
752 static void 
753 _ecore_evas_wl_maximized_set(Ecore_Evas *ee, int max)
754 {
755    LOGFN(__FILE__, __LINE__, __FUNCTION__);
756
757    if (!ee) return;
758    if (ee->prop.maximized == max) return;
759    ee->prop.maximized = max;
760    ecore_wl_window_maximized_set(ee->engine.wl.win, max);
761 }
762
763 static void 
764 _ecore_evas_wl_fullscreen_set(Ecore_Evas *ee, int full)
765 {
766    LOGFN(__FILE__, __LINE__, __FUNCTION__);
767
768    if ((!ee) || (!ee->visible)) return;
769    if (ee->prop.fullscreen == full) return;
770    ee->prop.fullscreen = full;
771    ecore_wl_window_fullscreen_set(ee->engine.wl.win, full);
772 }
773
774 static void 
775 _ecore_evas_wl_ignore_events_set(Ecore_Evas *ee, int ignore)
776 {
777    LOGFN(__FILE__, __LINE__, __FUNCTION__);
778
779    if (!ee) return;
780    ee->ignore_events = ignore;
781    /* NB: Hmmm, may need to pass this to ecore_wl_window in the future */
782 }
783
784 static void 
785 _ecore_evas_wl_alpha_set(Ecore_Evas *ee, int alpha)
786 {
787    Evas_Engine_Info_Wayland_Shm *einfo;
788
789    LOGFN(__FILE__, __LINE__, __FUNCTION__);
790
791    if (!ee) return;
792    if ((ee->alpha == alpha)) return;
793    ee->alpha = alpha;
794    if (ee->engine.wl.win)
795      ecore_wl_window_transparent_set(ee->engine.wl.win, alpha);
796    if ((einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas)))
797      {
798         einfo->info.destination_alpha = alpha;
799         if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
800           ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
801         evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
802      }
803 }
804
805 static void 
806 _ecore_evas_wl_transparent_set(Ecore_Evas *ee, int transparent)
807 {
808    Evas_Engine_Info_Wayland_Shm *einfo;
809
810    LOGFN(__FILE__, __LINE__, __FUNCTION__);
811
812    if (!ee) return;
813    if ((ee->transparent == transparent)) return;
814    ee->transparent = transparent;
815    if (ee->engine.wl.win)
816      ecore_wl_window_transparent_set(ee->engine.wl.win, transparent);
817    if ((einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas)))
818      {
819         einfo->info.destination_alpha = transparent;
820         if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
821           ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
822         evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
823      }
824 }
825
826 static int 
827 _ecore_evas_wl_render(Ecore_Evas *ee)
828 {
829    int rend = 0;
830
831    if (!ee) return 0;
832    if (!ee->visible)
833      evas_norender(ee->evas);
834    else
835      {
836         Eina_List *ll = NULL, *updates = NULL;
837         Ecore_Evas *ee2 = NULL;
838
839         if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
840
841         EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2) 
842           {
843              if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
844              if (ee2->engine.func->fn_render)
845                rend |= ee2->engine.func->fn_render(ee2);
846              if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
847           }
848
849         if ((updates = evas_render_updates(ee->evas))) 
850           {
851              Eina_List *l = NULL;
852              Eina_Rectangle *r;
853
854              LOGFN(__FILE__, __LINE__, __FUNCTION__);
855
856              EINA_LIST_FOREACH(updates, l, r) 
857                ecore_wl_window_damage(ee->engine.wl.win, 
858                                       r->x, r->y, r->w, r->h);
859
860              ecore_wl_flush();
861
862              evas_render_updates_free(updates);
863              _ecore_evas_idle_timeout_update(ee);
864              rend = 1;
865           }
866
867         if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
868      }
869    return rend;
870 }
871
872 static void 
873 _ecore_evas_wl_screen_geometry_get(const Ecore_Evas *ee __UNUSED__, int *x, int *y, int *w, int *h)
874 {
875    LOGFN(__FILE__, __LINE__, __FUNCTION__);
876
877    if (x) *x = 0;
878    if (y) *y = 0;
879    ecore_wl_screen_size_get(w, h);
880 }
881
882 static struct wl_shm_pool *
883 _ecore_evas_wl_shm_pool_create(int size, void **data)
884 {
885    struct wl_shm *shm;
886    struct wl_shm_pool *pool;
887    char tmp[PATH_MAX];
888    int fd;
889
890    LOGFN(__FILE__, __LINE__, __FUNCTION__);
891
892    if (!(shm = ecore_wl_shm_get())) return NULL;
893
894    strcpy(tmp, "/tmp/ecore-evas-wayland_shm-XXXXXX");
895    if ((fd = mkstemp(tmp)) < 0) 
896      {
897         ERR("Could not create temporary file.");
898         return NULL;
899      }
900
901    if (ftruncate(fd, size) < 0) 
902      {
903         ERR("Could not truncate temporary file.");
904         close(fd);
905         return NULL;
906      }
907
908    *data = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0);
909    unlink(tmp);
910
911    if (*data == MAP_FAILED) 
912      {
913         ERR("mmap of temporary file failed.");
914         close(fd);
915         return NULL;
916      }
917
918    pool = wl_shm_create_pool(shm, fd, size);
919
920    close(fd);
921
922    return pool;
923 }
924
925 static void 
926 _ecore_evas_wl_buffer_new(Ecore_Evas *ee, struct wl_shm_pool *pool)
927 {
928    unsigned int format;
929    int stride = 0;
930
931    if ((ee->alpha) || (ee->transparent))
932      format = WL_SHM_FORMAT_ARGB8888;
933    else
934      format = WL_SHM_FORMAT_XRGB8888;
935
936    stride = (ee->w * sizeof(int));
937
938    ee->engine.wl.buffer = 
939      wl_shm_pool_create_buffer(pool, 0, ee->w, ee->h, stride, format);
940 }
941
942 void 
943 _ecore_evas_wayland_shm_resize(Ecore_Evas *ee, int location)
944 {
945    LOGFN(__FILE__, __LINE__, __FUNCTION__);
946
947    if (!ee) return;
948    if (ee->engine.wl.win) 
949      ecore_wl_window_resize(ee->engine.wl.win, ee->w, ee->h, location);
950 }
951
952 static Eina_Bool 
953 _ecore_evas_wl_cb_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event)
954 {
955    Ecore_Evas *ee;
956    Ecore_Wl_Event_Mouse_In *ev;
957
958    LOGFN(__FILE__, __LINE__, __FUNCTION__);
959
960    ev = event;
961    ee = ecore_event_window_match(ev->window);
962    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
963    if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
964    if (ee->func.fn_mouse_in) ee->func.fn_mouse_in(ee);
965    ecore_event_evas_modifier_lock_update(ee->evas, ev->modifiers);
966    evas_event_feed_mouse_in(ee->evas, ev->timestamp, NULL);
967    _ecore_evas_mouse_move_process(ee, ev->x, ev->y, ev->timestamp);
968    return ECORE_CALLBACK_PASS_ON;
969 }
970
971 static Eina_Bool 
972 _ecore_evas_wl_cb_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event)
973 {
974    Ecore_Evas *ee;
975    Ecore_Wl_Event_Mouse_Out *ev;
976
977    LOGFN(__FILE__, __LINE__, __FUNCTION__);
978
979    ev = event;
980    ee = ecore_event_window_match(ev->window);
981    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
982    if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
983    ecore_event_evas_modifier_lock_update(ee->evas, ev->modifiers);
984    _ecore_evas_mouse_move_process(ee, ev->x, ev->y, ev->timestamp);
985    evas_event_feed_mouse_out(ee->evas, ev->timestamp, NULL);
986    if (ee->func.fn_mouse_out) ee->func.fn_mouse_out(ee);
987    if (ee->prop.cursor.object) evas_object_hide(ee->prop.cursor.object);
988    return ECORE_CALLBACK_PASS_ON;
989 }
990
991 static Eina_Bool 
992 _ecore_evas_wl_cb_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event)
993 {
994    Ecore_Evas *ee;
995    Ecore_Wl_Event_Focus_In *ev;
996
997    LOGFN(__FILE__, __LINE__, __FUNCTION__);
998
999    ev = event;
1000    ee = ecore_event_window_match(ev->win);
1001    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
1002    if (ev->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1003    ee->prop.focused = 1;
1004    evas_focus_in(ee->evas);
1005    if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
1006    return ECORE_CALLBACK_PASS_ON;
1007 }
1008
1009 static Eina_Bool 
1010 _ecore_evas_wl_cb_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event)
1011 {
1012    Ecore_Evas *ee;
1013    Ecore_Wl_Event_Focus_In *ev;
1014
1015    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1016
1017    ev = event;
1018    ee = ecore_event_window_match(ev->win);
1019    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
1020    if (ev->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1021    evas_focus_out(ee->evas);
1022    ee->prop.focused = 0;
1023    if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
1024    return ECORE_CALLBACK_PASS_ON;
1025 }
1026
1027 static Eina_Bool 
1028 _ecore_evas_wl_cb_window_configure(void *data __UNUSED__, int type __UNUSED__, void *event)
1029 {
1030    Ecore_Evas *ee;
1031    Ecore_Wl_Event_Window_Configure *ev;
1032
1033    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1034
1035    ev = event;
1036    ee = ecore_event_window_match(ev->win);
1037    if (!ee) return ECORE_CALLBACK_PASS_ON;
1038    if (ev->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
1039    if ((ee->x != ev->x) || (ee->y != ev->y))
1040      {
1041         ee->x = ev->x;
1042         ee->y = ev->y;
1043         ee->req.x = ee->x;
1044         ee->req.y = ee->y;
1045         if (ee->func.fn_move) ee->func.fn_move(ee);
1046      }
1047    if ((ee->req.w != ev->w) || (ee->req.h != ev->h))
1048      {
1049         /* ee->w = ev->w; */
1050         /* ee->h = ev->h; */
1051         ee->req.w = ev->w;
1052         ee->req.h = ev->h;
1053         if (ee->func.fn_resize) ee->func.fn_resize(ee);
1054      }
1055
1056    return ECORE_CALLBACK_PASS_ON;
1057 }
1058
1059 static void 
1060 _ecore_evas_wl_smart_init(void) 
1061 {
1062    if (_ecore_evas_wl_smart) return;
1063      {
1064         static const Evas_Smart_Class sc = 
1065           {
1066              "ecore_evas_wl_frame", EVAS_SMART_CLASS_VERSION, 
1067              _ecore_evas_wl_smart_add, 
1068              _ecore_evas_wl_smart_del, 
1069              NULL, 
1070              _ecore_evas_wl_smart_resize, 
1071              _ecore_evas_wl_smart_show, 
1072              _ecore_evas_wl_smart_hide, 
1073              NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
1074           };
1075         _ecore_evas_wl_smart = evas_smart_class_new(&sc);
1076      }
1077 }
1078
1079 static void 
1080 _ecore_evas_wl_smart_add(Evas_Object *obj) 
1081 {
1082    EE_Wl_Smart_Data *sd;
1083    Evas *evas;
1084
1085    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1086
1087    if (!(sd = calloc(1, sizeof(EE_Wl_Smart_Data)))) return;
1088
1089    evas = evas_object_evas_get(obj);
1090
1091    sd->x = 0;
1092    sd->y = 0;
1093    sd->w = 1;
1094    sd->h = 1;
1095
1096    sd->frame = evas_object_rectangle_add(evas);
1097    evas_object_is_frame_object_set(sd->frame, EINA_TRUE);
1098    evas_object_color_set(sd->frame, 249, 249, 249, 255);
1099    evas_object_smart_member_add(sd->frame, obj);
1100
1101    sd->text = evas_object_text_add(evas);
1102    evas_object_color_set(sd->text, 0, 0, 0, 255);
1103    evas_object_text_style_set(sd->text, EVAS_TEXT_STYLE_PLAIN);
1104    evas_object_text_font_set(sd->text, "Sans", 10);
1105    evas_object_text_text_set(sd->text, "Smart Test");
1106
1107    evas_object_smart_data_set(obj, sd);
1108 }
1109
1110 static void 
1111 _ecore_evas_wl_smart_del(Evas_Object *obj) 
1112 {
1113    EE_Wl_Smart_Data *sd;
1114
1115    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1116
1117    if (!(sd = evas_object_smart_data_get(obj))) return;
1118    evas_object_del(sd->text);
1119    evas_object_del(sd->frame);
1120    free(sd);
1121 }
1122
1123 static void 
1124 _ecore_evas_wl_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h) 
1125 {
1126    EE_Wl_Smart_Data *sd;
1127
1128    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1129
1130    if (!(sd = evas_object_smart_data_get(obj))) return;
1131    if ((sd->w == w) && (sd->h == h)) return;
1132    sd->w = w;
1133    sd->h = h;
1134    evas_object_resize(sd->frame, w, h);
1135 }
1136
1137 static void 
1138 _ecore_evas_wl_smart_show(Evas_Object *obj) 
1139 {
1140    EE_Wl_Smart_Data *sd;
1141
1142    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1143
1144    if (!(sd = evas_object_smart_data_get(obj))) return;
1145    evas_object_show(sd->frame);
1146    evas_object_show(sd->text);
1147 }
1148
1149 static void 
1150 _ecore_evas_wl_smart_hide(Evas_Object *obj) 
1151 {
1152    EE_Wl_Smart_Data *sd;
1153
1154    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1155
1156    if (!(sd = evas_object_smart_data_get(obj))) return;
1157    evas_object_hide(sd->text);
1158    evas_object_hide(sd->frame);
1159 }
1160
1161 static Evas_Object *
1162 _ecore_evas_wl_frame_add(Evas *evas) 
1163 {
1164    LOGFN(__FILE__, __LINE__, __FUNCTION__);
1165
1166    _ecore_evas_wl_smart_init();
1167    return evas_object_smart_add(evas, _ecore_evas_wl_smart);
1168 }
1169
1170 #else
1171 EAPI Ecore_Evas *
1172 ecore_evas_wayland_shm_new(const char *disp_name __UNUSED__, unsigned int parent __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__, Eina_Bool frame __UNUSED__)
1173 {
1174    return NULL;
1175 }
1176 #endif