17 # define alloca __builtin_alloca
19 # define alloca __alloca
20 # elif defined _MSC_VER
22 # define alloca _alloca
23 # elif !defined HAVE_ALLOCA
27 void *alloca (size_t);
35 # define LOGFN(fl, ln, fn) \
36 printf("-ECORE_EVAS-WL: %25s: %5i - %s\n", fl, ln, fn);
38 # define LOGFN(fl, ln, fn)
41 #ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
45 # include <sys/types.h>
46 # include <sys/mman.h>
51 #include "Ecore_Evas.h"
53 #ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
54 # include "ecore_evas_private.h"
55 # include <Evas_Engine_Wayland_Shm.h>
56 # include <Ecore_Wayland.h>
58 /* local function prototypes */
59 static void _ecore_evas_wl_free(Ecore_Evas *ee);
60 static void _ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h);
61 static void _ecore_evas_wl_move_resize(Ecore_Evas *ee, int x, int y, int w, int h);
62 static void _ecore_evas_wl_show(Ecore_Evas *ee);
63 static void _ecore_evas_wl_hide(Ecore_Evas *ee);
64 static void _ecore_evas_wl_alpha_set(Ecore_Evas *ee, int alpha);
65 static void _ecore_evas_wl_transparent_set(Ecore_Evas *ee, int transparent);
66 static int _ecore_evas_wl_render(Ecore_Evas *ee);
69 static void _ecore_evas_wl_shm_pool_free(Ecore_Evas *ee);
70 static void _ecore_evas_wl_shm_pool_create(Ecore_Evas *ee, size_t size);
71 static void _ecore_evas_wl_buffer_free(Ecore_Evas *ee);
72 static void _ecore_evas_wl_buffer_new(Ecore_Evas *ee, int w, int h);
75 static void _ecore_evas_wl_frame_complete(void *data, struct wl_callback *callback, uint32_t time);
76 static const struct wl_callback_listener frame_listener =
78 _ecore_evas_wl_frame_complete,
81 static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
84 _ecore_evas_wl_common_callback_resize_set,
85 _ecore_evas_wl_common_callback_move_set,
88 _ecore_evas_wl_common_callback_delete_request_set,
90 _ecore_evas_wl_common_callback_focus_in_set,
91 _ecore_evas_wl_common_callback_focus_out_set,
92 _ecore_evas_wl_common_callback_mouse_in_set,
93 _ecore_evas_wl_common_callback_mouse_out_set,
96 NULL, // pre_render_set
97 NULL, // post_render_set
98 _ecore_evas_wl_common_move,
100 _ecore_evas_wl_resize,
101 _ecore_evas_wl_move_resize,
102 NULL, // rotation_set
106 _ecore_evas_wl_common_raise,
109 _ecore_evas_wl_common_title_set,
110 _ecore_evas_wl_common_name_class_set,
111 _ecore_evas_wl_common_size_min_set,
112 _ecore_evas_wl_common_size_max_set,
113 _ecore_evas_wl_common_size_base_set,
114 _ecore_evas_wl_common_size_step_set,
115 NULL, // object_cursor_set
116 _ecore_evas_wl_common_layer_set,
118 _ecore_evas_wl_common_iconified_set,
119 NULL, // borderless set
120 NULL, // override set
121 _ecore_evas_wl_common_maximized_set,
122 _ecore_evas_wl_common_fullscreen_set,
123 NULL, // func avoid_damage set
124 NULL, // func withdrawn set
125 NULL, // func sticky set
126 _ecore_evas_wl_common_ignore_events_set,
127 _ecore_evas_wl_alpha_set,
128 _ecore_evas_wl_transparent_set,
129 NULL, // func profiles set
130 NULL, // window group set
134 NULL, // demand attention set
135 NULL, // focus skip set
136 _ecore_evas_wl_render,
137 _ecore_evas_wl_common_screen_geometry_get,
138 _ecore_evas_wl_common_screen_dpi_get,
139 NULL, // wm_rot_preferred_rotation_set
140 NULL // wm_rot_available_rotations_set
143 /* external variables */
145 /* external functions */
147 ecore_evas_wayland_shm_new(const char *disp_name, unsigned int parent, int x, int y, int w, int h, Eina_Bool frame)
149 Ecore_Wl_Window *p = NULL;
150 Evas_Engine_Info_Wayland_Shm *einfo;
152 int method = 0, count = 0;
154 LOGFN(__FILE__, __LINE__, __FUNCTION__);
156 if (!(method = evas_render_method_lookup("wayland_shm")))
158 ERR("Render method lookup failed for Wayland_Shm");
162 count = ecore_wl_init(disp_name);
165 ERR("Failed to initialize Ecore_Wayland");
169 ecore_wl_display_iterate();
171 if (!(ee = calloc(1, sizeof(Ecore_Evas))))
173 ERR("Failed to allocate Ecore_Evas");
177 ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
179 _ecore_evas_wl_common_init();
181 ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_wl_engine_func;
183 ee->driver = "wayland_shm";
184 if (disp_name) ee->name = strdup(disp_name);
198 ee->prop.max.w = 32767;
199 ee->prop.max.h = 32767;
201 ee->prop.request_pos = 0;
203 ee->prop.draw_frame = frame;
204 ee->alpha = EINA_FALSE;
206 ee->evas = evas_new();
207 evas_data_attach_set(ee->evas, ee);
208 evas_output_method_set(ee->evas, method);
209 evas_output_size_set(ee->evas, ee->w, ee->h);
210 evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
212 /* FIXME: This needs to be set based on theme & scale */
213 if (ee->prop.draw_frame)
214 evas_output_framespace_set(ee->evas, 4, 18, 8, 22);
217 p = ecore_wl_window_find(parent);
219 /* FIXME: Get if parent is alpha, and set */
221 ee->engine.wl.parent = p;
223 ecore_wl_window_new(p, x, y, w, h, ECORE_WL_WINDOW_BUFFER_TYPE_SHM);
224 ee->prop.window = ee->engine.wl.win->id;
226 if ((einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas)))
228 einfo->info.destination_alpha = ee->alpha;
229 einfo->info.rotation = ee->rotation;
230 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
232 ERR("Failed to set Evas Engine Info for '%s'", ee->driver);
238 ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
242 ecore_evas_callback_pre_free_set(ee, _ecore_evas_wl_common_pre_free);
244 if (ee->prop.draw_frame)
246 ee->engine.wl.frame = _ecore_evas_wl_common_frame_add(ee->evas);
247 evas_object_is_frame_object_set(ee->engine.wl.frame, EINA_TRUE);
248 evas_object_move(ee->engine.wl.frame, 0, 0);
251 _ecore_evas_register(ee);
252 ecore_evas_input_event_register(ee);
254 ecore_event_window_register(ee->prop.window, ee, ee->evas,
255 (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
256 (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
257 (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
258 (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
264 _ecore_evas_wl_common_shutdown();
272 _ecore_evas_wl_free(Ecore_Evas *ee)
274 _ecore_evas_wl_buffer_free(ee);
275 _ecore_evas_wl_shm_pool_free(ee);
276 _ecore_evas_wl_common_free(ee);
280 _ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h)
282 Evas_Engine_Info_Wayland_Shm *einfo;
284 LOGFN(__FILE__, __LINE__, __FUNCTION__);
293 if (!ee->prop.fullscreen)
297 if (ee->prop.min.w > w) w = ee->prop.min.w;
298 else if (w > ee->prop.max.w) w = ee->prop.max.w;
299 if (ee->prop.min.h > h) h = ee->prop.min.h;
300 else if (h > ee->prop.max.h) h = ee->prop.max.h;
302 evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh);
307 if ((ee->w != w) || (ee->h != h))
312 if ((ee->rotation == 90) || (ee->rotation == 270))
314 evas_output_size_set(ee->evas, h, w);
315 evas_output_viewport_set(ee->evas, 0, 0, h, w);
319 evas_output_size_set(ee->evas, w, h);
320 evas_output_viewport_set(ee->evas, 0, 0, w, h);
323 if (ee->prop.avoid_damage)
327 pdam = ecore_evas_avoid_damage_get(ee);
328 ecore_evas_avoid_damage_set(ee, 0);
329 ecore_evas_avoid_damage_set(ee, pdam);
332 if (ee->engine.wl.frame)
333 evas_object_resize(ee->engine.wl.frame, w, h);
335 _ecore_evas_wl_buffer_new(ee, w, h);
337 einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
340 ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
344 einfo->info.dest = ee->engine.wl.pool_data;
345 evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
347 if (ee->engine.wl.win)
349 ecore_wl_window_update_size(ee->engine.wl.win, w, h);
350 ecore_wl_window_buffer_attach(ee->engine.wl.win,
351 ee->engine.wl.buffer, 0, 0);
354 if (ee->func.fn_resize) ee->func.fn_resize(ee);
359 _ecore_evas_wl_move_resize(Ecore_Evas *ee, int x, int y, int w, int h)
361 LOGFN(__FILE__, __LINE__, __FUNCTION__);
364 if ((ee->x != x) || (ee->y != y))
365 _ecore_evas_wl_common_move(ee, x, y);
366 if ((ee->w != w) || (ee->h != h))
367 _ecore_evas_wl_resize(ee, w, h);
371 _ecore_evas_wl_show(Ecore_Evas *ee)
373 Evas_Engine_Info_Wayland_Shm *einfo;
375 LOGFN(__FILE__, __LINE__, __FUNCTION__);
377 if ((!ee) || (ee->visible)) return;
379 _ecore_evas_wl_buffer_new(ee, ee->w, ee->h);
381 einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
384 ERR("Failed to get Evas Engine Info for '%s'", ee->driver);
388 einfo->info.dest = ee->engine.wl.pool_data;
389 evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
391 if (ee->engine.wl.win)
393 ecore_wl_window_show(ee->engine.wl.win);
394 ecore_wl_window_update_size(ee->engine.wl.win, ee->w, ee->h);
395 ecore_wl_window_buffer_attach(ee->engine.wl.win,
396 ee->engine.wl.buffer, 0, 0);
398 if ((ee->prop.clas) && (ee->engine.wl.win->shell_surface))
399 wl_shell_surface_set_class(ee->engine.wl.win->shell_surface,
401 if ((ee->prop.title) && (ee->engine.wl.win->shell_surface))
402 wl_shell_surface_set_title(ee->engine.wl.win->shell_surface,
406 if (ee->engine.wl.frame)
408 evas_object_show(ee->engine.wl.frame);
409 evas_object_resize(ee->engine.wl.frame, ee->w, ee->h);
413 if (ee->func.fn_show) ee->func.fn_show(ee);
417 _ecore_evas_wl_hide(Ecore_Evas *ee)
419 Evas_Engine_Info_Wayland_Shm *einfo;
421 LOGFN(__FILE__, __LINE__, __FUNCTION__);
423 if ((!ee) || (!ee->visible)) return;
425 _ecore_evas_wl_buffer_free(ee);
427 munmap(ee->engine.wl.pool_data, ee->engine.wl.pool_size);
429 einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
430 if ((einfo) && (einfo->info.dest))
432 einfo->info.dest = NULL;
433 evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
436 if (ee->engine.wl.win)
437 ecore_wl_window_hide(ee->engine.wl.win);
440 ee->should_be_visible = 0;
442 if (ee->func.fn_hide) ee->func.fn_hide(ee);
446 _ecore_evas_wl_alpha_set(Ecore_Evas *ee, int alpha)
448 Evas_Engine_Info_Wayland_Shm *einfo;
449 Ecore_Wl_Window *win = NULL;
451 LOGFN(__FILE__, __LINE__, __FUNCTION__);
454 if ((ee->alpha == alpha)) return;
457 /* FIXME: NB: We should really add a ecore_wl_window_alpha_set function
458 * but we are in API freeze, so just hack it in for now and fix when
460 if ((win = ee->engine.wl.win))
463 /* if (ee->engine.wl.win) */
464 /* ecore_wl_window_transparent_set(ee->engine.wl.win, alpha); */
466 _ecore_evas_wl_buffer_new(ee, ee->w, ee->h);
468 if ((einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas)))
470 einfo->info.destination_alpha = alpha;
471 einfo->info.dest = ee->engine.wl.pool_data;
472 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
473 ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
474 evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
479 ecore_wl_window_update_size(win, ee->w, ee->h);
480 ecore_wl_window_buffer_attach(win, ee->engine.wl.buffer, 0, 0);
485 _ecore_evas_wl_transparent_set(Ecore_Evas *ee, int transparent)
487 Evas_Engine_Info_Wayland_Shm *einfo;
489 LOGFN(__FILE__, __LINE__, __FUNCTION__);
492 if ((ee->transparent == transparent)) return;
493 ee->transparent = transparent;
495 if (ee->engine.wl.win)
496 ecore_wl_window_transparent_set(ee->engine.wl.win, transparent);
498 _ecore_evas_wl_buffer_new(ee, ee->w, ee->h);
500 if ((einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas)))
502 einfo->info.destination_alpha = transparent;
503 einfo->info.dest = ee->engine.wl.pool_data;
504 if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
505 ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver);
506 evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
509 if (ee->engine.wl.win)
511 ecore_wl_window_update_size(ee->engine.wl.win, ee->w, ee->h);
512 ecore_wl_window_buffer_attach(ee->engine.wl.win,
513 ee->engine.wl.buffer, 0, 0);
518 _ecore_evas_wl_frame_complete(void *data, struct wl_callback *callback, uint32_t time __UNUSED__)
520 Ecore_Evas *ee = data;
521 Ecore_Wl_Window *win = NULL;
524 if (!(win = ee->engine.wl.win)) return;
526 win->frame_callback = NULL;
527 win->frame_pending = EINA_FALSE;
528 wl_callback_destroy(callback);
532 win->frame_callback = wl_surface_frame(win->surface);
533 wl_callback_add_listener(win->frame_callback, &frame_listener, ee);
538 _ecore_evas_wl_render(Ecore_Evas *ee)
541 Ecore_Wl_Window *win = NULL;
546 evas_norender(ee->evas);
550 if (!(win = ee->engine.wl.win)) return 0;
552 rend = _ecore_evas_wl_common_pre_render(ee);
553 if (!(win->frame_pending))
555 /* FIXME - ideally have an evas_changed_get to return the value
556 * of evas->changed to avoid creating this callback and
557 * destroying it again
560 if (!win->frame_callback)
562 win->frame_callback = wl_surface_frame(win->surface);
563 wl_callback_add_listener(win->frame_callback, &frame_listener, ee);
566 rend |= _ecore_evas_wl_common_render_updates(ee);
568 win->frame_pending = EINA_TRUE;
570 _ecore_evas_wl_common_post_render(ee);
575 _ecore_evas_wl_shm_pool_free(Ecore_Evas *ee)
577 if (!ee->engine.wl.pool) return;
579 wl_shm_pool_destroy(ee->engine.wl.pool);
580 ee->engine.wl.pool = NULL;
581 ee->engine.wl.pool_size = 0;
582 ee->engine.wl.pool_data = NULL;
586 _ecore_evas_wl_shm_pool_create(Ecore_Evas *ee, size_t size)
593 LOGFN(__FILE__, __LINE__, __FUNCTION__);
595 if (size <= ee->engine.wl.pool_size)
599 _ecore_evas_wl_shm_pool_free(ee);
601 if (!(shm = ecore_wl_shm_get()))
603 ERR("ecore_wl_shm_get returned NULL");
607 strcpy(tmp, "/tmp/ecore-evas-wayland_shm-XXXXXX");
608 if ((fd = mkstemp(tmp)) < 0)
610 ERR("Could not create temporary file.");
614 if (ftruncate(fd, size) < 0)
616 ERR("Could not truncate temporary file.");
620 data = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0);
623 if (data == MAP_FAILED)
625 ERR("mmap of temporary file failed.");
629 ee->engine.wl.pool_size = size;
630 ee->engine.wl.pool_data = data;
631 ee->engine.wl.pool = wl_shm_create_pool(shm, fd, size);
638 _ecore_evas_wl_buffer_free(Ecore_Evas *ee)
640 if (!ee->engine.wl.buffer) return;
642 wl_buffer_destroy(ee->engine.wl.buffer);
643 ee->engine.wl.buffer = NULL;
647 _ecore_evas_wl_buffer_new(Ecore_Evas *ee, int w, int h)
652 stride = (w * sizeof(int));
654 _ecore_evas_wl_shm_pool_create(ee, stride * h);
656 if ((ee->alpha) || (ee->transparent))
657 format = WL_SHM_FORMAT_ARGB8888;
659 format = WL_SHM_FORMAT_XRGB8888;
661 _ecore_evas_wl_buffer_free(ee);
662 ee->engine.wl.buffer =
663 wl_shm_pool_create_buffer(ee->engine.wl.pool, 0, w, h, stride, format);
667 _ecore_evas_wayland_shm_resize(Ecore_Evas *ee, int location)
669 LOGFN(__FILE__, __LINE__, __FUNCTION__);
672 if (ee->engine.wl.win)
674 ee->engine.wl.win->resizing = EINA_TRUE;
675 ecore_wl_window_resize(ee->engine.wl.win, ee->w, ee->h, location);
680 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__)