#define E_COMP_WL #include "e.h" #define COMPOSITOR_VERSION 3 #define E_COMP_WL_PIXMAP_CHECK \ if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return /* local functions */ static void _e_comp_wl_log_cb_print(const char *format, va_list args) { INF("WL: ", format, args); } static Eina_Bool _e_comp_wl_cb_read(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) { E_Comp_Data *cdata; if (!(cdata = data)) return ECORE_CALLBACK_RENEW; /* dispatch pending wayland events */ wl_event_loop_dispatch(cdata->wl.loop, 0); return ECORE_CALLBACK_RENEW; } static void _e_comp_wl_cb_prepare(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) { E_Comp_Data *cdata; if (!(cdata = data)) return; /* flush pending client events */ wl_display_flush_clients(cdata->wl.disp); } static Eina_Bool _e_comp_wl_cb_module_idle(void *data) { E_Comp_Data *cdata; E_Module *mod = NULL; if (!(cdata = data)) return ECORE_CALLBACK_RENEW; /* check if we are still loading modules */ if (e_module_loading_get()) return ECORE_CALLBACK_RENEW; if (!(mod = e_module_find("wl_desktop_shell"))) mod = e_module_new("wl_desktop_shell"); if (mod) { e_module_enable(mod); /* FIXME: NB: * Do we need to dispatch pending wl events here ?? */ return ECORE_CALLBACK_CANCEL; } return ECORE_CALLBACK_RENEW; } static void _e_comp_wl_compositor_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) { E_Comp *comp; struct wl_resource *res; if (!(comp = data)) return; if (!(res = wl_resource_create(client, &wl_compositor_interface, MIN(version, COMPOSITOR_VERSION), id))) { ERR("Could not create compositor resource: %m"); wl_client_post_no_memory(client); return; } } static void _e_comp_wl_compositor_cb_del(E_Comp *comp) { E_Comp_Data *cdata; /* get existing compositor data */ if (!(cdata = comp->wl_comp_data)) return; /* free allocated data structure */ free(cdata); } static Eina_Bool _e_comp_wl_compositor_create(void) { E_Comp *comp; const char *name; int fd = 0; /* check for existing compositor. create if needed */ if (!(comp = e_comp_get(NULL))) { comp = e_comp_new(); comp->comp_type = E_PIXMAP_TYPE_WL; E_OBJECT_DEL_SET(comp, _e_comp_wl_compositor_cb_del); } /* create new compositor data */ cdata = E_NEW(E_Comp_Data, 1); /* set wayland log handler */ wl_log_set_handler_server(_e_comp_wl_log_cb_print); /* try to create a wayland display */ if (!(cdata->wl.disp = wl_display_create())) { ERR("Could not create a Wayland display: %m"); goto disp_err; } /* try to setup wayland socket */ if (!(name = wl_display_add_socket_auto(cdata->wl.disp))) { ERR("Could not create Wayland display socket: %m"); goto sock_err; } /* set wayland display environment variable */ e_env_set("WAYLAND_DISPLAY", name); /* initialize compositor signals */ wl_signal_init(&cdata->signals.surface.create); wl_signal_init(&cdata->signals.surface.activate); wl_signal_init(&cdata->signals.surface.kill); /* try to add compositor to wayland globals */ if (!wl_global_create(cdata->wl.disp, &wl_compositor_interface, COMPOSITOR_VERSION, comp, _e_comp_wl_compositor_cb_bind)) { ERR("Could not add compositor to wayland globals: %m"); goto comp_global_err; } /* try to init data manager */ if (!e_comp_wl_data_manager_init(cdata)) { ERR("Could not initialize data manager"); goto data_err; } /* try to init input */ if (!e_comp_wl_input_init(cdata)) { ERR("Could not initialize input"); goto input_err; } /* initialize shm mechanism */ wl_display_init_shm(cdata->wl.disp); /* get the wayland display loop */ cdata->wl.loop = wl_display_get_event_loop(cdata->wl.disp); /* get the file descriptor of the wayland event loop */ fd = wl_event_loop_get_fd(cdata->wl.loop); /* create a listener for wayland main loop events */ cdata->fd_hdlr = ecore_main_fd_handler_add(fd, (ECORE_FD_READ | ECORE_FD_ERROR), _e_comp_wl_cb_read, cdata, NULL, NULL); ecore_main_fd_handler_prepare_callback_set(cdata->fd_hdlr, _e_comp_wl_cb_prepare, cdata); /* setup module idler to load shell mmodule */ ecore_idler_add(_e_comp_wl_cb_module_idle, cdata); if (comp->comp_type == E_PIXMAP_TYPE_X) { e_comp_wl_input_pointer_enabled_set(cdata, EINA_TRUE); e_comp_wl_input_keyboard_enabled_set(cdata, EINA_TRUE); } /* set compositor wayland data */ comp->wl_comp_data = cdata; return EINA_TRUE; input_err: e_comp_wl_data_manager_shutdown(cdata); data_err: comp_global_err: e_env_unset("WAYLAND_DISPLAY"); sock_err: wl_display_destroy(cdata->wl.disp); disp_err: free(cdata); return EINA_FALSE; } /* public functions */ EAPI Eina_Bool e_comp_wl_init(void) { /* set gl available if we have ecore_evas support */ if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_WAYLAND_EGL) || ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_OPENGL_DRM)) e_comp_gl_set(EINA_TRUE); /* try to create a wayland compositor */ if (!_e_comp_wl_compositor_create()) { e_error_message_show(_("Enlightenment cannot create a Wayland Compositor!\n")); return EINA_FALSE; } /* try to init ecore_wayland */ if (!ecore_wl_init(NULL)) { e_error_message_show(_("Enlightenment cannot initialize Ecore_Wayland!\n")); return EINA_FALSE; } return EINA_TRUE; } EAPI struct wl_signal e_comp_wl_surface_create_signal_get(E_Comp *comp) { return comp->wl_comp_data->signals.surface.create; } /* internal functions */ EINTERN void e_comp_wl_shutdown(void) { /* shutdown ecore_wayland */ ecore_wl_shutdown(); } EINTERN struct wl_resource * e_comp_wl_surface_create(struct wl_client *client, int version, uint32_t id) { return NULL; }