ecore-psl1ght.pc.in \
ecore-input.pc.in \
ecore-wince.pc.in \
+ecore-wayland.pc.in \
ecore.spec.in \
ecore.spec \
m4/ac_abstract_socket.m4 \
pkgconfig_DATA += ecore-psl1ght.pc
endif
+if BUILD_ECORE_WAYLAND
+pkgconfig_DATA += ecore-wayland.pc
+endif
+
.PHONY: doc
# Documentation
want_ecore_fb="no"
want_ecore_directfb="no"
want_ecore_wince="no"
+want_ecore_wayland="no"
# ecore_x options (both xlib and xcb)
want_ecore_x_composite="yes"
want_ecore_evas_fb="no"
want_ecore_evas_software_16_wince="no"
want_ecore_evas_ews="yes"
+want_ecore_evas_wayland_shm="no"
+want_ecore_evas_wayland_egl="no"
# ecore_imf modules
want_ecore_imf_xim="no"
want_ecore_fb="yes"
want_ecore_imf="yes"
want_ecore_x="yes"
+ want_ecore_wayland="yes"
want_ecore_evas_software_x11="yes"
want_ecore_evas_opengl_x11="yes"
want_ecore_evas_software_16_x11="yes"
want_ecore_evas_gl_cocoa="no"
want_ecore_evas_directfb="yes"
want_ecore_evas_fb="yes"
+ want_ecore_evas_wayland_shm="yes"
+ want_ecore_evas_wayland_egl="yes"
want_ecore_imf_xim="yes"
want_ecore_imf_scim="yes"
;;
requirements_ecore_wince=""
requirements_ecore_imf_xim=""
requirements_ecore_imf_scim=""
+requirements_ecore_wayland=""
AC_CHECK_DECL([MAXHOSTNAMELEN],[FOUND_MAXHOSTNAMELEN=yes])
[${have_ecore_psl1ght}],
[requirements_ecore_evas="ecore-psl1ght >= 1.1.99 ${requirements_ecore_evas}"])
+### WAYLAND
+
+ecore_wayland_deps="no"
+have_wayland="no"
+if test "x${want_ecore_wayland}" = "xyes" ; then
+ PKG_CHECK_MODULES([WAYLAND], [wayland-client xkbcommon], [have_wayland="yes"], [have_wayland="no"])
+fi
+if test "x${have_ecore_input}" = "xyes" -a "x${have_wayland}" = "xyes" ; then
+ ecore_wayland_deps="yes"
+fi
+
+ECORE_CHECK_MODULE([wayland], [${want_ecore_wayland}], [Wayland], [${ecore_wayland_deps}])
+if test "x${have_ecore_wayland}" = "xyes" ; then
+ requirements_ecore_wayland="ecore-input >= 1.1.0 wayland-client xkbcommon ${requirements_ecore_wayland}"
+fi
+
+ECORE_EVAS_CHECK_MODULE_FULL([wayland-shm], [wayland-shm],
+ [${want_ecore_evas_wayland_shm}],
+ [Wayland Shm],
+ [${have_ecore_wayland}],
+ [requirements_ecore_evas="ecore-wayland >= 1.1.0 ${requirements_ecore_evas}"])
+
+ECORE_EVAS_CHECK_MODULE_FULL([wayland-egl], [wayland-egl],
+ [${want_ecore_evas_wayland_egl}],
+ [Wayland Egl],
+ [${have_ecore_wayland}],
+ [requirements_ecore_evas="ecore-wayland >= 1.1.0 ${requirements_ecore_evas}"])
+
### install and build examples
EFL_CHECK_BUILD_EXAMPLES([enable_build_examples="yes"], [enable_build_examples="no"])
AC_SUBST(requirements_ecore_wince)
AC_SUBST(requirements_ecore_imf_xim)
AC_SUBST(requirements_ecore_imf_scim)
+AC_SUBST(requirements_ecore_wayland)
AC_CONFIG_FILES([
Makefile
ecore-cocoa.pc
ecore-psl1ght.pc
ecore-wince.pc
+ecore-wayland.pc
ecore.pc
doc/ecore.dox
doc/Makefile
src/lib/ecore_x/Makefile
src/lib/ecore_x/xlib/Makefile
src/lib/ecore_x/xcb/Makefile
+src/lib/ecore_wayland/Makefile
src/examples/Makefile
src/tests/Makefile
src/modules/Makefile
echo " Ecore_DirectFB...............: $have_ecore_directfb"
echo " Ecore_WinCE..................: $have_ecore_wince"
echo " Ecore_PSL1GHT................: $have_ecore_psl1ght"
+echo " Ecore_Wayland................: $have_ecore_wayland"
echo
echo " Ecore Evas:"
echo " Software 16bit DirectDraw..: $have_ecore_evas_software_16_ddraw"
echo " Software 16bit WinCE.......: $have_ecore_evas_software_16_wince"
echo " Sing.Proc. Windowing System: $have_ecore_evas_ews"
+ echo " Wayland Shm................: $have_ecore_evas_wayland_shm"
+ echo " Wayland Egl................: $have_ecore_evas_wayland_egl"
fi
echo
echo " Tests................: ${enable_tests}"
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ecore-wayland
+Description: E core library, Wayland module
+@pkgconfig_requires_private@: @requirements_ecore_wayland@
+Version: @VERSION@
+Libs: -L${libdir} -lecore_wayland
+Libs.private: -lwayland-client
+Cflags: -I${includedir}/ecore-@VMAJ@
SUBDIRS += ecore_cocoa
endif
+if BUILD_ECORE_WAYLAND
+SUBDIRS += ecore_wayland
+endif
+
if BUILD_ECORE_IPC
SUBDIRS += ecore_ipc
endif
#define HAVE_ECORE_EVAS_WINCE 1
#define HAVE_ECORE_EVAS_EWS 1
#define HAVE_ECORE_EVAS_PSL1GHT 1
+#define HAVE_ECORE_EVAS_WAYLAND_SHM 1
+#define HAVE_ECORE_EVAS_WAYLAND_EGL 1
typedef enum _Ecore_Evas_Engine_Type
{
ECORE_EVAS_ENGINE_SOFTWARE_16_WINCE,
ECORE_EVAS_ENGINE_OPENGL_SDL,
ECORE_EVAS_ENGINE_EWS,
- ECORE_EVAS_ENGINE_PSL1GHT
+ ECORE_EVAS_ENGINE_PSL1GHT,
+ ECORE_EVAS_ENGINE_WAYLAND_SHM,
+ ECORE_EVAS_ENGINE_WAYLAND_EGL
} Ecore_Evas_Engine_Type;
typedef enum _Ecore_Evas_Avoid_Damage_Type
typedef struct _Ecore_Cocoa_Window Ecore_Cocoa_Window;
#endif
+#ifndef _ECORE_WAYLAND_H_
+typedef struct _Ecore_Wl_Window Ecore_Wl_Window;
+#endif
+
#ifndef _ECORE_EVAS_PRIVATE_H
/* basic data types */
typedef struct _Ecore_Evas Ecore_Evas;
EAPI Ecore_Evas *ecore_evas_directfb_new(const char *disp_name, int windowed, int x, int y, int w, int h);
EAPI Ecore_DirectFB_Window *ecore_evas_directfb_window_get(const Ecore_Evas *ee);
+EAPI Ecore_Evas *ecore_evas_wayland_shm_new(const char *disp_name, int x, int y, int w, int h, int frame);
+//EAPI Ecore_Evas *ecore_evas_wayland_egl_new(const char *disp_name, int x, int y, int w, int h, int frame);
+
/**
* @brief Create a new @c Ecore_Evas canvas bound to the Evas
* @b buffer engine
*/
EAPI void ecore_evas_screen_geometry_get(const Ecore_Evas *ee, int *x, int *y, int *w, int *h);
+EAPI void ecore_evas_draw_frame_set(Ecore_Evas *ee, Eina_Bool draw_frame);
+EAPI Eina_Bool ecore_evas_draw_frame_get(const Ecore_Evas *ee);
+
/**
* @brief Associate the given object to this ecore evas.
*
MAINTAINERCLEANFILES = Makefile.in
if BUILD_ECORE_X
-ECORE_X_INC = -I$(top_srcdir)/src/lib/ecore_x @x_cflags@ @ECORE_XCB_CFLAGS@
-ECORE_X_LIB = $(top_builddir)/src/lib/ecore_x/libecore_x.la @x_libs@ @ECORE_XCB_LIBS@
+ECORE_X_INC = -I$(top_srcdir)/src/lib/ecore_x @x_cflags@
+ECORE_X_LIB = $(top_builddir)/src/lib/ecore_x/libecore_x.la @x_libs@
else
ECORE_X_INC =
ECORE_X_LIB =
ECORE_PSL1GHT_LIB =
endif
+if BUILD_ECORE_WAYLAND
+ECORE_WAYLAND_INC = -I$(top_srcdir)/src/lib/ecore_wayland @WAYLAND_CFLAGS@
+ECORE_WAYLAND_LIB = $(top_builddir)/src/lib/ecore_wayland/libecore_wayland.la
+ECORE_WAYLAND_LIBADD = @WAYLAND_LIBS@ $(ECORE_WAYLAND_LIB)
+else
+ECORE_WAYLAND_INC =
+ECORE_WAYLAND_LIB =
+ECORE_WAYLAND_LIBADD =
+endif
+
if BUILD_ECORE_IPC
ECORE_IPC_INC= \
-I$(top_srcdir)/src/lib/ecore_ipc \
$(ECORE_COCOA_INC) \
$(ECORE_WINCE_INC) \
$(ECORE_PSL1GHT_INC) \
+$(ECORE_WAYLAND_INC) \
$(ECORE_IPC_INC) \
@EVAS_CFLAGS@ \
@EINA_CFLAGS@ \
ecore_evas_wince.c \
ecore_evas_ews.c \
ecore_evas_psl1ght.c \
+ecore_evas_wayland_shm.c \
ecore_evas_extn.c
libecore_evas_la_LIBADD = \
$(ECORE_WINCE_LIB) \
$(ECORE_IPC_LIB) \
$(ECORE_PSL1GHT_LIB) \
+$(ECORE_WAYLAND_LIB) \
+$(ECORE_WAYLAND_LIBADD) \
$(top_builddir)/src/lib/ecore_input/libecore_input.la \
$(top_builddir)/src/lib/ecore_input_evas/libecore_input_evas.la \
$(top_builddir)/src/lib/ecore/libecore.la \
#else
return EINA_FALSE;
#endif
+ case ECORE_EVAS_ENGINE_WAYLAND_SHM:
+#ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
+ return EINA_TRUE;
+#else
+ return EINA_FALSE;
+#endif
+ case ECORE_EVAS_ENGINE_WAYLAND_EGL:
+#ifdef BUILD_ECORE_EVAS_WAYLAND_EGL
+ return EINA_TRUE;
+#else
+ return EINA_FALSE;
+#endif
default:
return EINA_FALSE;
};
#ifdef BUILD_ECORE_EVAS_SOFTWARE_16_WINCE
while (_ecore_evas_wince_shutdown());
#endif
+
if (_ecore_evas_async_events_fd)
ecore_main_fd_handler_del(_ecore_evas_async_events_fd);
}
#endif
+#ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
+static Ecore_Evas *
+_ecore_evas_constructor_wayland_shm(int x, int y, int w, int h, const char *extra_options)
+{
+ char *disp_name = NULL;
+ unsigned int frame = 0;
+ Ecore_Evas *ee;
+
+ _ecore_evas_parse_extra_options_str(extra_options, "display=", &disp_name);
+ _ecore_evas_parse_extra_options_uint(extra_options, "frame=", &frame);
+ ee = ecore_evas_wayland_shm_new(disp_name, x, y, w, h, frame);
+ free(disp_name);
+
+ return ee;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_WAYLAND_EGL
+static Ecore_Evas *
+_ecore_evas_constructor_wayland_egl(int x, int y, int w, int h, const char *extra_options)
+{
+ char *disp_name = NULL;
+ unsigned int frame = 0;
+// Ecore_Evas *ee;
+
+ _ecore_evas_parse_extra_options_str(extra_options, "display=", &disp_name);
+ _ecore_evas_parse_extra_options_uint(extra_options, "frame=", &frame);
+// ee = ecore_evas_wayland_egl_new(disp_name, x, y, w, h, frame);
+ free(disp_name);
+
+ return NULL;
+}
+#endif
+
#ifdef BUILD_ECORE_EVAS_SOFTWARE_GDI
static Ecore_Evas *
_ecore_evas_constructor_software_gdi(int x, int y, int w, int h, const char *extra_options)
{"psl1ght", _ecore_evas_constructor_psl1ght},
#endif
- /* Last chance to have a window */
+ /* Wayland */
+#ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
+ {"wayland_shm", _ecore_evas_constructor_wayland_shm},
+#endif
+
+#ifdef BUILD_ECORE_EVAS_WAYLAND_EGL
+ {"wayland_egl", _ecore_evas_constructor_wayland_egl},
+#endif
+
+ /* Last chance to have a window */
#ifdef BUILD_ECORE_EVAS_OPENGL_SDL
{"opengl_sdl", _ecore_evas_constructor_opengl_sdl},
#endif
ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
"ecore_evas_withdrawn_get");
return EINA_FALSE;
- } else
- return ee->prop.withdrawn ? EINA_TRUE : EINA_FALSE;
+ }
+ return ee->prop.withdrawn ? EINA_TRUE : EINA_FALSE;
}
/**
ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
"ecore_evas_sticky_get");
return EINA_FALSE;
- } else
- return ee->prop.sticky ? EINA_TRUE : EINA_FALSE;
+ }
+ return ee->prop.sticky ? EINA_TRUE : EINA_FALSE;
}
EAPI void
IFE;
}
+EAPI void
+ecore_evas_draw_frame_set(Ecore_Evas *ee, Eina_Bool draw_frame)
+{
+ if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+ {
+ ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, "ecore_evas_draw_frame_set");
+ return;
+ }
+ ee->prop.draw_frame = draw_frame;
+}
+
+EAPI Eina_Bool
+ecore_evas_draw_frame_get(const Ecore_Evas *ee)
+{
+ if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
+ {
+ ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, "ecore_evas_draw_frame_get");
+ return EINA_FALSE;
+ }
+ return ee->prop.draw_frame;
+}
+
/* fps debug calls - for debugging how much time your app actually spends */
/* rendering graphics... :) */
if (ee->visible)
{
Eina_List *updates;
-
Eina_List *ll;
Ecore_Evas *ee2;
+
if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
# include <Evas_Engine_Gl_Cocoa.h>
#endif
-/**
- Log domain macros and variable
- **/
+#ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
+# include "Ecore_Wayland.h"
+# include <Evas_Engine_Wayland_Shm.h>
+#endif
+
+#ifdef BUILD_ECORE_EVAS_WAYLAND_EGL
+# include "Ecore_Wayland.h"
+# include <Evas_Engine_Wayland_Egl.h>
+#endif
+
+/** Log domain macros and variables **/
extern int _ecore_evas_log_dom;
} ews;
#endif
+#if defined(BUILD_ECORE_EVAS_WAYLAND_SHM) || defined(BUILD_ECORE_EVAS_WAYLAND_EGL)
+ struct
+ {
+ Evas_Object *frame;
+
+# ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
+ struct wl_surface *surface;
+ struct wl_shell_surface *shell_surface;
+ struct wl_buffer *buffer;
+# endif
+
+ } wl;
+#endif
+
Ecore_Timer *idle_flush_timer;
};
char withdrawn : 1;
char sticky : 1;
char request_pos : 1;
+ char draw_frame : 1;
} prop;
struct {
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+# define LOGFNS 1
+
+# ifdef LOGFNS
+# include <stdio.h>
+# define LOGFN(fl, ln, fn) \
+ printf("-ECORE_EVAS-WL: %25s: %5i - %s\n", fl, ln, fn);
+# else
+# define LOGFN(fl, ln, fn)
+# endif
+# include <stdlib.h>
+# include <string.h>
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/mman.h>
+
+# include <Eina.h>
+# include <Evas.h>
+# include <Ecore.h>
+
+# include "ecore_evas_private.h"
+# include "Ecore_Evas.h"
+
+#ifdef BUILD_ECORE_EVAS_WAYLAND_EGL
+# include <Evas_Engine_Wayland_Egl.h>
+# include <Ecore_Wayland.h>
+#endif
+
+#ifdef BUILD_ECORE_EVAS_WAYLAND_EGL
+/* local function prototypes */
+static int _ecore_evas_wl_init(Ecore_Evas *ee);
+static int _ecore_evas_wl_shutdown(void);
+static void _ecore_evas_wl_free(Ecore_Evas *ee);
+static void _ecore_evas_wl_move(Ecore_Evas *ee, int x, int y);
+static void _ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h);
+static void _ecore_evas_wl_show(Ecore_Evas *ee);
+static int _ecore_evas_wl_render(Ecore_Evas *ee);
+
+/* local variables */
+static int _ecore_evas_init_count = 0;
+
+static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
+{
+ _ecore_evas_wl_free,
+ NULL, // _ecore_evas_wl_callback_resize_set,
+ NULL, // _ecore_evas_wl_callback_move_set,
+ NULL, // callback show set
+ NULL, // callback hide set
+ NULL, // _ecore_evas_wl_callback_delete_request_set,
+ NULL, // callback destroy set
+ NULL, // _ecore_evas_wl_callback_focus_in_set,
+ NULL, // _ecore_evas_wl_callback_focus_out_set,
+ NULL, // callback mouse in set
+ NULL, // callback mouse out set
+ NULL, // callback sticky set
+ NULL, // callback unsticky set
+ NULL, // callback pre render set
+ NULL, // callback post render set
+ _ecore_evas_wl_move,
+ NULL, // func managed move
+ _ecore_evas_wl_resize,
+ NULL, // _ecore_evas_wl_move_resize,
+ NULL, // func rotation set
+ NULL, // func shaped set
+ _ecore_evas_wl_show,
+ NULL, // _ecore_evas_wl_hide,
+ NULL, // _ecore_evas_wl_raise,
+ NULL, // _ecore_evas_wl_lower,
+ NULL, // _ecore_evas_wl_activate,
+ NULL, // _ecore_evas_wl_title_set,
+ NULL, // _ecore_evas_wl_name_class_set,
+ NULL, // _ecore_evas_wl_size_min_set,
+ NULL, // _ecore_evas_wl_size_max_set,
+ NULL, // _ecore_evas_wl_size_base_set,
+ NULL, // _ecore_evas_wl_size_step_set,
+ NULL, // _ecore_evas_wl_object_cursor_set,
+ NULL, // _ecore_evas_wl_layer_set,
+ NULL, // _ecore_evas_wl_focus_set,
+ NULL, // func iconified set
+ NULL, // func borderless set
+ NULL, // func override set
+ NULL, // func maximized set
+ NULL, // func fullscreen set
+ NULL, // _ecore_evas_wl_avoid_damage_set,
+ NULL, // func withdrawn set
+ NULL, // func sticky set
+ NULL, // func ignore events set
+ NULL, // func alpha set
+ NULL, // func transparent set
+ _ecore_evas_wl_render,
+ NULL // _ecore_evas_wl_screen_geometry_get
+};
+
+#endif
+
+#ifdef BUILD_ECORE_EVAS_WAYLAND_EGL
+EAPI Ecore_Evas *
+ecore_evas_wayland_egl_new(const char *disp_name, int x, int y, int w, int h, int frame)
+{
+ Evas_Engine_Info_Wayland_Egl *einfo;
+ Ecore_Evas *ee;
+ int method = 0;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!(method = evas_render_method_lookup("wayland_egl")))
+ {
+ ERR("Render method lookup failed for Wayland Egl");
+ return NULL;
+ }
+
+ if (!ecore_wl_init(disp_name))
+ {
+ ERR("Failed to initialize Ecore Wayland");
+ return NULL;
+ }
+
+ if (!(ee = calloc(1, sizeof(Ecore_Evas)))) return NULL;
+
+ ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+ _ecore_evas_wl_init(ee);
+
+ ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_wl_engine_func;
+
+ ee->driver = "wayland_egl";
+ if (disp_name) ee->name = strdup(disp_name);
+
+ if (w < 1) w = 1;
+ if (h < 1) h = 1;
+ ee->x = x;
+ ee->y = y;
+ ee->w = w;
+ ee->h = h;
+ ee->req.x = ee->x;
+ ee->req.y = ee->y;
+ ee->req.w = ee->w;
+ ee->req.h = ee->h;
+ ee->prop.max.w = 32767;
+ ee->prop.max.h = 32767;
+ ee->prop.layer = 4;
+ ee->prop.request_pos = 0;
+ ee->prop.sticky = 0;
+ ee->prop.draw_frame = frame;
+ ee->rotation = 0;
+
+ ee->engine.wl.win =
+ ecore_wl_window_new(ECORE_WL_WINDOW_TYPE_EGL, x, y, w, h);
+ ee->prop.window = ee->engine.wl.win->id;
+
+ ee->evas = evas_new();
+ evas_data_attach_set(ee->evas, ee);
+ evas_output_method_set(ee->evas, method);
+ evas_output_size_set(ee->evas, ee->w, ee->h);
+ evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+
+ if (ee->prop.draw_frame) evas_output_framespace_set(ee->evas, 4, 18, 8, 22);
+
+ if ((einfo = (Evas_Engine_Info_Wayland_Egl *)evas_engine_info_get(ee->evas)))
+ {
+ einfo->info.disp = ecore_wl_display_get();
+ einfo->info.comp = ecore_wl_compositor_get();
+ einfo->info.shell = ecore_wl_shell_get();
+ einfo->info.rotation = ee->rotation;
+ einfo->info.debug = EINA_FALSE;
+ if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+ {
+ ERR("Failed to set Evas Engine Info for '%s'.", ee->driver);
+ ecore_evas_free(ee);
+ return NULL;
+ }
+ }
+ else
+ {
+ ERR("Failed to get Evas Engine Info for '%s'.", ee->driver);
+ ecore_evas_free(ee);
+ return NULL;
+ }
+
+ ecore_evas_input_event_register(ee);
+ _ecore_evas_register(ee);
+
+ ecore_event_window_register(ee->prop.window, ee, ee->evas,
+ (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
+ (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
+ (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
+ (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
+
+ evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
+
+ return ee;
+}
+#else
+EAPI Ecore_Evas *
+ecore_evas_wayland_egl_new(const char *disp_name __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__, int frame __UNUSED__)
+{
+ return NULL;
+}
+#endif
+
+#ifdef BUILD_ECORE_EVAS_WAYLAND_EGL
+/* local functions */
+static int
+_ecore_evas_wl_init(Ecore_Evas *ee)
+{
+ _ecore_evas_init_count++;
+
+ /* TODO: Add handlers */
+
+ if (_ecore_evas_init_count > 1) return _ecore_evas_init_count;
+ ecore_event_evas_init();
+
+ return _ecore_evas_init_count;
+}
+
+static int
+_ecore_evas_wl_shutdown(void)
+{
+ _ecore_evas_init_count--;
+ if (_ecore_evas_init_count == 0)
+ {
+ /* TODO: Delete handlers */
+ }
+ if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0;
+ return _ecore_evas_init_count;
+}
+
+static void
+_ecore_evas_wl_free(Ecore_Evas *ee)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (ee)
+ {
+ if (ee->engine.wl.win) ecore_wl_window_free(ee->engine.wl.win);
+ ecore_event_window_unregister(ee->prop.window);
+ ecore_evas_input_event_unregister(ee);
+ }
+ _ecore_evas_wl_shutdown();
+ ecore_wl_shutdown();
+}
+
+static void
+_ecore_evas_wl_move(Ecore_Evas *ee, int x, int y)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!ee) return;
+ ee->req.x = x;
+ ee->req.y = y;
+ if ((ee->x == x) && (ee->y == y)) return;
+ ee->x = x;
+ ee->y = y;
+ /* TODO: Actually move this window */
+ if (!ee->should_be_visible) ee->prop.request_pos = 1;
+ if (ee->func.fn_move) ee->func.fn_move(ee);
+}
+
+static void
+_ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!ee) return;
+ ee->req.w = w;
+ ee->req.h = h;
+ if ((ee->w == w) && (ee->h == h)) return;
+
+ ee->w = w;
+ ee->h = h;
+ ecore_wl_window_resize(ee->engine.wl.win, w, h);
+
+ if ((ee->rotation == 90) || (ee->rotation == 270))
+ {
+ evas_output_size_set(ee->evas, h, w);
+ evas_output_viewport_set(ee->evas, 0, 0, h, w);
+ evas_damage_rectangle_add(ee->evas, 0, 0, h, w);
+ }
+ else
+ {
+ evas_output_size_set(ee->evas, w, h);
+ evas_output_viewport_set(ee->evas, 0, 0, w, h);
+ evas_damage_rectangle_add(ee->evas, 0, 0, w, h);
+ }
+
+ if (ee->func.fn_resize) ee->func.fn_resize(ee);
+}
+
+static void
+_ecore_evas_wl_show(Ecore_Evas *ee)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!ee) return;
+ ee->visible = 1;
+ ee->should_be_visible = 1;
+
+ if (ee->func.fn_show) ee->func.fn_show(ee);
+}
+
+static int
+_ecore_evas_wl_render(Ecore_Evas *ee)
+{
+ int rend = 0;
+
+ if (!ee) return 0;
+ if (ee->visible)
+ {
+ Eina_List *updates = NULL, *ll = NULL;
+ Ecore_Evas *ee2;
+
+ EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
+ {
+ if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
+ if (ee2->engine.func->fn_render)
+ rend |= ee2->engine.func->fn_render(ee2);
+ if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
+ }
+
+ if ((updates = evas_render_updates(ee->evas)))
+ {
+ if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
+
+ evas_render_updates_free(updates);
+ _ecore_evas_idle_timeout_update(ee);
+ rend = 1;
+
+ if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
+ }
+ else
+ evas_norender(ee->evas);
+ }
+ else
+ evas_norender(ee->evas);
+
+ return rend;
+}
+
+#endif
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#define LOGFNS 1
+
+#ifdef LOGFNS
+# include <stdio.h>
+# define LOGFN(fl, ln, fn) \
+ printf("-ECORE_EVAS-WL: %25s: %5i - %s\n", fl, ln, fn);
+#else
+# define LOGFN(fl, ln, fn)
+#endif
+
+# include <stdlib.h>
+# include <string.h>
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/mman.h>
+
+# include <Eina.h>
+# include <Evas.h>
+# include <Ecore.h>
+
+# include "ecore_evas_private.h"
+# include "Ecore_Evas.h"
+
+#ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
+# include <Evas_Engine_Wayland_Shm.h>
+# include <Ecore_Wayland.h>
+#endif
+
+#ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
+/* local function prototypes */
+static int _ecore_evas_wl_init(void);
+static int _ecore_evas_wl_shutdown(void);
+static void _ecore_evas_wl_pre_free(Ecore_Evas *ee);
+static void _ecore_evas_wl_free(Ecore_Evas *ee);
+static void _ecore_evas_wl_callback_resize_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
+static void _ecore_evas_wl_callback_move_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
+static void _ecore_evas_wl_callback_delete_request_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
+static void _ecore_evas_wl_callback_focus_in_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
+static void _ecore_evas_wl_callback_focus_out_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee));
+static void _ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h);
+static void _ecore_evas_wl_show(Ecore_Evas *ee);
+static int _ecore_evas_wl_render(Ecore_Evas *ee);
+static void _ecore_evas_wl_screen_geometry_get(const Ecore_Evas *ee __UNUSED__, int *x, int *y, int *w, int *h);
+static void _ecore_evas_wl_buffer_new(Ecore_Evas *ee, void **dest);
+
+static Eina_Bool _ecore_evas_wl_event_mouse_down(void *data __UNUSED__, int type __UNUSED__, void *event);
+static Eina_Bool _ecore_evas_wl_event_mouse_up(void *data __UNUSED__, int type __UNUSED__, void *event);
+static Eina_Bool _ecore_evas_wl_event_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event);
+static Eina_Bool _ecore_evas_wl_event_mouse_wheel(void *data __UNUSED__, int type __UNUSED__, void *event);
+static Eina_Bool _ecore_evas_wl_event_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event);
+static Eina_Bool _ecore_evas_wl_event_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event);
+static Eina_Bool _ecore_evas_wl_event_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event);
+static Eina_Bool _ecore_evas_wl_event_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event);
+
+/* local variables */
+static int _ecore_evas_wl_init_count = 0;
+static Ecore_Event_Handler *_ecore_evas_wl_event_handlers[8];
+
+static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
+{
+ _ecore_evas_wl_free,
+ _ecore_evas_wl_callback_resize_set,
+ _ecore_evas_wl_callback_move_set,
+ NULL, // callback show set
+ NULL, // callback hide set
+ _ecore_evas_wl_callback_delete_request_set,
+ NULL, // callback destroy set
+ _ecore_evas_wl_callback_focus_in_set,
+ _ecore_evas_wl_callback_focus_out_set,
+ NULL, // callback mouse in set
+ NULL, // callback mouse out set
+ NULL, // callback sticky set
+ NULL, // callback unsticky set
+ NULL, // callback pre render set
+ NULL, // callback post render set
+ NULL, // func move
+ NULL, // func managed move
+ _ecore_evas_wl_resize,
+ NULL, // func move_resize
+ NULL, // func rotation set
+ NULL, // func shaped set
+ _ecore_evas_wl_show,
+ NULL, // func hide
+ NULL, // func raise
+ NULL, // func lower
+ NULL, // func activate
+ NULL, // func title set
+ NULL, // func name_class set
+ NULL, // func size min set
+ NULL, // func size max set
+ NULL, // func size base set
+ NULL, // func size step set
+ NULL, // func object cursor set
+ NULL, // func layer set
+ NULL, // func focus set
+ NULL, // func iconified set
+ NULL, // func borderless set
+ NULL, // func override set
+ NULL, // func maximized set
+ NULL, // func fullscreen set
+ NULL, // func avoid_damage set
+ NULL, // func withdrawn set
+ NULL, // func sticky set
+ NULL, // func ignore_events set
+ NULL, // func alpha set
+ NULL, // func transparent set
+ _ecore_evas_wl_render,
+ _ecore_evas_wl_screen_geometry_get
+};
+
+/* external variables */
+#endif
+
+#ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
+EAPI Ecore_Evas *
+ecore_evas_wayland_shm_new(const char *disp_name, int x, int y, int w, int h, int frame)
+{
+ Evas_Engine_Info_Wayland_Shm *einfo;
+ Ecore_Evas *ee;
+ int method = 0;
+ static int _win_id = 1;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!(method = evas_render_method_lookup("wayland_shm")))
+ {
+ ERR("Render method lookup failed.");
+ return NULL;
+ }
+
+ if (!(ecore_wl_init(disp_name)))
+ {
+ ERR("Failed to initialize Ecore Wayland.");
+ return NULL;
+ }
+
+ if (!(ee = calloc(1, sizeof(Ecore_Evas))))
+ {
+ ERR("Failed to allocate Ecore_Evas.");
+ ecore_wl_shutdown();
+ return NULL;
+ }
+
+ ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS);
+
+ _ecore_evas_wl_init();
+
+ ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_wl_engine_func;
+
+ ee->driver = "wayland_shm";
+ if (disp_name) ee->name = strdup(disp_name);
+
+ if (w < 1) w = 1;
+ if (h < 1) h = 1;
+
+ ee->req.x = ee->x = x;
+ ee->req.y = ee->y = y;
+ ee->req.w = ee->w = w;
+ ee->req.h = ee->h = h;
+ ee->rotation = 0;
+ ee->prop.max.w = ee->prop.max.h = 32767;
+ ee->prop.layer = 4;
+ ee->prop.request_pos = 0;
+ ee->prop.sticky = 0;
+ ee->prop.draw_frame = frame;
+ ee->prop.window = _win_id++;
+
+ ee->evas = evas_new();
+ evas_data_attach_set(ee->evas, ee);
+ evas_output_method_set(ee->evas, method);
+ evas_output_size_set(ee->evas, ee->w, ee->h);
+ evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+
+ if (ee->prop.draw_frame)
+ evas_output_framespace_set(ee->evas, 4, 18, 8, 22);
+
+ if ((einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas)))
+ {
+ einfo->info.rotation = ee->rotation;
+ einfo->info.debug = EINA_FALSE;
+ if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
+ {
+ ERR("Failed to set Evas Engine Info for '%s'.", ee->driver);
+ ecore_evas_free(ee);
+ return NULL;
+ }
+ }
+ else
+ {
+ ERR("Failed to get Evas Engine Info for '%s'.", ee->driver);
+ ecore_evas_free(ee);
+ return NULL;
+ }
+
+ /* NB: we need to be notified before 'free' so we can munmap the evas
+ * engine destination */
+ ecore_evas_callback_pre_free_set(ee, _ecore_evas_wl_pre_free);
+
+ ecore_evas_input_event_register(ee);
+ _ecore_evas_register(ee);
+
+ ecore_event_window_register(ee->prop.window, ee, ee->evas,
+ (Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
+ (Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
+ (Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
+ (Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
+
+ evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
+
+ return ee;
+}
+
+/* local functions */
+static int
+_ecore_evas_wl_init(void)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (++_ecore_evas_wl_init_count != 1)
+ return _ecore_evas_wl_init_count;
+
+ _ecore_evas_wl_event_handlers[0] =
+ ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
+ _ecore_evas_wl_event_mouse_down, NULL);
+ _ecore_evas_wl_event_handlers[1] =
+ ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
+ _ecore_evas_wl_event_mouse_up, NULL);
+ _ecore_evas_wl_event_handlers[2] =
+ ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
+ _ecore_evas_wl_event_mouse_move, NULL);
+ _ecore_evas_wl_event_handlers[3] =
+ ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL,
+ _ecore_evas_wl_event_mouse_wheel, NULL);
+ _ecore_evas_wl_event_handlers[4] =
+ ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_IN,
+ _ecore_evas_wl_event_mouse_in, NULL);
+ _ecore_evas_wl_event_handlers[5] =
+ ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_OUT,
+ _ecore_evas_wl_event_mouse_out, NULL);
+ _ecore_evas_wl_event_handlers[6] =
+ ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN,
+ _ecore_evas_wl_event_focus_in, NULL);
+ _ecore_evas_wl_event_handlers[7] =
+ ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT,
+ _ecore_evas_wl_event_focus_out, NULL);
+
+ ecore_event_evas_init();
+
+ return _ecore_evas_wl_init_count;
+}
+
+static int
+_ecore_evas_wl_shutdown(void)
+{
+ unsigned int i = 0;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (--_ecore_evas_wl_init_count != 0)
+ return _ecore_evas_wl_init_count;
+
+ for (i = 0; i < sizeof(_ecore_evas_wl_event_handlers) / sizeof(Ecore_Event_Handler *); i++)
+ {
+ if (_ecore_evas_wl_event_handlers[i])
+ ecore_event_handler_del(_ecore_evas_wl_event_handlers[i]);
+ }
+
+ ecore_event_evas_shutdown();
+
+ return _ecore_evas_wl_init_count;
+}
+
+static void
+_ecore_evas_wl_pre_free(Ecore_Evas *ee)
+{
+ Evas_Engine_Info_Wayland_Shm *einfo;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ /* get engine info */
+ einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
+ if ((einfo) && (einfo->info.dest))
+ {
+ int ret = 0;
+
+ /* munmap previous engine destination */
+ ret = munmap(einfo->info.dest, ((ee->w * sizeof(int)) * ee->h));
+ }
+}
+
+static void
+_ecore_evas_wl_free(Ecore_Evas *ee)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ /* destroy buffer */
+ if (ee->engine.wl.buffer) wl_buffer_destroy(ee->engine.wl.buffer);
+ ee->engine.wl.buffer = NULL;
+
+ /* destroy shell surface */
+ if (ee->engine.wl.shell_surface)
+ wl_shell_surface_destroy(ee->engine.wl.shell_surface);
+ ee->engine.wl.shell_surface = NULL;
+
+ /* destroy surface */
+ if (ee->engine.wl.surface) wl_surface_destroy(ee->engine.wl.surface);
+ ee->engine.wl.surface = NULL;
+
+ ecore_event_window_unregister(ee->prop.window);
+
+ _ecore_evas_wl_shutdown();
+ ecore_wl_shutdown();
+}
+
+static void
+_ecore_evas_wl_callback_resize_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!ee) return;
+ ee->func.fn_resize = func;
+}
+
+static void
+_ecore_evas_wl_callback_move_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!ee) return;
+ ee->func.fn_move = func;
+}
+
+static void
+_ecore_evas_wl_callback_delete_request_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!ee) return;
+ ee->func.fn_delete_request = func;
+}
+
+static void
+_ecore_evas_wl_callback_focus_in_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!ee) return;
+ ee->func.fn_focus_in = func;
+}
+
+static void
+_ecore_evas_wl_callback_focus_out_set(Ecore_Evas *ee, void (*func)(Ecore_Evas *ee))
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!ee) return;
+ ee->func.fn_focus_out = func;
+}
+
+static void
+_ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h)
+{
+ Evas_Engine_Info_Wayland_Shm *einfo;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!ee) return;
+ if (w < 1) w = 1;
+ if (h < 1) h = 1;
+ ee->req.w = w;
+ ee->req.h = h;
+ if ((ee->w == w) && (ee->h == h)) return;
+
+ /* get engine info */
+ einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
+ if (einfo->info.dest)
+ {
+ int ret = 0;
+
+ /* munmap previous engine destination */
+ ret = munmap(einfo->info.dest, ((ee->w * sizeof(int)) * ee->h));
+ }
+
+ /* free old buffer */
+ if (ee->engine.wl.buffer) wl_buffer_destroy(ee->engine.wl.buffer);
+ ee->engine.wl.buffer = NULL;
+
+ ee->w = w;
+ ee->h = h;
+
+ /* create buffer @ new size (also mmaps the new destination) */
+ _ecore_evas_wl_buffer_new(ee, &einfo->info.dest);
+
+ /* change evas output & viewport sizes */
+ evas_output_size_set(ee->evas, ee->w, ee->h);
+ evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h);
+
+ /* set new engine destination */
+ evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+
+ /* flush new buffer fd */
+ ecore_wl_flush();
+
+ /* damage buffer */
+ wl_buffer_damage(ee->engine.wl.buffer, 0, 0, ee->w, ee->h);
+
+ if (ee->visible)
+ {
+ /* if visible, attach to surface */
+ wl_surface_attach(ee->engine.wl.surface, ee->engine.wl.buffer, 0, 0);
+
+ /* damage surface */
+ wl_surface_damage(ee->engine.wl.surface, 0, 0, ee->w, ee->h);
+ }
+
+ if (ee->func.fn_resize) ee->func.fn_resize(ee);
+}
+
+static void
+_ecore_evas_wl_show(Ecore_Evas *ee)
+{
+ Evas_Engine_Info_Wayland_Shm *einfo;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!ee) return;
+ if (ee->visible) return;
+
+ /* get engine info */
+ einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
+
+ /* create new surface */
+ ee->engine.wl.surface =
+ wl_compositor_create_surface(ecore_wl_compositor_get());
+ wl_surface_set_user_data(ee->engine.wl.surface, (void *)ee->prop.window);
+
+ /* get new shell surface */
+ ee->engine.wl.shell_surface =
+ wl_shell_get_shell_surface(ecore_wl_shell_get(), ee->engine.wl.surface);
+
+ /* set toplevel */
+ wl_shell_surface_set_toplevel(ee->engine.wl.shell_surface);
+
+ /* create buffer @ new size (also mmaps the new destination) */
+ _ecore_evas_wl_buffer_new(ee, &einfo->info.dest);
+
+ /* set new engine destination */
+ evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
+
+ /* flush new buffer fd */
+ ecore_wl_flush();
+
+ /* attach buffer to surface */
+ wl_surface_attach(ee->engine.wl.surface, ee->engine.wl.buffer, 0, 0);
+
+ /* NB: No need to do a damage here. If we do, we end up w/ screen
+ * artifacts in the compositor */
+ /* wl_surface_damage(ee->engine.wl.surface, 0, 0, ee->w, ee->h); */
+
+ ee->visible = 1;
+ if (ee->func.fn_show) ee->func.fn_show(ee);
+}
+
+static int
+_ecore_evas_wl_render(Ecore_Evas *ee)
+{
+ int rend = 0;
+
+ if (!ee) return 0;
+ if (!ee->visible)
+ evas_norender(ee->evas);
+ else
+ {
+ Eina_List *ll = NULL, *updates = NULL;
+ Ecore_Evas *ee2 = NULL;
+
+ if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
+
+ EINA_LIST_FOREACH(ee->sub_ecore_evas, ll, ee2)
+ {
+ if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
+ if (ee2->engine.func->fn_render)
+ rend |= ee2->engine.func->fn_render(ee2);
+ if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
+ }
+
+ if ((updates = evas_render_updates(ee->evas)))
+ {
+ Eina_List *l = NULL;
+ Eina_Rectangle *r;
+
+ EINA_LIST_FOREACH(updates, l, r)
+ {
+ if (ee->engine.wl.buffer)
+ wl_buffer_damage(ee->engine.wl.buffer,
+ r->x, r->y, r->w, r->h);
+
+ if (ee->engine.wl.surface)
+ wl_surface_damage(ee->engine.wl.surface,
+ r->x, r->y, r->w, r->h);
+ }
+
+ evas_render_updates_free(updates);
+ _ecore_evas_idle_timeout_update(ee);
+ rend = 1;
+ }
+
+ if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
+ }
+
+ return rend;
+}
+
+static void
+_ecore_evas_wl_screen_geometry_get(const Ecore_Evas *ee __UNUSED__, int *x, int *y, int *w, int *h)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (x) *x = 0;
+ if (y) *y = 0;
+ ecore_wl_screen_size_get(w, h);
+}
+
+static Eina_Bool
+_ecore_evas_wl_event_mouse_down(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+ Ecore_Evas *ee;
+ Ecore_Event_Mouse_Button *ev;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ ev = event;
+ ee = ecore_event_window_match(ev->window);
+ if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
+ if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
+ /* printf("Mouse Down: %d %d\t%d %d\n", */
+ /* ev->x, ev->y, ev->root.x, ev->root.y); */
+ evas_event_feed_mouse_down(ee->evas, ev->buttons, ev->modifiers,
+ ev->timestamp, NULL);
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_ecore_evas_wl_event_mouse_up(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+ Ecore_Evas *ee;
+ Ecore_Event_Mouse_Button *ev;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ ev = event;
+ ee = ecore_event_window_match(ev->window);
+ if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
+ if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
+ evas_event_feed_mouse_up(ee->evas, ev->buttons, ev->modifiers,
+ ev->timestamp, NULL);
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_ecore_evas_wl_event_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+ Ecore_Evas *ee;
+ Ecore_Event_Mouse_Move *ev;
+
+ ev = event;
+ ee = ecore_event_window_match(ev->window);
+ if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
+ if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
+ ee->mouse.x = ev->x;
+ ee->mouse.y = ev->y;
+ evas_event_feed_mouse_move(ee->evas, ev->x, ev->y, ev->timestamp, NULL);
+ _ecore_evas_mouse_move_process(ee, ev->x, ev->y, ev->timestamp);
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_ecore_evas_wl_event_mouse_wheel(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+ Ecore_Evas *ee;
+ Ecore_Event_Mouse_Wheel *ev;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ ev = event;
+ ee = ecore_event_window_match(ev->window);
+ if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
+ if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
+ evas_event_feed_mouse_wheel(ee->evas, ev->direction, ev->z,
+ ev->timestamp, NULL);
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_ecore_evas_wl_event_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+ Ecore_Evas *ee;
+ Ecore_Wl_Event_Mouse_In *ev;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ ev = event;
+ ee = ecore_event_window_match(ev->window);
+ if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
+ if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
+ if (ee->func.fn_mouse_in) ee->func.fn_mouse_in(ee);
+ ecore_event_evas_modifier_lock_update(ee->evas, ev->modifiers);
+ evas_event_feed_mouse_in(ee->evas, ev->time, NULL);
+ _ecore_evas_mouse_move_process(ee, ev->x, ev->y, ev->time);
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_ecore_evas_wl_event_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+ Ecore_Evas *ee;
+ Ecore_Wl_Event_Mouse_Out *ev;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ ev = event;
+ ee = ecore_event_window_match(ev->window);
+ if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
+ if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
+ ecore_event_evas_modifier_lock_update(ee->evas, ev->modifiers);
+ _ecore_evas_mouse_move_process(ee, ev->x, ev->y, ev->time);
+ evas_event_feed_mouse_out(ee->evas, ev->time, NULL);
+ if (ee->func.fn_mouse_out) ee->func.fn_mouse_out(ee);
+ if (ee->prop.cursor.object) evas_object_hide(ee->prop.cursor.object);
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_ecore_evas_wl_event_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+ Ecore_Evas *ee;
+ Ecore_Wl_Event_Focus_In *ev;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ ev = event;
+ ee = ecore_event_window_match(ev->window);
+ if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
+ if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
+ ee->prop.focused = 1;
+ evas_focus_in(ee->evas);
+ if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static Eina_Bool
+_ecore_evas_wl_event_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event)
+{
+ Ecore_Evas *ee;
+ Ecore_Wl_Event_Focus_Out *ev;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ ev = event;
+ ee = ecore_event_window_match(ev->window);
+ if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
+ if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
+ evas_focus_out(ee->evas);
+ ee->prop.focused = 0;
+ if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
+ return ECORE_CALLBACK_PASS_ON;
+}
+
+static void
+_ecore_evas_wl_buffer_new(Ecore_Evas *ee, void **dest)
+{
+ static unsigned int format;
+ char tmp[PATH_MAX];
+ int fd = -1, stride = 0, size = 0;
+ void *ret;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (dest) *dest = NULL;
+
+ if (!format) format = ecore_wl_format_get();
+
+ strcpy(tmp, "/tmp/ecore-wayland_shm-XXXXXX");
+ if ((fd = mkstemp(tmp)) < 0)
+ {
+ ERR("Could not create temporary file.");
+ return;
+ }
+
+ stride = (ee->w * sizeof(int));
+ size = (stride * ee->h);
+ if (ftruncate(fd, size) < 0)
+ {
+ ERR("Could not truncate temporary file.");
+ close(fd);
+ return;
+ }
+
+ ret = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0);
+ unlink(tmp);
+
+ if (ret == MAP_FAILED)
+ {
+ ERR("mmap of temporary file failed.");
+ close(fd);
+ return;
+ }
+
+ if (dest) *dest = ret;
+
+ ee->engine.wl.buffer =
+ wl_shm_create_buffer(ecore_wl_shm_get(), fd, ee->w, ee->h, stride, format);
+
+ close(fd);
+}
+
+#else
+EAPI Ecore_Evas *
+ecore_evas_wayland_shm_new(const char *disp_name __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__, int frame __UNUSED__)
+{
+ return NULL;
+}
+#endif
--- /dev/null
+#ifndef _ECORE_WAYLAND_H_
+# define _ECORE_WAYLAND_H_
+
+# include <Eina.h>
+# include <wayland-client.h>
+
+# ifdef EAPI
+# undef EAPI
+# endif
+
+# ifdef __GNUC__
+# if __GNUC__ >= 4
+# define EAPI __attribute__ ((visibility("default")))
+# else
+# define EAPI
+# endif
+# else
+# define EAPI
+# endif
+
+typedef enum _Ecore_Wl_Window_Type Ecore_Wl_Window_Type;
+typedef struct _Ecore_Wl_Window Ecore_Wl_Window;
+typedef struct _Ecore_Wl_Event_Mouse_In Ecore_Wl_Event_Mouse_In;
+typedef struct _Ecore_Wl_Event_Mouse_Out Ecore_Wl_Event_Mouse_Out;
+typedef struct _Ecore_Wl_Event_Focus_In Ecore_Wl_Event_Focus_In;
+typedef struct _Ecore_Wl_Event_Focus_Out Ecore_Wl_Event_Focus_Out;
+
+enum _Ecore_Wl_Window_Type
+{
+ ECORE_WL_WINDOW_TYPE_SHM,
+ ECORE_WL_WINDOW_TYPE_EGL
+};
+
+struct _Ecore_Wl_Window
+{
+ int id;
+ int x, y, w, h;
+ Ecore_Wl_Window_Type type;
+ Eina_Bool synced : 1;
+
+ struct wl_surface *surface;
+ struct wl_shell_surface *shell_surface;
+
+ struct wl_callback *callback;
+};
+
+struct _Ecore_Wl_Event_Mouse_In
+{
+ int modifiers;
+ int x, y;
+
+ struct
+ {
+ int x, y;
+ } root;
+
+ unsigned int window;
+
+ unsigned int time;
+};
+
+struct _Ecore_Wl_Event_Mouse_Out
+{
+ int modifiers;
+ int x, y;
+
+ struct
+ {
+ int x, y;
+ } root;
+
+ unsigned int window;
+
+ unsigned int time;
+};
+
+struct _Ecore_Wl_Event_Focus_In
+{
+ unsigned int window;
+ /* TODO: mode & detail */
+ unsigned int time;
+};
+
+struct _Ecore_Wl_Event_Focus_Out
+{
+ unsigned int window;
+ /* TODO: mode & detail */
+ unsigned int time;
+};
+
+/**
+ * @file
+ * @brief Ecore functions for dealing with the Wayland window system
+ *
+ * Ecore_Wl provides a wrapper and convenience functions for using the
+ * Wayland window system. Function groups for this part of the library
+ * include the following:
+ * @li @ref Ecore_Wl_Init_Group
+ */
+
+EAPI int ecore_wl_init(const char *name);
+EAPI int ecore_wl_shutdown(void);
+
+EAPI struct wl_display *ecore_wl_display_get(void);
+EAPI struct wl_shm *ecore_wl_shm_get(void);
+EAPI struct wl_compositor *ecore_wl_compositor_get(void);
+EAPI struct wl_shell *ecore_wl_shell_get(void);
+EAPI struct wl_input_device *ecore_wl_input_device_get(void);
+EAPI void ecore_wl_screen_size_get(int *w, int *h);
+EAPI unsigned int ecore_wl_format_get(void);
+EAPI void ecore_wl_sync(void);
+EAPI void ecore_wl_flush(void);
+
+EAPI Ecore_Wl_Window *ecore_wl_window_new(Ecore_Wl_Window_Type type, int x, int y, int w, int h);
+EAPI void ecore_wl_window_free(Ecore_Wl_Window *win);
+EAPI void ecore_wl_window_move(Ecore_Wl_Window *win, int x, int y);
+EAPI void ecore_wl_window_resize(Ecore_Wl_Window *win, int w, int h);
+EAPI void ecore_wl_window_show(Ecore_Wl_Window *win);
+EAPI void ecore_wl_window_hide(Ecore_Wl_Window *win);
+EAPI void ecore_wl_window_raise(Ecore_Wl_Window *win);
+EAPI void ecore_wl_window_lower(Ecore_Wl_Window *win);
+EAPI void ecore_wl_window_activate(Ecore_Wl_Window *win);
+EAPI void ecore_wl_window_focus(Ecore_Wl_Window *win);
+EAPI void ecore_wl_window_fullscreen(Ecore_Wl_Window *win);
+EAPI void ecore_wl_window_attach(Ecore_Wl_Window *win, struct wl_buffer *buffer);
+EAPI void ecore_wl_window_damage(Ecore_Wl_Window *win, int x, int y, int w, int h);
+EAPI void ecore_wl_window_sync(Ecore_Wl_Window *win);
+
+EAPI extern int ECORE_WL_EVENT_MOUSE_IN;
+EAPI extern int ECORE_WL_EVENT_MOUSE_OUT;
+EAPI extern int ECORE_WL_EVENT_FOCUS_IN;
+EAPI extern int ECORE_WL_EVENT_FOCUS_OUT;
+
+#endif
--- /dev/null
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/ecore \
+-I$(top_srcdir)/src/lib/ecore_input \
+-I$(top_builddir)/src/lib/ecore \
+-I$(top_builddir)/src/lib/ecore_input \
+@WAYLAND_CFLAGS@ \
+@EVAS_CFLAGS@ \
+@EINA_CFLAGS@
+
+lib_LTLIBRARIES = libecore_wayland.la
+includes_HEADERS = Ecore_Wayland.h
+includesdir = $(includedir)/ecore-@VMAJ@
+
+libecore_wayland_la_SOURCES = \
+ecore_wl.c
+
+## ecore_wl_window.c
+
+libecore_wayland_la_LIBADD = \
+$(top_builddir)/src/lib/ecore/libecore.la \
+$(top_builddir)/src/lib/ecore_input/libecore_input.la \
+@WAYLAND_LIBS@ \
+@EVAS_LIBS@ \
+@EINA_LIBS@
+
+libecore_wayland_la_LDFLAGS = -version-info @version_info@ @release_info@
+libecore_wayland_la_DEPENDENCIES = $(top_builddir)/src/lib/ecore/libecore.la
+
+EXTRA_DIST = ecore_wl_private.h
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_Input.h"
+#include "ecore_wl_private.h"
+#include "Ecore_Wayland.h"
+
+/* FIXME: This gives BTN_LEFT/RIGHT/MIDDLE for linux systems ...
+ * What about other OSs ?? */
+#ifdef __linux__
+# include <linux/input.h>
+#else
+# define BTN_LEFT 0x110
+# define BTN_RIGHT 0x111
+# define BTN_MIDDLE 0x112
+# define BTN_SIDE 0x113
+# define BTN_EXTRA 0x114
+# define BTN_FORWARD 0x115
+# define BTN_BACK 0x116
+#endif
+
+#include <X11/extensions/XKBcommon.h>
+
+/* local function prototypes */
+static Eina_Bool _ecore_wl_shutdown(Eina_Bool close_display);
+static void _ecore_wl_cb_disp_handle_global(struct wl_display *disp, uint32_t id, const char *interface, uint32_t version __UNUSED__, void *data __UNUSED__);
+static int _ecore_wl_cb_disp_event_mask_update(uint32_t mask, void *data __UNUSED__);
+static void _ecore_wl_cb_shm_format_iterate(void *data __UNUSED__, struct wl_shm *shm __UNUSED__, uint32_t format);
+static void _ecore_wl_cb_disp_handle_geometry(void *data __UNUSED__, struct wl_output *output __UNUSED__, int x, int y, int pw __UNUSED__, int ph __UNUSED__, int subpixel __UNUSED__, const char *make __UNUSED__, const char *model __UNUSED__);
+static void _ecore_wl_cb_disp_handle_mode(void *data __UNUSED__, struct wl_output *output __UNUSED__, uint32_t flags, int w, int h, int refresh __UNUSED__);
+static Eina_Bool _ecore_wl_cb_fd_handle(void *data, Ecore_Fd_Handler *hdl __UNUSED__);
+static void _ecore_wl_cb_handle_motion(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t, int32_t x, int32_t y, int32_t sx, int32_t sy);
+static void _ecore_wl_cb_handle_button(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t, uint32_t btn, uint32_t state);
+static void _ecore_wl_cb_handle_key(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, uint32_t key, uint32_t state);
+static void _ecore_wl_cb_handle_pointer_focus(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, struct wl_surface *surface, int32_t x, int32_t y, int32_t sx, int32_t sy);
+static void _ecore_wl_cb_handle_keyboard_focus(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, struct wl_surface *surface, struct wl_array *keys);
+static void _ecore_wl_mouse_out_send(void);
+static void _ecore_wl_mouse_in_send(void);
+static void _ecore_wl_focus_out_send(void);
+static void _ecore_wl_focus_in_send(void);
+
+/* local variables */
+static int _ecore_wl_init_count = 0;
+static struct wl_display *_ecore_wl_disp = NULL;
+static uint32_t _ecore_wl_disp_mask = 0;
+static uint32_t _ecore_wl_disp_format = WL_SHM_FORMAT_PREMULTIPLIED_ARGB32;
+static Eina_Rectangle _ecore_wl_screen;
+static Ecore_Fd_Handler *_ecore_wl_fd_hdl = NULL;
+static int _ecore_wl_input_x = 0;
+static int _ecore_wl_input_y = 0;
+static int _ecore_wl_input_sx = 0;
+static int _ecore_wl_input_sy = 0;
+static int _ecore_wl_input_modifiers = 0;
+static struct xkb_desc *_ecore_wl_xkb;
+
+static struct wl_compositor *_ecore_wl_comp;
+static struct wl_shm *_ecore_wl_shm;
+static struct wl_shell *_ecore_wl_shell;
+static struct wl_output *_ecore_wl_output;
+static struct wl_input_device *_ecore_wl_input;
+static struct wl_surface *_ecore_wl_input_surface;
+static const struct wl_shm_listener _ecore_wl_shm_listener =
+{
+ _ecore_wl_cb_shm_format_iterate
+};
+static const struct wl_output_listener _ecore_wl_output_listener =
+{
+ _ecore_wl_cb_disp_handle_geometry,
+ _ecore_wl_cb_disp_handle_mode
+};
+static const struct wl_input_device_listener _ecore_wl_input_listener =
+{
+ _ecore_wl_cb_handle_motion,
+ _ecore_wl_cb_handle_button,
+ _ecore_wl_cb_handle_key,
+ _ecore_wl_cb_handle_pointer_focus,
+ _ecore_wl_cb_handle_keyboard_focus,
+ NULL, // touch down
+ NULL, // touch up
+ NULL, // touch motion
+ NULL, // touch frame
+ NULL, // touch cancel
+};
+
+/* external variables */
+int _ecore_wl_log_dom = -1;
+EAPI int ECORE_WL_EVENT_MOUSE_IN = 0;
+EAPI int ECORE_WL_EVENT_MOUSE_OUT = 0;
+EAPI int ECORE_WL_EVENT_FOCUS_IN = 0;
+EAPI int ECORE_WL_EVENT_FOCUS_OUT = 0;
+
+EAPI int
+ecore_wl_init(const char *name)
+{
+ struct xkb_rule_names xkb_names;
+ int fd = 0;
+
+ if (++_ecore_wl_init_count != 1)
+ return _ecore_wl_init_count;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!eina_init()) return --_ecore_wl_init_count;
+
+ _ecore_wl_log_dom =
+ eina_log_domain_register("ecore_wl", ECORE_WL_DEFAULT_LOG_COLOR);
+ if (_ecore_wl_log_dom < 0)
+ {
+ EINA_LOG_ERR("Cannot create a log domain for Ecore Wayland.");
+ eina_shutdown();
+ return --_ecore_wl_init_count;
+ }
+
+ if (!ecore_init())
+ {
+ eina_log_domain_unregister(_ecore_wl_log_dom);
+ _ecore_wl_log_dom = -1;
+ eina_shutdown();
+ return --_ecore_wl_init_count;
+ }
+
+ if (!ecore_event_init())
+ {
+ eina_log_domain_unregister(_ecore_wl_log_dom);
+ _ecore_wl_log_dom = -1;
+ ecore_shutdown();
+ eina_shutdown();
+ return --_ecore_wl_init_count;
+ }
+
+ if (!ECORE_WL_EVENT_MOUSE_IN)
+ {
+ ECORE_WL_EVENT_MOUSE_IN = ecore_event_type_new();
+ ECORE_WL_EVENT_MOUSE_OUT = ecore_event_type_new();
+ ECORE_WL_EVENT_FOCUS_IN = ecore_event_type_new();
+ ECORE_WL_EVENT_FOCUS_OUT = ecore_event_type_new();
+ }
+
+ /* init xkb */
+ /* FIXME: Somehow make this portable to other languages/countries */
+ xkb_names.rules = "evdev";
+ xkb_names.model = "evdev";
+ xkb_names.layout = "us";
+ xkb_names.variant = "";
+ xkb_names.options = "";
+ if (!(_ecore_wl_xkb = xkb_compile_keymap_from_rules(&xkb_names)))
+ {
+ ERR("Could not compile keymap");
+ eina_log_domain_unregister(_ecore_wl_log_dom);
+ _ecore_wl_log_dom = -1;
+ ecore_event_shutdown();
+ ecore_shutdown();
+ eina_shutdown();
+ return --_ecore_wl_init_count;
+ }
+
+ /* connect to the wayland display */
+ if (!(_ecore_wl_disp = wl_display_connect(name)))
+ {
+ eina_log_domain_unregister(_ecore_wl_log_dom);
+ _ecore_wl_log_dom = -1;
+ ecore_event_shutdown();
+ ecore_shutdown();
+ eina_shutdown();
+ return --_ecore_wl_init_count;
+ }
+
+ /* setup handler for wayland interfaces */
+ wl_display_add_global_listener(_ecore_wl_disp,
+ _ecore_wl_cb_disp_handle_global, NULL);
+
+ /* process connection events */
+ wl_display_iterate(_ecore_wl_disp, WL_DISPLAY_READABLE);
+
+ fd = wl_display_get_fd(_ecore_wl_disp,
+ _ecore_wl_cb_disp_event_mask_update, NULL);
+
+ /* NB: DO NOT TOUCH THIS OR YOU WILL PAY THE PRICE OF FAILURE !! */
+ /* Without a ECORE_FD_WRITE, then animators/timers break */
+ _ecore_wl_fd_hdl =
+ ecore_main_fd_handler_add(fd, ECORE_FD_READ | ECORE_FD_WRITE,
+ _ecore_wl_cb_fd_handle, _ecore_wl_disp,
+ NULL, NULL);
+ if (!_ecore_wl_fd_hdl)
+ {
+ wl_display_destroy(_ecore_wl_disp);
+ _ecore_wl_disp = NULL;
+ eina_log_domain_unregister(_ecore_wl_log_dom);
+ _ecore_wl_log_dom = -1;
+ ecore_event_shutdown();
+ ecore_shutdown();
+ eina_shutdown();
+ return --_ecore_wl_init_count;
+ }
+
+ return _ecore_wl_init_count;
+}
+
+EAPI int
+ecore_wl_shutdown(void)
+{
+ return _ecore_wl_shutdown(EINA_TRUE);
+}
+
+EAPI struct wl_display *
+ecore_wl_display_get(void)
+{
+ return _ecore_wl_disp;
+}
+
+EAPI struct wl_shm *
+ecore_wl_shm_get(void)
+{
+ return _ecore_wl_shm;
+}
+
+EAPI struct wl_compositor *
+ecore_wl_compositor_get(void)
+{
+ return _ecore_wl_comp;
+}
+
+EAPI struct wl_shell *
+ecore_wl_shell_get(void)
+{
+ return _ecore_wl_shell;
+}
+
+EAPI struct wl_input_device *
+ecore_wl_input_device_get(void)
+{
+ return _ecore_wl_input;
+}
+
+EAPI void
+ecore_wl_screen_size_get(int *w, int *h)
+{
+ if (w) *w = _ecore_wl_screen.w;
+ if (h) *h = _ecore_wl_screen.h;
+}
+
+EAPI unsigned int
+ecore_wl_format_get(void)
+{
+ return _ecore_wl_disp_format;
+}
+
+EAPI void
+ecore_wl_flush(void)
+{
+ wl_display_flush(_ecore_wl_disp);
+ /* if (_ecore_wl_disp_mask & WL_DISPLAY_WRITABLE) */
+ /* wl_display_iterate(_ecore_wl_disp, WL_DISPLAY_WRITABLE); */
+}
+
+EAPI void
+ecore_wl_sync(void)
+{
+ wl_display_iterate(_ecore_wl_disp, WL_DISPLAY_READABLE);
+}
+
+/* local functions */
+static Eina_Bool
+_ecore_wl_shutdown(Eina_Bool close_display)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (--_ecore_wl_init_count != 0)
+ return _ecore_wl_init_count;
+
+ if (!_ecore_wl_disp) return _ecore_wl_init_count;
+
+ if (_ecore_wl_xkb) free(_ecore_wl_xkb);
+
+ if (_ecore_wl_fd_hdl) ecore_main_fd_handler_del(_ecore_wl_fd_hdl);
+ _ecore_wl_fd_hdl = NULL;
+
+ if (close_display)
+ {
+ if (_ecore_wl_shm) wl_shm_destroy(_ecore_wl_shm);
+ if (_ecore_wl_comp) wl_compositor_destroy(_ecore_wl_comp);
+ if (_ecore_wl_disp) wl_display_destroy(_ecore_wl_disp);
+ _ecore_wl_disp = NULL;
+ }
+
+ eina_log_domain_unregister(_ecore_wl_log_dom);
+ _ecore_wl_log_dom = -1;
+
+ ecore_event_shutdown();
+ ecore_shutdown();
+ eina_shutdown();
+
+ return _ecore_wl_init_count;
+}
+
+static void
+_ecore_wl_cb_disp_handle_global(struct wl_display *disp, uint32_t id, const char *interface, uint32_t version __UNUSED__, void *data __UNUSED__)
+{
+// LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (disp != _ecore_wl_disp) return;
+ if (!strcmp(interface, "wl_compositor"))
+ {
+ _ecore_wl_comp =
+ wl_display_bind(_ecore_wl_disp, id, &wl_compositor_interface);
+ }
+ else if (!strcmp(interface, "wl_shm"))
+ {
+ _ecore_wl_shm =
+ wl_display_bind(_ecore_wl_disp, id, &wl_shm_interface);
+ wl_shm_add_listener(_ecore_wl_shm, &_ecore_wl_shm_listener, NULL);
+ }
+ else if (!strcmp(interface, "wl_output"))
+ {
+ _ecore_wl_output =
+ wl_display_bind(_ecore_wl_disp, id, &wl_output_interface);
+ wl_output_add_listener(_ecore_wl_output,
+ &_ecore_wl_output_listener, NULL);
+ }
+ else if (!strcmp(interface, "wl_shell"))
+ {
+ _ecore_wl_shell =
+ wl_display_bind(_ecore_wl_disp, id, &wl_shell_interface);
+ }
+ else if (!strcmp(interface, "wl_input_device"))
+ {
+ _ecore_wl_input =
+ wl_display_bind(_ecore_wl_disp, id, &wl_input_device_interface);
+ wl_input_device_add_listener(_ecore_wl_input,
+ &_ecore_wl_input_listener, NULL);
+ }
+}
+
+static int
+_ecore_wl_cb_disp_event_mask_update(uint32_t mask, void *data __UNUSED__)
+{
+// LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ _ecore_wl_disp_mask = mask;
+ return 0;
+}
+
+static void
+_ecore_wl_cb_shm_format_iterate(void *data __UNUSED__, struct wl_shm *shm __UNUSED__, uint32_t format)
+{
+// LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (_ecore_wl_disp_format < 2) return;
+ switch (format)
+ {
+ case WL_SHM_FORMAT_ARGB32:
+ /* NB: Ignore argb32. We prefer premul */
+ break;
+ case WL_SHM_FORMAT_PREMULTIPLIED_ARGB32:
+ _ecore_wl_disp_format = format;
+ break;
+ case WL_SHM_FORMAT_XRGB32:
+ _ecore_wl_disp_format = format;
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+_ecore_wl_cb_disp_handle_geometry(void *data __UNUSED__, struct wl_output *output __UNUSED__, int x, int y, int pw __UNUSED__, int ph __UNUSED__, int subpixel __UNUSED__, const char *make __UNUSED__, const char *model __UNUSED__)
+{
+ _ecore_wl_screen.x = x;
+ _ecore_wl_screen.y = y;
+}
+
+static void
+_ecore_wl_cb_disp_handle_mode(void *data __UNUSED__, struct wl_output *output __UNUSED__, uint32_t flags, int w, int h, int refresh __UNUSED__)
+{
+ if (flags & WL_OUTPUT_MODE_CURRENT)
+ {
+ _ecore_wl_screen.w = w;
+ _ecore_wl_screen.h = h;
+ }
+}
+
+static Eina_Bool
+_ecore_wl_cb_fd_handle(void *data, Ecore_Fd_Handler *hdl __UNUSED__)
+{
+ struct wl_display *disp;
+
+ if (!(disp = data)) return ECORE_CALLBACK_RENEW;
+ if (disp != _ecore_wl_disp) return ECORE_CALLBACK_RENEW;
+
+// LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ /* NB: This handles iterate for writable AND readable.
+ * DO NOT TOUCH THIS OR YOU WILL PAY THE PRICE OF FAILURE !!
+ * Without this, animators/timers die */
+ if (_ecore_wl_disp_mask & (WL_DISPLAY_READABLE | WL_DISPLAY_WRITABLE))
+ wl_display_roundtrip(_ecore_wl_disp);
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_ecore_wl_cb_handle_motion(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t, int32_t x, int32_t y, int32_t sx, int32_t sy)
+{
+ Ecore_Event_Mouse_Move *ev;
+
+ if (dev != _ecore_wl_input) return;
+ if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Move)))) return;
+
+ _ecore_wl_input_x = x;
+ _ecore_wl_input_y = y;
+ _ecore_wl_input_sx = sx;
+ _ecore_wl_input_sy = sy;
+
+ ev->timestamp = t;
+ ev->x = sx;
+ ev->y = sy;
+ ev->root.x = x;
+ ev->root.y = y;
+
+ if (_ecore_wl_input_surface)
+ {
+ unsigned int id = 0;
+
+ if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
+ {
+ ev->window = id;
+ ev->event_window = id;
+ }
+ }
+
+ ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
+}
+
+static void
+_ecore_wl_cb_handle_button(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t, uint32_t btn, uint32_t state)
+{
+ if (dev != _ecore_wl_input) return;
+
+ if ((btn >= BTN_SIDE) && (btn <= BTN_BACK))
+ {
+ Ecore_Event_Mouse_Wheel *ev;
+
+ if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Wheel)))) return;
+
+ ev->timestamp = t;
+ ev->x = _ecore_wl_input_sx;
+ ev->y = _ecore_wl_input_sy;
+ ev->root.x = _ecore_wl_input_x;
+ ev->root.y = _ecore_wl_input_y;
+ ev->modifiers = _ecore_wl_input_modifiers;
+ ev->direction = 0;
+
+ if (_ecore_wl_input_surface)
+ {
+ unsigned int id = 0;
+
+ if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
+ {
+ ev->window = id;
+ ev->event_window = id;
+ }
+ }
+
+ /* NB: (FIXME) Currently Wayland provides no measure of how much the
+ * wheel has scrolled (read: delta of movement). So for now, we will
+ * just assume that the amount scrolled is 1 */
+ if ((btn == BTN_EXTRA) || (btn == BTN_FORWARD)) // down
+ ev->z = 1;
+ else if ((btn == BTN_SIDE) || (btn == BTN_BACK)) // up
+ ev->z = -1;
+
+ ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
+ }
+ else
+ {
+ Ecore_Event_Mouse_Button *ev;
+
+ if (!(ev = malloc(sizeof(Ecore_Event_Mouse_Button)))) return;
+
+ if (btn == BTN_LEFT)
+ ev->buttons = 1;
+ else if (btn == BTN_MIDDLE)
+ ev->buttons = 2;
+ else if (btn == BTN_RIGHT)
+ ev->buttons = 3;
+
+ ev->timestamp = t;
+ ev->x = _ecore_wl_input_sx;
+ ev->y = _ecore_wl_input_sy;
+ ev->root.x = _ecore_wl_input_x;
+ ev->root.y = _ecore_wl_input_y;
+ ev->modifiers = _ecore_wl_input_modifiers;
+
+ if (_ecore_wl_input_surface)
+ {
+ unsigned int id = 0;
+
+ if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
+ {
+ ev->window = id;
+ ev->event_window = id;
+ }
+ }
+
+ if (state)
+ ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
+ else
+ ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
+ }
+}
+
+static void
+_ecore_wl_cb_handle_key(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, uint32_t key, uint32_t state)
+{
+ unsigned int keycode = 0;
+
+ if (dev != _ecore_wl_input) return;
+
+ keycode = key + _ecore_wl_xkb->min_key_code;
+
+ if (state)
+ _ecore_wl_input_modifiers |= _ecore_wl_xkb->map->modmap[keycode];
+ else
+ _ecore_wl_input_modifiers &= ~_ecore_wl_xkb->map->modmap[keycode];
+}
+
+static void
+_ecore_wl_cb_handle_pointer_focus(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, struct wl_surface *surface, int32_t x, int32_t y, int32_t sx, int32_t sy)
+{
+ if (dev != _ecore_wl_input) return;
+
+ _ecore_wl_input_x = x;
+ _ecore_wl_input_y = y;
+ _ecore_wl_input_sx = sx;
+ _ecore_wl_input_sy = sy;
+
+ if (surface)
+ {
+ if (_ecore_wl_input_surface)
+ {
+ if (_ecore_wl_input_surface != surface)
+ {
+ /* NB: Pointer focus in different window. Send mouse & focus
+ * out events for previous window */
+ _ecore_wl_mouse_out_send();
+ _ecore_wl_focus_out_send();
+
+ /* NB: Send mouse & focus in events for new window */
+ _ecore_wl_input_surface = surface;
+ _ecore_wl_mouse_in_send();
+ _ecore_wl_focus_in_send();
+ }
+ }
+ else
+ {
+ _ecore_wl_input_surface = surface;
+ _ecore_wl_mouse_in_send();
+ _ecore_wl_focus_in_send();
+ /* printf("\tPointer Focus In New Window\n"); */
+ }
+ }
+ else
+ {
+ if (_ecore_wl_input_surface)
+ {
+ _ecore_wl_mouse_out_send();
+ _ecore_wl_focus_out_send();
+ /* printf("\tPointer Focus Not On a Window\n"); */
+ }
+ else
+ printf("\tUnhandled Pointer Focus Case !!!\n");
+ _ecore_wl_input_surface = NULL;
+ }
+}
+
+static void
+_ecore_wl_cb_handle_keyboard_focus(void *data __UNUSED__, struct wl_input_device *dev, uint32_t t __UNUSED__, struct wl_surface *surface, struct wl_array *keys)
+{
+ unsigned int *keyend = 0, *i = 0;
+
+ if (dev != _ecore_wl_input) return;
+
+ if ((surface) && (surface != _ecore_wl_input_surface))
+ _ecore_wl_input_surface = surface;
+ else if (!surface)
+ _ecore_wl_input_surface = NULL;
+
+ keyend = keys->data + keys->size;
+ _ecore_wl_input_modifiers = 0;
+ for (i = keys->data; i < keyend; i++)
+ _ecore_wl_input_modifiers |= _ecore_wl_xkb->map->modmap[*i];
+}
+
+static void
+_ecore_wl_mouse_out_send(void)
+{
+ Ecore_Wl_Event_Mouse_Out *ev;
+
+ if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Mouse_Out)))) return;
+
+ ev->x = _ecore_wl_input_sx;
+ ev->y = _ecore_wl_input_sy;
+ ev->root.x = _ecore_wl_input_x;
+ ev->root.y = _ecore_wl_input_y;
+ ev->modifiers = _ecore_wl_input_modifiers;
+ ev->time = ecore_time_get();
+
+ if (_ecore_wl_input_surface)
+ {
+ unsigned int id = 0;
+
+ if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
+ ev->window = id;
+ }
+
+ ecore_event_add(ECORE_WL_EVENT_MOUSE_OUT, ev, NULL, NULL);
+}
+
+static void
+_ecore_wl_mouse_in_send(void)
+{
+ Ecore_Wl_Event_Mouse_In *ev;
+
+ if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Mouse_In)))) return;
+
+ ev->x = _ecore_wl_input_sx;
+ ev->y = _ecore_wl_input_sy;
+ ev->root.x = _ecore_wl_input_x;
+ ev->root.y = _ecore_wl_input_y;
+ ev->modifiers = _ecore_wl_input_modifiers;
+ ev->time = ecore_time_get();
+
+ if (_ecore_wl_input_surface)
+ {
+ unsigned int id = 0;
+
+ if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
+ ev->window = id;
+ }
+
+ ecore_event_add(ECORE_WL_EVENT_MOUSE_IN, ev, NULL, NULL);
+}
+
+static void
+_ecore_wl_focus_out_send(void)
+{
+ Ecore_Wl_Event_Focus_Out *ev;
+
+ if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Focus_Out)))) return;
+ ev->time = ecore_time_get();
+ if (_ecore_wl_input_surface)
+ {
+ unsigned int id = 0;
+
+ if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
+ ev->window = id;
+ }
+ ecore_event_add(ECORE_WL_EVENT_FOCUS_OUT, ev, NULL, NULL);
+}
+
+static void
+_ecore_wl_focus_in_send(void)
+{
+ Ecore_Wl_Event_Focus_In *ev;
+
+ if (!(ev = calloc(1, sizeof(Ecore_Wl_Event_Focus_In)))) return;
+ ev->time = ecore_time_get();
+ if (_ecore_wl_input_surface)
+ {
+ unsigned int id = 0;
+
+ if ((id = (unsigned int)wl_surface_get_user_data(_ecore_wl_input_surface)))
+ ev->window = id;
+ }
+ ecore_event_add(ECORE_WL_EVENT_FOCUS_IN, ev, NULL, NULL);
+}
--- /dev/null
+#ifndef _ECORE_WAYLAND_PRIVATE_H
+# define _ECORE_WAYLAND_PRIVATE_H
+
+# include <limits.h>
+
+# define LOGFNS 1
+
+# ifdef LOGFNS
+# include <stdio.h>
+# define LOGFN(fl, ln, fn) printf("-ECORE-WL: %25s: %5i - %s\n", fl, ln, fn);
+# else
+# define LOGFN(fl, ln, fn)
+# endif
+
+extern int _ecore_wl_log_dom;
+
+# ifdef ECORE_WL_DEFAULT_LOG_COLOR
+# undef ECORE_WL_DEFAULT_LOG_COLOR
+# endif
+# define ECORE_WL_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
+
+# ifdef ERR
+# undef ERR
+# endif
+# define ERR(...) EINA_LOG_DOM_ERR(_ecore_wl_log_dom, __VA_ARGS__)
+
+# ifdef DBG
+# undef DBG
+# endif
+# define DBG(...) EINA_LOG_DOM_DBG(_ecore_wl_log_dom, __VA_ARGS__)
+
+# ifdef INF
+# undef INF
+# endif
+# define INF(...) EINA_LOG_DOM_INFO(_ecore_wl_log_dom, __VA_ARGS__)
+
+# ifdef WRN
+# undef WRN
+# endif
+# define WRN(...) EINA_LOG_DOM_WARN(_ecore_wl_log_dom, __VA_ARGS__)
+
+# ifdef CRIT
+# undef CRIT
+# endif
+# define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_wl_log_dom, __VA_ARGS__)
+
+#endif
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "Ecore.h"
+#include "ecore_private.h"
+#include "Ecore_Wayland.h"
+#include "ecore_wl_private.h"
+
+/* local function prototypes */
+static void _ecore_wl_window_cb_frame(void *data, struct wl_callback *cb __UNUSED__, uint32_t tm __UNUSED__);
+
+/* local variables */
+static const struct wl_callback_listener _ecore_wl_window_frame_listener =
+{
+ _ecore_wl_window_cb_frame
+};
+
+EAPI Ecore_Wl_Window *
+ecore_wl_window_new(Ecore_Wl_Window_Type type, int x, int y, int w, int h)
+{
+ static int _win_id = 1;
+ Ecore_Wl_Window *win;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!(win = calloc(1, sizeof(Ecore_Wl_Window)))) return NULL;
+
+ win->id = _win_id++;
+ printf("Ecore_Wl Window Id: %d\n", win->id);
+ win->x = x;
+ win->y = y;
+ win->w = w;
+ win->h = h;
+ win->synced = EINA_TRUE;
+ win->type = type;
+
+ return win;
+}
+
+EAPI void
+ecore_wl_window_free(Ecore_Wl_Window *win)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+// ecore_wl_window_hide(win);
+ free(win);
+}
+
+EAPI void
+ecore_wl_window_move(Ecore_Wl_Window *win, int x, int y)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+ if ((win->x == x) && (win->y == y)) return;
+ win->x = x;
+ win->y = y;
+}
+
+EAPI void
+ecore_wl_window_resize(Ecore_Wl_Window *win, int w, int h)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+ if ((win->w == w) && (win->h == h)) return;
+ win->w = w;
+ win->h = h;
+}
+
+EAPI void
+ecore_wl_window_show(Ecore_Wl_Window *win)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+
+ win->surface = wl_compositor_create_surface(ecore_wl_compositor_get());
+
+ win->shell_surface =
+ wl_shell_get_shell_surface(ecore_wl_shell_get(), win->surface);
+ wl_shell_surface_set_toplevel(win->shell_surface);
+}
+
+EAPI void
+ecore_wl_window_hide(Ecore_Wl_Window *win)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+ if (win->callback) wl_callback_destroy(win->callback);
+ if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface);
+ if (win->surface) wl_surface_destroy(win->surface);
+}
+
+EAPI void
+ecore_wl_window_raise(Ecore_Wl_Window *win)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+ if (!win->shell_surface) return;
+ wl_shell_surface_set_toplevel(win->shell_surface);
+}
+
+EAPI void
+ecore_wl_window_lower(Ecore_Wl_Window *win)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+}
+
+EAPI void
+ecore_wl_window_activate(Ecore_Wl_Window *win)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+ if (!win->shell_surface) return;
+ wl_shell_surface_set_toplevel(win->shell_surface);
+}
+
+EAPI void
+ecore_wl_window_focus(Ecore_Wl_Window *win)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+ if (!win->shell_surface) return;
+ wl_shell_surface_set_toplevel(win->shell_surface);
+}
+
+EAPI void
+ecore_wl_window_fullscreen(Ecore_Wl_Window *win)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+ if (!win->shell_surface) return;
+ wl_shell_surface_set_fullscreen(win->shell_surface);
+}
+
+EAPI void
+ecore_wl_window_attach(Ecore_Wl_Window *win, struct wl_buffer *buffer)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+ if ((win->surface) && (buffer))
+ wl_surface_attach(win->surface, buffer, 0, 0);
+}
+
+EAPI void
+ecore_wl_window_damage(Ecore_Wl_Window *win, int x, int y, int w, int h)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+ if (!win->surface) return;
+ if (win->synced)
+ {
+ if (win->callback) wl_callback_destroy(win->callback);
+ win->callback = wl_surface_frame(win->surface);
+ wl_callback_add_listener(win->callback,
+ &_ecore_wl_window_frame_listener, win);
+ win->synced = EINA_FALSE;
+ }
+ wl_surface_damage(win->surface, x, y, w, h);
+}
+
+EAPI void
+ecore_wl_window_sync(Ecore_Wl_Window *win)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!win) return;
+ ecore_wl_flush();
+ while (!win->synced)
+ ecore_wl_sync();
+}
+
+/* local functions */
+static void
+_ecore_wl_window_cb_frame(void *data, struct wl_callback *cb __UNUSED__, uint32_t tm __UNUSED__)
+{
+ Ecore_Wl_Window *win;
+
+ if (!(win = data)) return;
+ win->synced = EINA_TRUE;
+ if (win->callback) wl_callback_destroy(win->callback);
+ win->callback = NULL;
+ wl_surface_damage(win->surface, 0, 0, win->w, win->h);
+}