wayland: implement session recovery

add support for reconnecting wayland applications if the compositor dies

disconnect -> destroy gl ctx + image textures -> block rendering ->
reconnect -> create gl ctx -> create image textures -> unblock rendering ->
sprinkle special seasoning on top -> just like ma used to make

 #SamsungFeatures

@feature
This commit is contained in:
Mike Blumenkrantz 2016-05-05 10:45:59 -04:00
parent 0231800b60
commit 9d5caf00b6
14 changed files with 393 additions and 241 deletions

View File

@ -3331,7 +3331,7 @@ EFL_INTERNAL_DEPEND_PKG([ECORE_WL2], [efl])
EFL_INTERNAL_DEPEND_PKG([ECORE_WL2], [eina])
EFL_DEPEND_PKG([ECORE_WL2], [WAYLAND],
[wayland-server >= 1.10.0 wayland-client >= 1.10.0 wayland-cursor >= 1.10.0 xkbcommon >= 0.5.0 uuid])
[wayland-server >= 1.10.0 wayland-client >= 1.10.0 wayland-cursor >= 1.10.0 xkbcommon >= 0.5.0])
EFL_EVAL_PKGS([ECORE_WL2])

View File

@ -8,8 +8,8 @@ installed_ecorewl2mainheadersdir = $(includedir)/ecore-wl2-@VMAJ@
dist_installed_ecorewl2mainheaders_DATA = lib/ecore_wl2/Ecore_Wl2.h
lib_ecore_wl2_libecore_wl2_la_SOURCES = \
lib/ecore_wl2/session-recovery-client-protocol.h \
lib/ecore_wl2/session-recovery-protocol.c \
lib/ecore_wl2/session-recovery.h \
lib/ecore_wl2/session-recovery.c \
lib/ecore_wl2/subsurface-client-protocol.h \
lib/ecore_wl2/subsurface-protocol.c \
lib/ecore_wl2/xdg-shell-client-protocol.h \

View File

