diff --git a/configure.ac b/configure.ac index 2d38a43111..cac8850f4a 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/src/Makefile_Ecore_Wl2.am b/src/Makefile_Ecore_Wl2.am index 8a55a2d7d0..9bf375e5a0 100644 --- a/src/Makefile_Ecore_Wl2.am +++ b/src/Makefile_Ecore_Wl2.am @@ -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 \ diff --git a/src/lib/ecore_wl2/Ecore_Wl2.h b/src/lib/ecore_wl2/Ecore_Wl2.h index 02099f73c9..fef28a6604 100644 --- a/src/lib/ecore_wl2/Ecore_Wl2.h +++ b/src/lib/ecore_wl2/Ecore_Wl2.h @@ -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 */ diff --git a/src/lib/ecore_wl2/ecore_wl2.c b/src/lib/ecore_wl2/ecore_wl2.c index f1fded6193..e9cf9f6131 100644 --- a/src/lib/ecore_wl2/ecore_wl2.c +++ b/src/lib/ecore_wl2/ecore_wl2.c @@ -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; diff --git a/src/lib/ecore_wl2/ecore_wl2_display.c b/src/lib/ecore_wl2/ecore_wl2_display.c index ccc4a8bcbb..a993ea119b 100644 --- a/src/lib/ecore_wl2/ecore_wl2_display.c +++ b/src/lib/ecore_wl2/ecore_wl2_display.c @@ -8,10 +8,24 @@ #include #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); diff --git a/src/lib/ecore_wl2/ecore_wl2_private.h b/src/lib/ecore_wl2/ecore_wl2_private.h index 6913edc662..be69725321 100644 --- a/src/lib/ecore_wl2/ecore_wl2_private.h +++ b/src/lib/ecore_wl2/ecore_wl2_private.h @@ -2,7 +2,6 @@ # define _ECORE_WL2_PRIVATE_H # include -# include # 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); diff --git a/src/lib/ecore_wl2/ecore_wl2_window.c b/src/lib/ecore_wl2/ecore_wl2_window.c index c3415eaa34..b9fdb5c303 100644 --- a/src/lib/ecore_wl2/ecore_wl2_window.c +++ b/src/lib/ecore_wl2/ecore_wl2_window.c @@ -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); diff --git a/src/lib/ecore_wl2/session-recovery-client-protocol.h b/src/lib/ecore_wl2/session-recovery-client-protocol.h deleted file mode 100644 index 24057471fb..0000000000 --- a/src/lib/ecore_wl2/session-recovery-client-protocol.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef E_SESSION_RECOVERY_CLIENT_PROTOCOL_H -#define E_SESSION_RECOVERY_CLIENT_PROTOCOL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#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 diff --git a/src/lib/ecore_wl2/session-recovery-protocol.c b/src/lib/ecore_wl2/session-recovery.c similarity index 54% rename from src/lib/ecore_wl2/session-recovery-protocol.c rename to src/lib/ecore_wl2/session-recovery.c index 32ddbcbefe..47ecbb9759 100644 --- a/src/lib/ecore_wl2/session-recovery-protocol.c +++ b/src/lib/ecore_wl2/session-recovery.c @@ -2,22 +2,31 @@ #include #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, }; diff --git a/src/lib/ecore_wl2/session-recovery.h b/src/lib/ecore_wl2/session-recovery.h new file mode 100644 index 0000000000..980d37fd81 --- /dev/null +++ b/src/lib/ecore_wl2/session-recovery.h @@ -0,0 +1,97 @@ +#ifndef E_SESSION_RECOVERY_CLIENT_PROTOCOL_H +#define E_SESSION_RECOVERY_CLIENT_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#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 diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c index 67086667e5..10d4ccaf10 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c @@ -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; diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c index 47904d2f24..e3536da949 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c @@ -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; diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h index 9942e908a2..49d02c43b4 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h @@ -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); diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c index d97ce8bff6..ad87d90ee3 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c @@ -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;