diff --git a/src/Makefile_Ecore_Wayland.am b/src/Makefile_Ecore_Wayland.am index 0709d6b545..2e71df1a0b 100644 --- a/src/Makefile_Ecore_Wayland.am +++ b/src/Makefile_Ecore_Wayland.am @@ -14,6 +14,7 @@ lib/ecore_wayland/ecore_wl_dnd.c \ lib/ecore_wayland/ecore_wl_input.c \ lib/ecore_wayland/ecore_wl_output.c \ lib/ecore_wayland/ecore_wl_window.c \ +lib/ecore_wayland/ecore_wl_subsurf.c \ lib/ecore_wayland/ecore_wl_private.h lib_ecore_wayland_libecore_wayland_la_BUILT_SOURCES = \ diff --git a/src/lib/ecore_wayland/Ecore_Wayland.h b/src/lib/ecore_wayland/Ecore_Wayland.h index c9b3e1f6ca..30545b7343 100644 --- a/src/lib/ecore_wayland/Ecore_Wayland.h +++ b/src/lib/ecore_wayland/Ecore_Wayland.h @@ -12,7 +12,6 @@ # include # include # include -# include # ifdef EAPI # undef EAPI @@ -36,6 +35,7 @@ typedef struct _Ecore_Wl_Display Ecore_Wl_Display; typedef struct _Ecore_Wl_Output Ecore_Wl_Output; typedef struct _Ecore_Wl_Input Ecore_Wl_Input; typedef struct _Ecore_Wl_Global Ecore_Wl_Global; /** @since 1.7.6 */ +typedef struct _Ecore_Wl_Subsurf Ecore_Wl_Subsurf; /** @since 1.8 */ # ifndef _ECORE_WAYLAND_WINDOW_PREDEF typedef struct _Ecore_Wl_Window Ecore_Wl_Window; @@ -253,6 +253,8 @@ struct _Ecore_Wl_Window /* FIXME: Ideally we should record the cursor name for this window * so we can compare and avoid unnecessary cursor set calls to wayland */ + Ecore_Wl_Subsurf *subsurfs; + void *data; }; @@ -383,6 +385,7 @@ struct _Ecore_Wl_Event_Interfaces_Bound * @li @ref Ecore_Wl_Window_Group * @li @ref Ecore_Wl_Input_Group * @li @ref Ecore_Wl_Dnd_Group + * @li @ref Ecore_Wl_Subsurf */ EAPI extern int ECORE_WL_EVENT_MOUSE_IN; @@ -866,6 +869,93 @@ EAPI struct wl_array *ecore_wl_dnd_drag_types_get(Ecore_Wl_Input *input); EAPI void ecore_wl_server_mode_set(Eina_Bool on); +/** + * @defgroup Ecore_Wl_Subsurf Functions to manipulate subsurfaces. + * @ingroup Ecore_Wl_Group + * + * Functions to manipulate wayland subsurfaces, using Ecore_Wl_Subsurf. + * + * This API is intended to expose Wayland subsurface functionality, although it + * should not be necessary for most applications to use it, as soon as we have + * means to make Evas automatically switch Evas images to use subsurfaces. + * + * It can/should be used, for instance, when subsurfaces are needed to be not + * in sync with the main window surface. + */ + +/** + * Create and return a new subsurface. + * + * Create a new surface (and subsurface interface), with the parent surface + * being the one associated with the given @param win. + * + * The @param win must be visible, otherwise there will be no surface created + * for it yet. + * + * @ingroup Ecore_Wl_Subsurf + * @since 1.8 + */ +EAPI Ecore_Wl_Subsurf *ecore_wl_subsurf_create(Ecore_Wl_Window *win); + +/** + * Destroy the given subsurface, as well as the surface associated with it. + * + * @ingroup Ecore_Wl_Subsurf + * @since 1.8 + */ +EAPI void ecore_wl_subsurf_del(Ecore_Wl_Subsurf *ess); + +/** + * Return the wl_surface associated with this subsurface. + * + * @ingroup Ecore_Wl_Subsurf + * @since 1.8 + */ +EAPI struct wl_surface *ecore_wl_subsurf_surface_get(Ecore_Wl_Subsurf *ess); + +/** + * Set the position of this subsurface, relative to its parent surface. + * + * @ingroup Ecore_Wl_Subsurf + * @since 1.8 + */ +EAPI void ecore_wl_subsurf_position_set(Ecore_Wl_Subsurf *ess, int x, int y); + +/** + * Get the position of this subsurface, relative to its parent surface. + * + * @ingroup Ecore_Wl_Subsurf + * @since 1.8 + */ +EAPI void ecore_wl_subsurf_position_get(Ecore_Wl_Subsurf *ess, int *x, int *y); + +/** + * @ingroup Ecore_Wl_Subsurf + * @since 1.8 + */ +EAPI void ecore_wl_subsurf_place_above(Ecore_Wl_Subsurf *ess, struct wl_surface *surface); + +/** + * @ingroup Ecore_Wl_Subsurf + * @since 1.8 + */ +EAPI void ecore_wl_subsurf_place_below(Ecore_Wl_Subsurf *ess, struct wl_surface *surface); + +/** + * @ingroup Ecore_Wl_Subsurf + * @since 1.8 + */ +EAPI void ecore_wl_subsurf_sync_set(Ecore_Wl_Subsurf *ess, Eina_Bool val); + +/** + * Set an opaque region for the given subsurface. + * + * Use a 0x0 region size to unset the opaque region. + * + * @ingroup Ecore_Wl_Subsurf + * @since 1.8 + */ +EAPI void ecore_wl_subsurf_opaque_region_set(Ecore_Wl_Subsurf *ess, int x, int y, int w, int h); #ifdef __cplusplus } #endif diff --git a/src/lib/ecore_wayland/ecore_wl.c b/src/lib/ecore_wayland/ecore_wl.c index acc5988af9..ee614e0e4b 100644 --- a/src/lib/ecore_wayland/ecore_wl.c +++ b/src/lib/ecore_wayland/ecore_wl.c @@ -4,6 +4,7 @@ #include #include "ecore_wl_private.h" +#include /* local function prototypes */ static Eina_Bool _ecore_wl_shutdown(Eina_Bool close); @@ -398,7 +399,7 @@ _ecore_wl_shutdown(Eina_Bool close) if (_ecore_wl_disp->wl.compositor) wl_compositor_destroy(_ecore_wl_disp->wl.compositor); if (_ecore_wl_disp->wl.subcompositor) - wl_compositor_destroy(_ecore_wl_disp->wl.subcompositor); + wl_subcompositor_destroy(_ecore_wl_disp->wl.subcompositor); if (_ecore_wl_disp->wl.display) { wl_registry_destroy(_ecore_wl_disp->wl.registry); diff --git a/src/lib/ecore_wayland/ecore_wl_private.h b/src/lib/ecore_wayland/ecore_wl_private.h index dc034af8d8..b83aae38eb 100644 --- a/src/lib/ecore_wayland/ecore_wl_private.h +++ b/src/lib/ecore_wayland/ecore_wl_private.h @@ -95,4 +95,6 @@ void _ecore_wl_dnd_del(Ecore_Wl_Dnd_Source *source); void _ecore_wl_events_init(void); void _ecore_wl_events_shutdown(void); +void _ecore_wl_subsurfs_del_all(Ecore_Wl_Window *win); + #endif diff --git a/src/lib/ecore_wayland/ecore_wl_subsurf.c b/src/lib/ecore_wayland/ecore_wl_subsurf.c new file mode 100644 index 0000000000..4e144fa084 --- /dev/null +++ b/src/lib/ecore_wayland/ecore_wl_subsurf.c @@ -0,0 +1,191 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "ecore_wl_private.h" +#include + +struct _Ecore_Wl_Subsurf +{ + EINA_INLIST; + Ecore_Wl_Window *parent_win; + struct wl_surface *surface; + struct wl_subsurface *subsurface; + + int x, y; + + Eina_Bool sync : 1; +}; + +EAPI Ecore_Wl_Subsurf * +ecore_wl_subsurf_create(Ecore_Wl_Window *win) +{ + struct wl_subsurface *subsurface; + struct wl_surface *surface; + Ecore_Wl_Subsurf *ess; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return NULL; + if (!win->surface) return NULL; + if (!_ecore_wl_disp->wl.subcompositor) return NULL; + + surface = wl_compositor_create_surface(_ecore_wl_disp->wl.compositor); + if (!surface) + return NULL; + + subsurface = wl_subcompositor_get_subsurface + (_ecore_wl_disp->wl.subcompositor, surface, win->surface); + if (!subsurface) + { + wl_surface_destroy(surface); + return NULL; + } + + ess = calloc(1, sizeof(*ess)); + ess->surface = surface; + ess->subsurface = subsurface; + ess->parent_win = win; + + win->subsurfs = (Ecore_Wl_Subsurf *)eina_inlist_append + (EINA_INLIST_GET(win->subsurfs), EINA_INLIST_GET(ess)); + + return ess; +} + +static void +_ecore_wl_subsurf_destroy(Ecore_Wl_Subsurf *ess) +{ + Ecore_Wl_Window *parent; + + wl_subsurface_destroy(ess->subsurface); + wl_surface_destroy(ess->surface); + + parent = ess->parent_win; + parent->subsurfs = (Ecore_Wl_Subsurf *)eina_inlist_remove + (EINA_INLIST_GET(parent->subsurfs), EINA_INLIST_GET(ess)); + + free(ess); +} + +EAPI void +ecore_wl_subsurf_del(Ecore_Wl_Subsurf *ess) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ess) return; + + _ecore_wl_subsurf_destroy(ess); +} + +void +_ecore_wl_subsurfs_del_all(Ecore_Wl_Window *win) +{ + Ecore_Wl_Subsurf *ess; + + if (!win) return; + + EINA_INLIST_FREE(win->subsurfs, ess) + { + _ecore_wl_subsurf_destroy(ess); + } +} + +EAPI struct wl_surface * +ecore_wl_subsurf_surface_get(Ecore_Wl_Subsurf *ess) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ess) return NULL; + + return ess->surface; +} + +EAPI void +ecore_wl_subsurf_position_set(Ecore_Wl_Subsurf *ess, int x, int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ess) return; + + if ((x == ess->x) && (y == ess->y)) + return; + + ess->x = x; + ess->y = y; + + wl_subsurface_set_position(ess->subsurface, x, y); +} + +EAPI void +ecore_wl_subsurf_position_get(Ecore_Wl_Subsurf *ess, int *x, int *y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ess) return; + + if (x) *x = ess->x; + if (y) *y = ess->y; +} + +EAPI void +ecore_wl_subsurf_place_above(Ecore_Wl_Subsurf *ess, struct wl_surface *surface) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ess) return; + if (!surface) return; + + wl_subsurface_place_above(ess->subsurface, surface); +} + +EAPI void +ecore_wl_subsurf_place_below(Ecore_Wl_Subsurf *ess, struct wl_surface *surface) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ess) return; + if (!surface) return; + + wl_subsurface_place_below(ess->subsurface, surface); +} + +EAPI void +ecore_wl_subsurf_sync_set(Ecore_Wl_Subsurf *ess, Eina_Bool val) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ess) return; + + val = !!val; + if (val == ess->sync) return; + + ess->sync = val; + + if (ess->sync) + wl_subsurface_set_sync(ess->subsurface); + else + wl_subsurface_set_desync(ess->subsurface); +} + +EAPI void +ecore_wl_subsurf_opaque_region_set(Ecore_Wl_Subsurf *ess, int x, int y, int w, int h) +{ + Ecore_Wl_Window *parent; + struct wl_region *region = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ess) return; + + if ((w > 0) && (h > 0)) + { + parent = ess->parent_win; + region = wl_compositor_create_region(parent->display->wl.compositor); + wl_region_add(region, x, y, w, h); + wl_surface_set_opaque_region(ess->surface, region); + wl_region_destroy(region); + } + else + wl_surface_set_opaque_region(ess->surface, NULL); +} diff --git a/src/lib/ecore_wayland/ecore_wl_window.c b/src/lib/ecore_wayland/ecore_wl_window.c index cd5aabe7ad..4ec78c8460 100644 --- a/src/lib/ecore_wayland/ecore_wl_window.c +++ b/src/lib/ecore_wayland/ecore_wl_window.c @@ -114,6 +114,8 @@ ecore_wl_window_free(Ecore_Wl_Window *win) if (win->anim_callback) wl_callback_destroy(win->anim_callback); win->anim_callback = NULL; + if (win->subsurfs) _ecore_wl_subsurfs_del_all(win); + if (win->shell_surface) wl_shell_surface_destroy(win->shell_surface); win->shell_surface = NULL; if (win->surface) wl_surface_destroy(win->surface);