@ -53,6 +53,13 @@ typedef enum
ECORE_WL2_DRAG_ACTION_ASK = 4,
} Ecore_Wl2_Drag_Action;
struct _Ecore_Wl2_Event_Connection
{
Ecore_Wl2_Display *display;
};
typedef struct _Ecore_Wl2_Event_Connection Ecore_Wl2_Event_Connect;
typedef struct _Ecore_Wl2_Event_Connection Ecore_Wl2_Event_Disconnect;
typedef struct _Ecore_Wl2_Global
{
Eina_Stringshare *interface;
@ -175,6 +182,8 @@ typedef enum _Ecore_Wl2_Window_Type
typedef void (*Ecore_Wl2_Bind_Cb)(struct wl_client *client, void *data, uint32_t version, uint32_t id);
typedef void (*Ecore_Wl2_Unbind_Cb)(struct wl_resource *resource);
EAPI extern int ECORE_WL2_EVENT_DISCONNECT; /** @since 1.18 */
EAPI extern int ECORE_WL2_EVENT_CONNECT; /** @since 1.18 */
EAPI extern int ECORE_WL2_EVENT_GLOBAL_ADDED; /** @since 1.17 */
EAPI extern int ECORE_WL2_EVENT_GLOBAL_REMOVED; /** @since 1.17 */
EAPI extern int ECORE_WL2_EVENT_FOCUS_IN; /** @since 1.17 */

View File

@ -8,9 +8,12 @@
static int _ecore_wl2_init_count = 0;
/* external variables */
Eina_Bool no_session_recovery;
int _ecore_wl2_log_dom = -1;
/* public API variables */
EAPI int ECORE_WL2_EVENT_CONNECT = 0;
EAPI int ECORE_WL2_EVENT_DISCONNECT = 0;
EAPI int ECORE_WL2_EVENT_GLOBAL_ADDED = 0;
EAPI int ECORE_WL2_EVENT_GLOBAL_REMOVED = 0;
EAPI int ECORE_WL2_EVENT_FOCUS_IN = 0;
@ -67,6 +70,8 @@ ecore_wl2_init(void)
/* handle creating new Ecore_Wl2 event types */
if (!ECORE_WL2_EVENT_GLOBAL_ADDED)
{
ECORE_WL2_EVENT_CONNECT = ecore_event_type_new();
ECORE_WL2_EVENT_DISCONNECT = ecore_event_type_new();
ECORE_WL2_EVENT_GLOBAL_ADDED = ecore_event_type_new();
ECORE_WL2_EVENT_GLOBAL_REMOVED = ecore_event_type_new();
ECORE_WL2_EVENT_FOCUS_IN = ecore_event_type_new();
@ -87,6 +92,7 @@ ecore_wl2_init(void)
_ecore_wl2_event_window_www = ecore_event_type_new();
_ecore_wl2_event_window_www_drag = ecore_event_type_new();
}
no_session_recovery = !!getenv("EFL_NO_WAYLAND_SESSION_RECOVERY");
return _ecore_wl2_init_count;
@ -114,6 +120,8 @@ ecore_wl2_shutdown(void)
if (--_ecore_wl2_init_count != 0) return _ecore_wl2_init_count;
/* reset events */
ECORE_WL2_EVENT_CONNECT = 0;
ECORE_WL2_EVENT_DISCONNECT = 0;
ECORE_WL2_EVENT_GLOBAL_ADDED = 0;
ECORE_WL2_EVENT_GLOBAL_REMOVED = 0;
ECORE_WL2_EVENT_FOCUS_IN = 0;

View File

@ -8,10 +8,24 @@
#include <sys/param.h>
#include "linux-dmabuf-unstable-v1-client-protocol.h"
static Eina_Bool _fatal_error = EINA_FALSE;
static Eina_Hash *_server_displays = NULL;
static Eina_Hash *_client_displays = NULL;
static Eina_Bool _cb_connect_idle(void *data);
static Eina_Bool _cb_connect_data(void *data, Ecore_Fd_Handler *hdl);
static Eina_Bool _ecore_wl2_display_connect(Ecore_Wl2_Display *ewd, Eina_Bool sync);
static void
_ecore_wl2_display_event(Ecore_Wl2_Display *ewd, int event)
{
Ecore_Wl2_Event_Connect *ev;
ev = calloc(1, sizeof(Ecore_Wl2_Event_Connect));
EINA_SAFETY_ON_NULL_RETURN(ev);
ev->display = ewd;
ecore_event_add(event, ev, NULL, NULL);
}
static void
_ecore_wl2_display_signal_exit(void)
{
@ -147,7 +161,7 @@ _cb_global_add(void *data, struct wl_registry *registry, unsigned int id, const
_ecore_wl2_window_www_surface_init(window);
}
else if ((!strcmp(interface, "zwp_e_session_recovery")) &&
(getenv("EFL_WAYLAND_SESSION_RECOVERY")))
(!no_session_recovery))
{
ewd->wl.session_recovery =
wl_registry_bind(registry, id,
@ -210,25 +224,11 @@ static const struct wl_registry_listener _registry_listener =
};
static Eina_Bool
_cb_create_data(void *data, Ecore_Fd_Handler *hdl)
_cb_create_data(void *data, Ecore_Fd_Handler *hdl EINA_UNUSED)
{
Ecore_Wl2_Display *ewd;
Ecore_Wl2_Display *ewd = data;
struct wl_event_loop *loop;
ewd = data;
if (_fatal_error) return ECORE_CALLBACK_CANCEL;
if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_ERROR))
{
ERR("Received Fatal Error on Wayland Display");
_fatal_error = EINA_TRUE;
_ecore_wl2_display_signal_exit();
return ECORE_CALLBACK_CANCEL;
}
loop = wl_display_get_event_loop(ewd->wl.display);
wl_event_loop_dispatch(loop, 0);
@ -240,44 +240,83 @@ _cb_create_data(void *data, Ecore_Fd_Handler *hdl)
static void
_cb_create_prepare(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
{
Ecore_Wl2_Display *ewd;
Ecore_Wl2_Display *ewd = data;
ewd = data;
wl_display_flush_clients(ewd->wl.display);
}
static Eina_Bool
_recovery_timer(Ecore_Wl2_Display *ewd)
{
if (!_ecore_wl2_display_connect(ewd, 1))
return EINA_TRUE;
ewd->recovery_timer = NULL;
return EINA_FALSE;
}
static void
_recovery_timer_add(Ecore_Wl2_Display *ewd)
{
Eina_Inlist *tmp;
Ecore_Wl2_Output *output;
Ecore_Wl2_Input *input;
Ecore_Wl2_Window *window;
eina_hash_free_buckets(ewd->globals);
ecore_idle_enterer_del(ewd->idle_enterer);
ewd->idle_enterer = NULL;
ecore_main_fd_handler_del(ewd->fd_hdl);
ewd->fd_hdl = NULL;
if (ewd->wl.session_recovery)
zwp_e_session_recovery_destroy(ewd->wl.session_recovery);
if (ewd->wl.www) www_destroy(ewd->wl.www);
if (ewd->wl.xdg_shell) xdg_shell_destroy(ewd->wl.xdg_shell);
if (ewd->wl.wl_shell) wl_shell_destroy(ewd->wl.wl_shell);
if (ewd->wl.shm) wl_shm_destroy(ewd->wl.shm);
if (ewd->wl.data_device_manager)
wl_data_device_manager_destroy(ewd->wl.data_device_manager);
if (ewd->wl.compositor) wl_compositor_destroy(ewd->wl.compositor);
if (ewd->wl.subcompositor) wl_subcompositor_destroy(ewd->wl.subcompositor);
if (ewd->wl.registry) wl_registry_destroy(ewd->wl.registry);
memset(&ewd->wl, 0, sizeof(ewd->wl));
EINA_INLIST_FOREACH_SAFE(ewd->inputs, tmp, input)
_ecore_wl2_input_del(input);
EINA_INLIST_FOREACH_SAFE(ewd->outputs, tmp, output)
_ecore_wl2_output_del(output);
EINA_INLIST_FOREACH_SAFE(ewd->windows, tmp, window)
ecore_wl2_window_hide(window);
ewd->recovery_timer = ecore_timer_add(0.5, (Ecore_Task_Cb)_recovery_timer, ewd);
_ecore_wl2_display_event(ewd, ECORE_WL2_EVENT_DISCONNECT);
}
static void
_begin_recovery_maybe(Ecore_Wl2_Display *ewd)
{
ERR("Wayland Socket Error: %s", strerror(errno));
if (ewd->wl.session_recovery)// && (errno == EPIPE))
_recovery_timer_add(ewd);
else
_ecore_wl2_display_signal_exit();
}
static Eina_Bool
_cb_connect_data(void *data, Ecore_Fd_Handler *hdl)
{
Ecore_Wl2_Display *ewd;
Ecore_Wl2_Display *ewd = data;
int ret = 0;
ewd = data;
if (_fatal_error) return ECORE_CALLBACK_CANCEL;
if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_ERROR))
{
ERR("Received Fatal Error on Wayland Display");
_fatal_error = EINA_TRUE;
_ecore_wl2_display_signal_exit();
return ECORE_CALLBACK_CANCEL;
}
if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_READ))
{
ret = wl_display_dispatch(ewd->wl.display);
if ((ret < 0) && (errno != EAGAIN))
{
ERR("Received Fatal Error on Wayland Display");
_fatal_error = EINA_TRUE;
_ecore_wl2_display_signal_exit();
return ECORE_CALLBACK_CANCEL;
}
if ((ret < 0) && (errno != EAGAIN)) goto err;
}
if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_WRITE))
@ -286,18 +325,16 @@ _cb_connect_data(void *data, Ecore_Fd_Handler *hdl)
if (ret == 0)
ecore_main_fd_handler_active_set(hdl, ECORE_FD_READ);
if ((ret < 0) && (errno != EAGAIN))
{
ERR("Received Fatal Error on Wayland Display");
_fatal_error = EINA_TRUE;
_ecore_wl2_display_signal_exit();
return ECORE_CALLBACK_CANCEL;
}
if ((ret < 0) && (errno != EAGAIN)) goto err;
}
return ECORE_CALLBACK_RENEW;
err:
ewd->fd_hdl = NULL;
_begin_recovery_maybe(ewd);
return ECORE_CALLBACK_CANCEL;
}
static void
@ -315,14 +352,9 @@ _cb_globals_hash_del(void *data)
static Eina_Bool
_cb_connect_idle(void *data)
{
Ecore_Wl2_Display *ewd;
Ecore_Wl2_Display *ewd = data;
int ret = 0;
ewd = data;
if (!ewd) return ECORE_CALLBACK_RENEW;
if (_fatal_error) return ECORE_CALLBACK_CANCEL;
ret = wl_display_get_error(ewd->wl.display);
if (ret < 0) goto err;
@ -339,10 +371,8 @@ _cb_connect_idle(void *data)
err:
if ((ret < 0) && (errno != EAGAIN))
{
ERR("Wayland Socket Error: %s", strerror(errno));
_fatal_error = EINA_TRUE;
_ecore_wl2_display_signal_exit();
ewd->idle_enterer = NULL;
_begin_recovery_maybe(ewd);
return ECORE_CALLBACK_CANCEL;
}
@ -373,6 +403,56 @@ static const struct wl_callback_listener _sync_listener =
_cb_sync_done
};
static Eina_Bool
_ecore_wl2_display_connect(Ecore_Wl2_Display *ewd, Eina_Bool sync)
{
struct wl_callback *cb;
/* try to connect to wayland display with this name */
ewd->wl.display = wl_display_connect(ewd->name);
if (!ewd->wl.display)
{
ERR("Could not connect to display %s", ewd->name);
return EINA_FALSE;
}
ewd->wl.registry = wl_display_get_registry(ewd->wl.display);
wl_registry_add_listener(ewd->wl.registry, &_registry_listener, ewd);
cb = wl_display_sync(ewd->wl.display);
wl_callback_add_listener(cb, &_sync_listener, ewd);
if (sync)
{
/* NB: If we are connecting (as a client), then we will need to setup
* a callback for display_sync and wait for it to complete. There is no
* other option here as we need the compositor, shell, etc, to be setup
* before we can allow a user to make use of the API functions */
while (!ewd->sync_done)
{
int ret;
ret = wl_display_dispatch(ewd->wl.display);
if ((ret < 0) && (errno != EAGAIN))
{
ERR("Received Fatal Error on Wayland Display");
wl_registry_destroy(ewd->wl.registry);
return EINA_FALSE;
}
}
}
ewd->fd_hdl =
ecore_main_fd_handler_add(wl_display_get_fd(ewd->wl.display),
ECORE_FD_READ | ECORE_FD_WRITE | ECORE_FD_ERROR,
_cb_connect_data, ewd, NULL, NULL);
ewd->idle_enterer = ecore_idle_enterer_add(_cb_connect_idle, ewd);
_ecore_wl2_display_event(ewd, ECORE_WL2_EVENT_CONNECT);
return EINA_TRUE;
}
static void
_ecore_wl2_display_cleanup(Ecore_Wl2_Display *ewd)
{
@ -545,8 +625,6 @@ EAPI Ecore_Wl2_Display *
ecore_wl2_display_connect(const char *name)
{
Ecore_Wl2_Display *ewd;
Eina_Bool sync = EINA_TRUE;
struct wl_callback *cb;
const char *n;
Eina_Bool hash_create = !_client_displays;
@ -594,56 +672,13 @@ ecore_wl2_display_connect(const char *name)
ewd->globals = eina_hash_int32_new(_cb_globals_hash_del);
/* try to connect to wayland display with this name */
ewd->wl.display = wl_display_connect(ewd->name);
if (!ewd->wl.display)
{
ERR("Could not connect to display %s", ewd->name);
goto connect_err;
}
ewd->fd_hdl =
ecore_main_fd_handler_add(wl_display_get_fd(ewd->wl.display),
ECORE_FD_READ | ECORE_FD_WRITE | ECORE_FD_ERROR,
_cb_connect_data, ewd, NULL, NULL);
ewd->idle_enterer = ecore_idle_enterer_add(_cb_connect_idle, ewd);
ewd->wl.registry = wl_display_get_registry(ewd->wl.display);
wl_registry_add_listener(ewd->wl.registry, &_registry_listener, ewd);
/* check server display hash and match on pid. If match, skip sync */
if (!_ecore_wl2_display_connect(ewd, _ecore_wl2_display_sync_get()))
goto connect_err;
ewd->xkb_context = xkb_context_new(0);
if (!ewd->xkb_context) goto context_err;
/* check server display hash and match on pid. If match, skip sync */
sync = _ecore_wl2_display_sync_get();
cb = wl_display_sync(ewd->wl.display);
wl_callback_add_listener(cb, &_sync_listener, ewd);
if (sync)
{
/* NB: If we are connecting (as a client), then we will need to setup
* a callback for display_sync and wait for it to complete. There is no
* other option here as we need the compositor, shell, etc, to be setup
* before we can allow a user to make use of the API functions */
while (!ewd->sync_done)
{
int ret;
ret = wl_display_dispatch(ewd->wl.display);
if ((ret < 0) && (errno != EAGAIN))
{
ERR("Received Fatal Error on Wayland Display");
_fatal_error = EINA_TRUE;
_ecore_wl2_display_signal_exit();
goto context_err;
}
}
}
/* add this new client display to hash */
eina_hash_add(_client_displays, ewd->name, ewd);
@ -703,6 +738,7 @@ ecore_wl2_display_destroy(Ecore_Wl2_Display *display)
/* remove this client display from hash */
eina_hash_del_by_key(_server_displays, display->name);
ecore_timer_del(display->recovery_timer);
free(display->name);
free(display);

View File

@ -2,7 +2,6 @@
# define _ECORE_WL2_PRIVATE_H
# include <unistd.h>
# include <uuid/uuid.h>
# include "Ecore_Wl2.h"
# include "Ecore_Input.h"
# include "www-protocol.h"
@ -16,9 +15,10 @@
# include "xdg-shell-client-protocol.h"
# define XDG_VERSION 5
# include "session-recovery-client-protocol.h"
# include "session-recovery.h"
extern int _ecore_wl2_log_dom;
extern Eina_Bool no_session_recovery;
# ifdef EAPI
# undef EAPI
@ -95,6 +95,7 @@ struct _Ecore_Wl2_Display
Ecore_Fd_Handler *fd_hdl;
Eina_Hash *globals;
Ecore_Timer *recovery_timer;
Eina_Inlist *windows;
Eina_Inlist *outputs;
@ -141,7 +142,7 @@ struct _Ecore_Wl2_Window
struct xdg_popup *xdg_popup;
struct www_surface *www_surface;
uuid_t uuid;
Eina_Stringshare *uuid;
uint32_t configure_serial;
void (*configure_ack)(struct xdg_surface *surface, uint32_t serial);
@ -445,6 +446,7 @@ void _ecore_wl2_dnd_drop(Ecore_Wl2_Input *input);
void _ecore_wl2_dnd_selection(Ecore_Wl2_Input *input, struct wl_data_offer *offer);
void _ecore_wl2_dnd_del(Ecore_Wl2_Dnd_Source *source);
void _ecore_wl2_subsurf_unmap(Ecore_Wl2_Subsurface *subsurf);
void _ecore_wl2_subsurf_free(Ecore_Wl2_Subsurface *subsurf);
void _ecore_wl2_window_shell_surface_init(Ecore_Wl2_Window *window);

View File

@ -5,22 +5,16 @@
#include "ecore_wl2_private.h"
static void
_session_recovery_uuid(void *data, struct zwp_e_session_recovery *session_recovery, const char *uuid)
_session_recovery_create_uuid(void *data, struct zwp_e_session_recovery *session_recovery EINA_UNUSED, struct wl_surface *surface EINA_UNUSED, const char *uuid)
{
Ecore_Wl2_Window *win;
char str[37];
Ecore_Wl2_Window *win = data;
win = data;
if (!win) return;
if (!session_recovery) return;
uuid_parse(uuid, win->uuid);
uuid_unparse(win->uuid, str);
DBG("UUID event received from compositor with UUID: %s\n", str);
eina_stringshare_replace(&win->uuid, uuid);
}
static const struct zwp_e_session_recovery_listener _session_listener =
{
_session_recovery_uuid,
_session_recovery_create_uuid,
};
static void
@ -300,6 +294,22 @@ _ecore_wl2_window_shell_surface_init(Ecore_Wl2_Window *window)
window->configure_ack = xdg_surface_ack_configure;
_ecore_wl2_window_type_set(window);
if (window->display->wl.session_recovery)
{
if (window->uuid)
{
zwp_e_session_recovery_set_uuid(window->display->wl.session_recovery,
window->surface, window->uuid);
xdg_surface_set_window_geometry(window->xdg_surface,
window->geometry.x, window->geometry.y,
window->geometry.w, window->geometry.h);
ecore_wl2_window_opaque_region_set(window,
window->opaque.x, window->opaque.y,
window->opaque.w, window->opaque.h);
}
else
zwp_e_session_recovery_get_uuid(window->display->wl.session_recovery, window->surface);
}
}
else if ((window->display->wl.wl_shell) && (!window->wl_shell_surface))
{
@ -380,19 +390,9 @@ ecore_wl2_window_surface_get(Ecore_Wl2_Window *window)
window->surface_id =
wl_proxy_get_id((struct wl_proxy *)window->surface);
if ((window->display->wl.session_recovery) &&
(getenv("EFL_WAYLAND_SESSION_RECOVERY")))
{
char uuid[37];
zwp_e_session_recovery_add_listener(window->display->wl.session_recovery,
&_session_listener, window);
if (!uuid_is_null(window->uuid))
{
uuid_unparse(window->uuid, uuid);
zwp_e_session_recovery_provide_uuid(window->display->wl.session_recovery, uuid);
}
}
if (window->display->wl.session_recovery)
zwp_e_session_recovery_add_listener(window->display->wl.session_recovery,
&_session_listener, window);
}
return window->surface;
@ -432,6 +432,8 @@ ecore_wl2_window_show(Ecore_Wl2_Window *window)
EAPI void
ecore_wl2_window_hide(Ecore_Wl2_Window *window)
{
Ecore_Wl2_Subsurface *subsurf;
Eina_Inlist *tmp;
EINA_SAFETY_ON_NULL_RETURN(window);
if (window->xdg_surface) xdg_surface_destroy(window->xdg_surface);
@ -448,8 +450,18 @@ ecore_wl2_window_hide(Ecore_Wl2_Window *window)
www_surface_destroy(window->www_surface);
window->www_surface = NULL;
EINA_INLIST_FOREACH_SAFE(window->subsurfs, tmp, subsurf)
_ecore_wl2_subsurf_unmap(subsurf);
if (window->uuid && window->surface && window->display->wl.session_recovery)
zwp_e_session_recovery_destroy_uuid(window->display->wl.session_recovery,
window->surface, window->uuid);
if (window->surface) wl_surface_destroy(window->surface);
window->surface = NULL;
window->configure_serial = 0;
window->configure_ack = NULL;
}
EAPI void
@ -482,6 +494,7 @@ ecore_wl2_window_free(Ecore_Wl2_Window *window)
_ecore_wl2_subsurf_free(subsurf);
ecore_wl2_window_hide(window);
eina_stringshare_replace(&window->uuid, NULL);
if (window->title) eina_stringshare_del(window->title);
if (window->class) eina_stringshare_del(window->class);

View File

@ -1,68 +0,0 @@
#ifndef E_SESSION_RECOVERY_CLIENT_PROTOCOL_H
#define E_SESSION_RECOVERY_CLIENT_PROTOCOL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include "wayland-client.h"
struct wl_client;
struct wl_resource;
struct zwp_e_session_recovery;
extern const struct wl_interface zwp_e_session_recovery_interface;
struct zwp_e_session_recovery_listener {
/**
* uuid - (none)
* @uuid: (none)
*/
void (*uuid)(void *data,
struct zwp_e_session_recovery *zwp_e_session_recovery,
const char *uuid);
};
static inline int
zwp_e_session_recovery_add_listener(struct zwp_e_session_recovery *zwp_e_session_recovery,
const struct zwp_e_session_recovery_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) zwp_e_session_recovery,
(void (**)(void)) listener, data);
}
#define ZWP_E_SESSION_RECOVERY_PROVIDE_UUID 0
static inline void
zwp_e_session_recovery_set_user_data(struct zwp_e_session_recovery *zwp_e_session_recovery, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) zwp_e_session_recovery, user_data);
}
static inline void *
zwp_e_session_recovery_get_user_data(struct zwp_e_session_recovery *zwp_e_session_recovery)
{
return wl_proxy_get_user_data((struct wl_proxy *) zwp_e_session_recovery);
}
static inline void
zwp_e_session_recovery_destroy(struct zwp_e_session_recovery *zwp_e_session_recovery)
{
wl_proxy_destroy((struct wl_proxy *) zwp_e_session_recovery);
}
static inline void
zwp_e_session_recovery_provide_uuid(struct zwp_e_session_recovery *zwp_e_session_recovery, const char *uuid)
{
wl_proxy_marshal((struct wl_proxy *) zwp_e_session_recovery,
ZWP_E_SESSION_RECOVERY_PROVIDE_UUID, uuid);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -2,22 +2,31 @@
#include <stdint.h>
#include "wayland-util.h"
extern const struct wl_interface wl_surface_interface;
static const struct wl_interface *types[] = {
&wl_surface_interface,
&wl_surface_interface,
NULL,
&wl_surface_interface,
NULL,
&wl_surface_interface,
NULL,
};
static const struct wl_message zwp_e_session_recovery_requests[] = {
{ "provide_uuid", "s", types + 0 },
{ "get_uuid", "o", types + 0 },
{ "set_uuid", "os", types + 1 },
{ "destroy_uuid", "os", types + 3 },
};
static const struct wl_message zwp_e_session_recovery_events[] = {
{ "uuid", "s", types + 0 },
{ "create_uuid", "os", types + 5 },
};
WL_EXPORT const struct wl_interface zwp_e_session_recovery_interface = {
"zwp_e_session_recovery", 1,
1, zwp_e_session_recovery_requests,
3, zwp_e_session_recovery_requests,
1, zwp_e_session_recovery_events,
};

View File

@ -0,0 +1,97 @@
#ifndef E_SESSION_RECOVERY_CLIENT_PROTOCOL_H
#define E_SESSION_RECOVERY_CLIENT_PROTOCOL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include "wayland-client.h"
struct wl_client;
struct wl_resource;
struct wl_surface;
struct zwp_e_session_recovery;
extern const struct wl_interface zwp_e_session_recovery_interface;
struct zwp_e_session_recovery_listener {
/**
* create_uuid - (none)
* @surface: (none)
* @uuid: (none)
*/
void (*create_uuid)(void *data,
struct zwp_e_session_recovery *zwp_e_session_recovery,
struct wl_surface *surface,
const char *uuid);
};
static inline int
zwp_e_session_recovery_add_listener(struct zwp_e_session_recovery *zwp_e_session_recovery,
const struct zwp_e_session_recovery_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) zwp_e_session_recovery,
(void (**)(void)) listener, data);
}
#define ZWP_E_SESSION_RECOVERY_GET_UUID 0
#define ZWP_E_SESSION_RECOVERY_SET_UUID 1
#define ZWP_E_SESSION_RECOVERY_DESTROY_UUID 2
#define ZWP_E_SESSION_RECOVERY_GET_UUID_SINCE_VERSION 1
#define ZWP_E_SESSION_RECOVERY_SET_UUID_SINCE_VERSION 1
#define ZWP_E_SESSION_RECOVERY_DESTROY_UUID_SINCE_VERSION 1
static inline void
zwp_e_session_recovery_set_user_data(struct zwp_e_session_recovery *zwp_e_session_recovery, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) zwp_e_session_recovery, user_data);
}
static inline void *
zwp_e_session_recovery_get_user_data(struct zwp_e_session_recovery *zwp_e_session_recovery)
{
return wl_proxy_get_user_data((struct wl_proxy *) zwp_e_session_recovery);
}
static inline uint32_t
zwp_e_session_recovery_get_version(struct zwp_e_session_recovery *zwp_e_session_recovery)
{
return wl_proxy_get_version((struct wl_proxy *) zwp_e_session_recovery);
}
static inline void
zwp_e_session_recovery_destroy(struct zwp_e_session_recovery *zwp_e_session_recovery)
{
wl_proxy_destroy((struct wl_proxy *) zwp_e_session_recovery);
}
static inline void
zwp_e_session_recovery_get_uuid(struct zwp_e_session_recovery *zwp_e_session_recovery, struct wl_surface *surface)
{
wl_proxy_marshal((struct wl_proxy *) zwp_e_session_recovery,
ZWP_E_SESSION_RECOVERY_GET_UUID, surface);
}
static inline void
zwp_e_session_recovery_set_uuid(struct zwp_e_session_recovery *zwp_e_session_recovery, struct wl_surface *surface, const char *uuid)
{
wl_proxy_marshal((struct wl_proxy *) zwp_e_session_recovery,
ZWP_E_SESSION_RECOVERY_SET_UUID, surface, uuid);
}
static inline void
zwp_e_session_recovery_destroy_uuid(struct zwp_e_session_recovery *zwp_e_session_recovery, struct wl_surface *surface, const char *uuid)
{
wl_proxy_marshal((struct wl_proxy *) zwp_e_session_recovery,
ZWP_E_SESSION_RECOVERY_DESTROY_UUID, surface, uuid);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -12,6 +12,8 @@
static const char *interface_wl_name = "wayland";
static const int interface_wl_version = 1;
Eina_List *ee_list;
/* local structures for the frame smart object */
typedef struct _EE_Wl_Smart_Data EE_Wl_Smart_Data;
struct _EE_Wl_Smart_Data
@ -34,7 +36,7 @@ EVAS_SMART_SUBCLASS_NEW(_smart_frame_type, _ecore_evas_wl_frame,
/* local variables */
static int _ecore_evas_wl_init_count = 0;
static Ecore_Event_Handler *_ecore_evas_wl_event_hdls[7];
static Ecore_Event_Handler *_ecore_evas_wl_event_hdls[8];
static void _ecore_evas_wayland_resize(Ecore_Evas *ee, int location);
@ -161,6 +163,30 @@ _ecore_evas_wl_common_cb_focus_out(void *data EINA_UNUSED, int type EINA_UNUSED,
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_ecore_evas_wl_common_cb_disconnect(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
Ecore_Wl2_Event_Disconnect *ev = event;
Eina_List *l;
Ecore_Evas *ee;
EINA_LIST_FOREACH(ee_list, l, ee)
{
Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
if (wdata->display != ev->display) continue;
if (wdata->anim_callback) wl_callback_destroy(wdata->anim_callback);
wdata->anim_callback = NULL;
wdata->sync_done = EINA_FALSE;
wdata->defer_show = EINA_TRUE;
wdata->reset_pending = 1;
ecore_evas_manual_render_set(ee, 1);
if (wdata->display_unset)
wdata->display_unset(ee);
}
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_ecore_evas_wl_common_cb_window_configure(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
@ -441,6 +467,9 @@ _ecore_evas_wl_common_init(void)
_ecore_evas_wl_event_hdls[6] =
ecore_event_handler_add(_ecore_wl2_event_window_www_drag,
_ecore_evas_wl_common_cb_www_drag, NULL);
_ecore_evas_wl_event_hdls[7] =
ecore_event_handler_add(ECORE_WL2_EVENT_DISCONNECT,
_ecore_evas_wl_common_cb_disconnect, NULL);
ecore_event_evas_init();
return _ecore_evas_wl_init_count;
@ -489,10 +518,15 @@ _ecore_evas_wl_common_free(Ecore_Evas *ee)
if (!ee) return;
wdata = ee->engine.data;
ee_list = eina_list_remove(ee_list, ee);
eina_list_free(wdata->regen_objs);
if (wdata->anim_callback) wl_callback_destroy(wdata->anim_callback);
wdata->anim_callback = NULL;
ecore_event_handler_del(wdata->sync_handler);
if (wdata->win) ecore_wl2_window_free(wdata->win);
wdata->win = NULL;

View File

@ -30,6 +30,9 @@
# endif
#endif /* ! _WIN32 */
extern EAPI Eina_List *_evas_canvas_image_data_unset(Evas *eo_e);
extern EAPI void _evas_canvas_image_data_regenerate(Eina_List *list);
/* local function prototypes */
static void _ecore_evas_wl_move_resize(Ecore_Evas *ee, int x, int y, int w, int h);
static void _ecore_evas_wl_show(Ecore_Evas *ee);
@ -117,6 +120,19 @@ static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
/* external variables */
void
_ee_egl_display_unset(Ecore_Evas *ee)
{
Evas_Engine_Info_Wayland_Egl *einfo;
Ecore_Evas_Engine_Wl_Data *wdata;
einfo = (Evas_Engine_Info_Wayland_Egl *)evas_engine_info_get(ee->evas);
einfo->info.display = NULL;
wdata = ee->engine.data;
wdata->regen_objs = _evas_canvas_image_data_unset(ecore_evas_get(ee));
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
}
static Eina_Bool
_ee_cb_sync_done(void *data, int type EINA_UNUSED, void *event EINA_UNUSED)
{
@ -136,10 +152,19 @@ _ee_cb_sync_done(void *data, int type EINA_UNUSED, void *event EINA_UNUSED)
einfo->info.rotation = ee->rotation;
einfo->info.surface = ecore_wl2_window_surface_get(wdata->win);
if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
if (wdata->reset_pending)
{
ERR("Failed to set Evas Engine Info for '%s'", ee->driver);
ecore_evas_manual_render_set(ee, 0);
}
if (evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo))
{
if (wdata->reset_pending)
_evas_canvas_image_data_regenerate(wdata->regen_objs);
wdata->regen_objs = NULL;
}
else
ERR("Failed to set Evas Engine Info for '%s'", ee->driver);
wdata->reset_pending = 0;
}
else
{
@ -164,15 +189,7 @@ _ee_cb_sync_done(void *data, int type EINA_UNUSED, void *event EINA_UNUSED)
einfo = (Evas_Engine_Info_Wayland_Egl *)evas_engine_info_get(ee->evas);
if (einfo)
{
struct wl_surface *surf;
surf = ecore_wl2_window_surface_get(wdata->win);
if ((!einfo->info.surface) || (einfo->info.surface != surf))
{
einfo->info.surface = surf;
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
evas_damage_rectangle_add(ee->evas, 0, 0, ee->w + fw, ee->h + fh);
}
evas_damage_rectangle_add(ee->evas, 0, 0, ee->w + fw, ee->h + fh);
einfo->www_avail = !!wdata->win->www_surface;
einfo->just_mapped = EINA_TRUE;
}
@ -362,6 +379,7 @@ ecore_evas_wayland_egl_new_internal(const char *disp_name, unsigned int parent,
wdata->sync_done = EINA_FALSE;
wdata->parent = p;
wdata->display = ewd;
wdata->display_unset = _ee_egl_display_unset;
wdata->win = ecore_wl2_window_new(ewd, p, x, y, w + fw, h + fh);
ee->prop.window = ecore_wl2_window_id_get(wdata->win);
@ -432,7 +450,8 @@ ecore_evas_wayland_egl_new_internal(const char *disp_name, unsigned int parent,
(Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
(Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
ecore_event_handler_add(ECORE_WL2_EVENT_SYNC_DONE, _ee_cb_sync_done, ee);
wdata->sync_handler = ecore_event_handler_add(ECORE_WL2_EVENT_SYNC_DONE, _ee_cb_sync_done, ee);
ee_list = eina_list_append(ee_list, ee);
return ee;

View File

@ -33,7 +33,10 @@ typedef struct _Ecore_Evas_Engine_Wl_Data Ecore_Evas_Engine_Wl_Data;
struct _Ecore_Evas_Engine_Wl_Data
{
Ecore_Wl2_Display *display;
void (*display_unset)(Ecore_Evas*);
Eina_List *regen_objs;
Ecore_Wl2_Window *parent, *win;
Ecore_Event_Handler *sync_handler;
Evas_Object *frame;
int fx, fy, fw, fh;
#ifdef BUILD_ECORE_EVAS_WAYLAND_EGL
@ -48,6 +51,7 @@ struct _Ecore_Evas_Engine_Wl_Data
Eina_Bool sync_done : 1;
Eina_Bool defer_show : 1;
Eina_Bool reset_pending : 1;
};
Ecore_Evas_Interface_Wayland *_ecore_evas_wl_interface_new(void);
@ -100,6 +104,8 @@ void _ecore_evas_wl_common_frame_border_size_set(Evas_Object *obj, int fx, int f
void _ecore_evas_wl_common_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y);
extern Eina_List *ee_list;
#ifdef BUILD_ECORE_EVAS_WAYLAND_SHM
void _ecore_evas_wayland_shm_resize(Ecore_Evas *ee, int location);
void _ecore_evas_wayland_shm_resize_edge_set(Ecore_Evas *ee, int edge);

View File

@ -131,6 +131,7 @@ _ee_cb_sync_done(void *data, int type EINA_UNUSED, void *event EINA_UNUSED)
if ((einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas)))
{
ecore_evas_manual_render_set(ee, 0);
einfo->info.wl_disp = ecore_wl2_display_get(wdata->display);
einfo->info.wl_dmabuf = ecore_wl2_display_dmabuf_get(wdata->display);
einfo->info.wl_shm = ecore_wl2_display_shm_get(wdata->display);
@ -162,22 +163,7 @@ _ee_cb_sync_done(void *data, int type EINA_UNUSED, void *event EINA_UNUSED)
evas_output_framespace_get(ee->evas, NULL, NULL, &fw, &fh);
if (wdata->win)
{
einfo = (Evas_Engine_Info_Wayland_Shm *)evas_engine_info_get(ee->evas);
if (einfo)
{
struct wl_surface *surf;
surf = ecore_wl2_window_surface_get(wdata->win);
if ((!einfo->info.wl_surface) || (einfo->info.wl_surface != surf))
{
einfo->info.wl_surface = surf;
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
evas_damage_rectangle_add(ee->evas, 0, 0, ee->w + fw, ee->h + fh);
}
}
}
evas_damage_rectangle_add(ee->evas, 0, 0, ee->w + fw, ee->h + fh);
if (wdata->frame)
{
@ -373,7 +359,8 @@ ecore_evas_wayland_shm_new_internal(const char *disp_name, unsigned int parent,
(Ecore_Event_Multi_Down_Cb)_ecore_evas_mouse_multi_down_process,
(Ecore_Event_Multi_Up_Cb)_ecore_evas_mouse_multi_up_process);
ecore_event_handler_add(ECORE_WL2_EVENT_SYNC_DONE, _ee_cb_sync_done, ee);
wdata->sync_handler = ecore_event_handler_add(ECORE_WL2_EVENT_SYNC_DONE, _ee_cb_sync_done, ee);
ee_list = eina_list_append(ee_list, ee);
return ee;