wayland: implement session recovery
authorMike Blumenkrantz <zmike@osg.samsung.com>
Thu, 5 May 2016 14:45:59 +0000 (10:45 -0400)
committerMike Blumenkrantz <zmike@osg.samsung.com>
Thu, 5 May 2016 14:49:31 +0000 (10:49 -0400)
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

14 files changed:
configure.ac
src/Makefile_Ecore_Wl2.am
src/lib/ecore_wl2/Ecore_Wl2.h
src/lib/ecore_wl2/ecore_wl2.c
src/lib/ecore_wl2/ecore_wl2_display.c
src/lib/ecore_wl2/ecore_wl2_private.h
src/lib/ecore_wl2/ecore_wl2_window.c
src/lib/ecore_wl2/session-recovery-client-protocol.h [deleted file]
src/lib/ecore_wl2/session-recovery.c [moved from src/lib/ecore_wl2/session-recovery-protocol.c with 54% similarity]
src/lib/ecore_wl2/session-recovery.h [new file with mode: 0644]
src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c
src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_private.h
src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c

index 2d38a43..cac8850 100644 (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])
 
index 8a55a2d..9bf375e 100644 (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 \
index 02099f7..fef28a6 100644 (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 */
index f1fded6..e9cf9f6 100644 (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;
index ccc4a8b..a993ea1 100644 (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
-_cb_connect_data(void *data, Ecore_Fd_Handler *hdl)
+static Eina_Bool 
+_recovery_timer(Ecore_Wl2_Display *ewd)
 {
-   Ecore_Wl2_Display *ewd;
-   int ret = 0;
+   if (!_ecore_wl2_display_connect(ewd, 1))
+     return EINA_TRUE;
 
-   ewd = data;
+   ewd->recovery_timer = NULL;
+   return EINA_FALSE;
+}
 
-   if (_fatal_error) return ECORE_CALLBACK_CANCEL;
+static void
+_recovery_timer_add(Ecore_Wl2_Display *ewd)
+{
+   Eina_Inlist *tmp;
+   Ecore_Wl2_Output *output;
+   Ecore_Wl2_Input *input;
+   Ecore_Wl2_Window *window;
 
-   if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_ERROR))
-     {
-        ERR("Received Fatal Error on Wayland Display");
+   eina_hash_free_buckets(ewd->globals);
+   ecore_idle_enterer_del(ewd->idle_enterer);
+   ewd->idle_enterer = NULL;
 
-        _fatal_error = EINA_TRUE;
-        _ecore_wl2_display_signal_exit();
+   ecore_main_fd_handler_del(ewd->fd_hdl);
+   ewd->fd_hdl = NULL;
 
-        return ECORE_CALLBACK_CANCEL;
-     }
+   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 = data;
+   int ret = 0;
 
    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);
index 6913edc..be69725 100644 (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"
 # 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);
index c3415ea..b9fdb5c 100644 (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);
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 (file)
index 2405747..0000000
+++ /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 <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
similarity index 54%
rename from src/lib/ecore_wl2/session-recovery-protocol.c
rename to src/lib/ecore_wl2/session-recovery.c
index 32ddbcb..47ecbb9 100644 (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,
 };
 
diff --git a/src/lib/ecore_wl2/session-recovery.h b/src/lib/ecore_wl2/session-recovery.h
new file mode 100644 (file)
index 0000000..980d37f
--- /dev/null
@@ -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
index 6708666..10d4cca 100644 (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);
 
@@ -162,6 +164,30 @@ _ecore_evas_wl_common_cb_focus_out(void *data EINA_UNUSED, int type EINA_UNUSED,
 }
 
 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)
 {
    Ecore_Evas *ee;
@@ -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;
 
index 47904d2..e3536da 100644 (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;
 
index 9942e90..49d02c4 100644 (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);
index d97ce8b..ad87d90 100644 (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;