9 # define LOGFN(fl, ln, fn) \
10 printf("-ECORE_EVAS-WL: %25s: %5i - %s\n", fl, ln, fn);
12 # define LOGFN(fl, ln, fn)
15 #ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
19 # include <sys/types.h>
20 # include <sys/mman.h>
25 #include "Ecore_Evas.h"
27 #ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
28 # include "ecore_evas_private.h"
29 # include <Evas_Engine_Wayland_Shm.h>
30 # include <Ecore_Wayland.h>
32 /* local function prototypes */
33 static void _ecore_evas_wl_free(Ecore_Evas *ee);
34 static void _ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h);
35 static void _ecore_evas_wl_move_resize(Ecore_Evas *ee, int x, int y, int w, int h);
36 static void _ecore_evas_wl_show(Ecore_Evas *ee);
37 static void _ecore_evas_wl_hide(Ecore_Evas *ee);
38 static void _ecore_evas_wl_alpha_set(Ecore_Evas *ee, int alpha);
39 static void _ecore_evas_wl_transparent_set(Ecore_Evas *ee, int transparent);
40 static int _ecore_evas_wl_render(Ecore_Evas *ee);
43 static void _ecore_evas_wl_shm_pool_free(Ecore_Evas *ee);
44 static void _ecore_evas_wl_shm_pool_create(Ecore_Evas *ee, size_t size);
45 static void _ecore_evas_wl_buffer_free(Ecore_Evas *ee);
46 static void _ecore_evas_wl_buffer_new(Ecore_Evas *ee, int w, int h);
49 static void _ecore_evas_wl_frame_complete(void *data, struct wl_callback *callback, uint32_t time);
50 static const struct wl_callback_listener frame_listener =
52 _ecore_evas_wl_frame_complete,
55 static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
58 _ecore_evas_wl_common_callback_resize_set,
59 _ecore_evas_wl_common_callback_move_set,
62 _ecore_evas_wl_common_callback_delete_request_set,
64 _ecore_evas_wl_common_callback_focus_in_set,
65 _ecore_evas_wl_common_callback_focus_out_set,
66 _ecore_evas_wl_common_callback_mouse_in_set,
67 _ecore_evas_wl_common_callback_mouse_out_set,
70 NULL, // pre_render_set
71 NULL, // post_render_set
72 _ecore_evas_wl_common_move,
74 _ecore_evas_wl_resize,
75 _ecore_evas_wl_move_resize,
80 _ecore_evas_wl_common_raise,
83 _ecore_evas_wl_common_title_set,
84 _ecore_evas_wl_common_name_class_set,
85 _ecore_evas_wl_common_size_min_set,
86 _ecore_evas_wl_common_size_max_set,
87 _ecore_evas_wl_common_size_base_set,
88 _ecore_evas_wl_common_size_step_set,
89 NULL, // object_cursor_set
90 _ecore_evas_wl_common_layer_set,
92 _ecore_evas_wl_common_iconified_set,
93 NULL, // borderless set
95 _ecore_evas_wl_common_maximized_set,
96 _ecore_evas_wl_common_fullscreen_set,
97 NULL, // func avoid_damage set
98 NULL, // func withdrawn set
99 NULL, // func sticky set
100 _ecore_evas_wl_common_ignore_events_set,
101 _ecore_evas_wl_alpha_set,
102 _ecore_evas_wl_transparent_set,
103 NULL, // func profiles set
104 NULL, // window group set
108 NULL, // demand attention set
109 NULL, // focus skip set
110 _ecore_evas_wl_render,
111 _ecore_evas_wl_common_screen_geometry_get,
112 _ecore_evas_wl_common_screen_dpi_get
115 /* external variables */
117 /* external functions */
119 ecore_evas_wayland_shm_new(const char *disp_name, unsigned int parent, int x, int y, int w, int h, Eina_Bool frame)
121 Ecore_Wl_Window *p = NULL;
122 Evas_Engine_Info_Wayland_Shm *einfo;
124 int method = 0, count = 0;
126 LOGFN(__FILE__, __LINE__, __FUNCTION__);
128 if (!(method = evas_render_method_lookup("wayland_shm")))
130 ERR("Render method lookup failed for Wayland_Shm");
134 count = ecore_wl_init(disp_name);
137 ERR("Failed to initialize Ecore_Wayland");
141 ecore_wl_display_iterate();
143 if (!(ee = calloc(1, sizeof(Ecore_Evas))))
145 ERR("Failed to allocate Ecore_Evas");
149 ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
151 _ecore_evas_wl_common_init();
153 ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_wl_engine_func;
155 ee->driver = "wayland_shm";
156 if (disp_name) ee->name = strdup(disp_name);
170 ee->prop.max.w = 32767;
171 ee->prop.max.h = 32767;
173 ee->prop.request_pos = 0;
175 ee->prop.draw_frame = frame;
176 ee->alpha = EINA_FALSE;
178 ee->evas = evas_new();
179 evas_data_attach_set(ee->evas, ee);
180 evas_output_method_set(ee->evas, method);
181 evas_output_size_set(ee->evas, ee->w, ee->h);
182 evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
184 /* FIXME: This needs to be set based on theme & scale */
185 if (ee->prop.draw_frame)
186 evas_output_framespace_set(ee->evas, 4, 18, 8, 22);
189 p = ecore_wl_window_find(parent);
191 /* FIXME: Get if parent is alpha, and set */
193 ee->engine.wl.parent = p;
195 ecore_wl_window_new(p, x, y, w, h, ECORE_WL_WINDOW_BUFFER_TYPE_SHM);
196 ee->prop.window = ee->engine.wl.win->id;
198 if ((einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas)))
200 einfo->info.destination_alpha = ee->alpha;
201 einfo->info.rotation = ee->rotation;
202 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
204 ERR("Failed to set Evas Engine Info for '%s'", ee->driver);
210 ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
214 ecore_evas_callback_pre_free_set(ee, _ecore_evas_wl_common_pre_free);
216 if (ee->prop.draw_frame)
218 ee->engine.wl.frame = _ecore_evas_wl_common_frame_add(ee->evas);
219 evas_object_is_frame_object_set(ee->engine.wl.frame, EINA_TRUE);
220 evas_object_move(ee->engine.wl.frame, 0, 0);
223 _ecore_evas_register(ee);
224 ecore_evas_input_event_register(ee);
226 ecore_event_window_register(ee->prop.window, ee, ee->evas,
227 (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
228 (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
229 (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
230 (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
236 _ecore_evas_wl_common_shutdown();
244 _ecore_evas_wl_free(Ecore_Evas *ee)
246 _ecore_evas_wl_buffer_free(ee);
247 _ecore_evas_wl_shm_pool_free(ee);
248 _ecore_evas_wl_common_free(ee);
252 _ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h)
254 Evas_Engine_Info_Wayland_Shm *einfo;
257 LOGFN(__FILE__, __LINE__, __FUNCTION__);
266 if (!ee->prop.fullscreen)
270 if (ee->prop.min.w > w) w = ee->prop.min.w;
271 else if (w > ee->prop.max.w) w = ee->prop.max.w;
272 if (ee->prop.min.h > h) h = ee->prop.min.h;
273 else if (h > ee->prop.max.h) h = ee->prop.max.h;
275 evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh);
280 if ((ee->w != w) || (ee->h != h))
285 if ((ee->rotation == 90) || (ee->rotation == 270))
287 evas_output_size_set(ee->evas, h, w);
288 evas_output_viewport_set(ee->evas, 0, 0, h, w);
292 evas_output_size_set(ee->evas, w, h);
293 evas_output_viewport_set(ee->evas, 0, 0, w, h);
296 if (ee->prop.avoid_damage)
300 pdam = ecore_evas_avoid_damage_get(ee);
301 ecore_evas_avoid_damage_set(ee, 0);
302 ecore_evas_avoid_damage_set(ee, pdam);
305 if (ee->engine.wl.frame)
306 evas_object_resize(ee->engine.wl.frame, w, h);
308 _ecore_evas_wl_buffer_new(ee, w, h);
310 einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
313 ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
317 einfo->info.dest = ee->engine.wl.pool_data;
318 evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
320 if (ee->engine.wl.win)
322 ecore_wl_window_update_size(ee->engine.wl.win, w, h);
323 ecore_wl_window_buffer_attach(ee->engine.wl.win,
324 ee->engine.wl.buffer, 0, 0);
327 if (ee->func.fn_resize) ee->func.fn_resize(ee);
332 _ecore_evas_wl_move_resize(Ecore_Evas *ee, int x, int y, int w, int h)
334 LOGFN(__FILE__, __LINE__, __FUNCTION__);
337 if ((ee->x != x) || (ee->y != y))
338 _ecore_evas_wl_common_move(ee, x, y);
339 if ((ee->w != w) || (ee->h != h))
340 _ecore_evas_wl_resize(ee, w, h);
344 _ecore_evas_wl_show(Ecore_Evas *ee)
346 Evas_Engine_Info_Wayland_Shm *einfo;
348 LOGFN(__FILE__, __LINE__, __FUNCTION__);
350 if ((!ee) || (ee->visible)) return;
352 _ecore_evas_wl_buffer_new(ee, ee->w, ee->h);
354 einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
357 ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
361 einfo->info.dest = ee->engine.wl.pool_data;
362 evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
364 if (ee->engine.wl.win)
366 ecore_wl_window_show(ee->engine.wl.win);
367 ecore_wl_window_update_size(ee->engine.wl.win, ee->w, ee->h);
368 ecore_wl_window_buffer_attach(ee->engine.wl.win,
369 ee->engine.wl.buffer, 0, 0);
371 if ((ee->prop.clas) && (ee->engine.wl.win->shell_surface))
372 wl_shell_surface_set_class(ee->engine.wl.win->shell_surface,
374 if ((ee->prop.title) && (ee->engine.wl.win->shell_surface))
375 wl_shell_surface_set_title(ee->engine.wl.win->shell_surface,
379 if (ee->engine.wl.frame)
381 evas_object_show(ee->engine.wl.frame);
382 evas_object_resize(ee->engine.wl.frame, ee->w, ee->h);
386 if (ee->func.fn_show) ee->func.fn_show(ee);
390 _ecore_evas_wl_hide(Ecore_Evas *ee)
392 Evas_Engine_Info_Wayland_Shm *einfo;
394 LOGFN(__FILE__, __LINE__, __FUNCTION__);
396 if ((!ee) || (!ee->visible)) return;
398 _ecore_evas_wl_buffer_free(ee);
400 munmap(ee->engine.wl.pool_data, ee->engine.wl.pool_size);
402 einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
403 if ((einfo) && (einfo->info.dest))
405 einfo->info.dest = NULL;
406 evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
409 if (ee->engine.wl.win)
410 ecore_wl_window_hide(ee->engine.wl.win);
413 ee->should_be_visible = 0;
415 if (ee->func.fn_hide) ee->func.fn_hide(ee);
419 _ecore_evas_wl_alpha_set(Ecore_Evas *ee, int alpha)
421 Evas_Engine_Info_Wayland_Shm *einfo;
422 Ecore_Wl_Window *win = NULL;
424 LOGFN(__FILE__, __LINE__, __FUNCTION__);
427 if ((ee->alpha == alpha)) return;
430 /* FIXME: NB: We should really add a ecore_wl_window_alpha_set function
431 * but we are in API freeze, so just hack it in for now and fix when
433 if ((win = ee->engine.wl.win))
436 /* if (ee->engine.wl.win) */
437 /* ecore_wl_window_transparent_set(ee->engine.wl.win, alpha); */
439 _ecore_evas_wl_buffer_new(ee, ee->w, ee->h);
441 if ((einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas)))
443 einfo->info.destination_alpha = alpha;
444 einfo->info.dest = ee->engine.wl.pool_data;
445 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
446 ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
447 evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
452 ecore_wl_window_update_size(win, ee->w, ee->h);
453 ecore_wl_window_buffer_attach(win, ee->engine.wl.buffer, 0, 0);
458 _ecore_evas_wl_transparent_set(Ecore_Evas *ee, int transparent)
460 Evas_Engine_Info_Wayland_Shm *einfo;
462 LOGFN(__FILE__, __LINE__, __FUNCTION__);
465 if ((ee->transparent == transparent)) return;
466 ee->transparent = transparent;
468 if (ee->engine.wl.win)
469 ecore_wl_window_transparent_set(ee->engine.wl.win, transparent);
471 _ecore_evas_wl_buffer_new(ee, ee->w, ee->h);
473 if ((einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas)))
475 einfo->info.destination_alpha = transparent;
476 einfo->info.dest = ee->engine.wl.pool_data;
477 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
478 ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
479 evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
482 if (ee->engine.wl.win)
484 ecore_wl_window_update_size(ee->engine.wl.win, ee->w, ee->h);
485 ecore_wl_window_buffer_attach(ee->engine.wl.win,
486 ee->engine.wl.buffer, 0, 0);
491 _ecore_evas_wl_frame_complete(void *data, struct wl_callback *callback, uint32_t time __UNUSED__)
493 Ecore_Evas *ee = data;
494 Ecore_Wl_Window *win = NULL;
497 if (!(win = ee->engine.wl.win)) return;
499 win->frame_callback = NULL;
500 win->frame_pending = EINA_FALSE;
501 wl_callback_destroy(callback);
505 win->frame_callback = wl_surface_frame(win->surface);
506 wl_callback_add_listener(win->frame_callback, &frame_listener, ee);
511 _ecore_evas_wl_render(Ecore_Evas *ee)
514 Ecore_Wl_Window *win = NULL;
519 evas_norender(ee->evas);
523 if (!(win = ee->engine.wl.win)) return 0;
525 rend = _ecore_evas_wl_common_pre_render(ee);
526 if (!(win->frame_pending))
528 /* FIXME - ideally have an evas_changed_get to return the value
529 * of evas->changed to avoid creating this callback and
530 * destroying it again
533 if (!win->frame_callback)
535 win->frame_callback = wl_surface_frame(win->surface);
536 wl_callback_add_listener(win->frame_callback, &frame_listener, ee);
539 rend |= _ecore_evas_wl_common_render_updates(ee);
541 win->frame_pending = EINA_TRUE;
543 _ecore_evas_wl_common_post_render(ee);
548 _ecore_evas_wl_shm_pool_free(Ecore_Evas *ee)
550 if (!ee->engine.wl.pool) return;
552 wl_shm_pool_destroy(ee->engine.wl.pool);
553 ee->engine.wl.pool = NULL;
554 ee->engine.wl.pool_size = 0;
555 ee->engine.wl.pool_data = NULL;
559 _ecore_evas_wl_shm_pool_create(Ecore_Evas *ee, size_t size)
566 LOGFN(__FILE__, __LINE__, __FUNCTION__);
568 if (size <= ee->engine.wl.pool_size)
572 _ecore_evas_wl_shm_pool_free(ee);
574 if (!(shm = ecore_wl_shm_get()))
576 ERR("ecore_wl_shm_get returned NULL");
580 strcpy(tmp, "/tmp/ecore-evas-wayland_shm-XXXXXX");
581 if ((fd = mkstemp(tmp)) < 0)
583 ERR("Could not create temporary file.");
587 if (ftruncate(fd, size) < 0)
589 ERR("Could not truncate temporary file.");
593 data = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0);
596 if (data == MAP_FAILED)
598 ERR("mmap of temporary file failed.");
602 ee->engine.wl.pool_size = size;
603 ee->engine.wl.pool_data = data;
604 ee->engine.wl.pool = wl_shm_create_pool(shm, fd, size);
611 _ecore_evas_wl_buffer_free(Ecore_Evas *ee)
613 if (!ee->engine.wl.buffer) return;
615 wl_buffer_destroy(ee->engine.wl.buffer);
616 ee->engine.wl.buffer = NULL;
620 _ecore_evas_wl_buffer_new(Ecore_Evas *ee, int w, int h)
625 stride = (w * sizeof(int));
627 _ecore_evas_wl_shm_pool_create(ee, stride * h);
629 if ((ee->alpha) || (ee->transparent))
630 format = WL_SHM_FORMAT_ARGB8888;
632 format = WL_SHM_FORMAT_XRGB8888;
634 _ecore_evas_wl_buffer_free(ee);
635 ee->engine.wl.buffer =
636 wl_shm_pool_create_buffer(ee->engine.wl.pool, 0, w, h, stride, format);
640 _ecore_evas_wayland_shm_resize(Ecore_Evas *ee, int location)
642 LOGFN(__FILE__, __LINE__, __FUNCTION__);
645 if (ee->engine.wl.win)
647 ee->engine.wl.win->resizing = EINA_TRUE;
648 ecore_wl_window_resize(ee->engine.wl.win, ee->w, ee->h, location);
653 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__)