implement wl client session recovery

another small feature patch brought to you by insomnia

 #SamsungFeatures
devs/captainigloo/eglfs_rpi
Mike Blumenkrantz 7 years ago
parent e0d1a572a1
commit ef1772b8cb
  1. 6
      src/bin/Makefile.mk
  2. 1
      src/bin/e.h
  3. 9
      src/bin/e_client.c
  4. 4
      src/bin/e_client.h
  5. 16
      src/bin/e_comp_wl.c
  6. 65
      src/bin/e_comp_wl_extensions.c
  7. 2
      src/bin/e_config.c
  8. 1
      src/bin/e_includes.h
  9. 13
      src/bin/e_main.c
  10. 1222
      src/bin/e_remember.c
  11. 5
      src/bin/e_remember.h
  12. 210
      src/bin/e_uuid_store.c
  13. 36
      src/bin/e_uuid_store.h
  14. 43
      src/bin/generated/session-recovery-server-protocol.h
  15. 15
      src/bin/generated/session-recovery.c
  16. 62
      src/bin/generated/session-recovery.h
  17. 13
      src/protocol/session-recovery.xml

@ -221,7 +221,6 @@ src/bin/e_zone.h
if HAVE_WAYLAND
ENLIGHTENMENTHEADERS += \
src/bin/e_uuid_store.h \
src/bin/e_comp_wl_data.h \
src/bin/e_comp_wl_input.h \
src/bin/e_comp_wl.h
@ -394,11 +393,10 @@ endif
if HAVE_WAYLAND
enlightenment_src += \
src/bin/e_uuid_store.c \
src/bin/generated/www-protocol.c \
src/bin/generated/www-protocol.h \
src/bin/generated/session-recovery-protocol.c \
src/bin/generated/session-recovery-server-protocol.h \
src/bin/generated/session-recovery.c \
src/bin/generated/session-recovery.h \
src/bin/generated/e_comp_wl_screenshooter_server.c \
src/bin/generated/e_comp_wl_screenshooter_server.h \
src/bin/e_comp_wl_data.c \

@ -133,7 +133,6 @@ void *alloca (size_t);
# ifdef HAVE_WAYLAND
# include <Ecore_Wl2.h>
# include <uuid.h>
# endif
# ifdef E_API

@ -554,6 +554,7 @@ _e_client_free(E_Client *ec)
eina_stringshare_replace(&ec->netwm.icon_name, NULL);
eina_stringshare_replace(&ec->internal_icon, NULL);
eina_stringshare_replace(&ec->internal_icon_key, NULL);
eina_stringshare_replace(&ec->uuid, NULL);
focus_stack = eina_list_remove(focus_stack, ec);
raise_stack = eina_list_remove(raise_stack, ec);
@ -570,10 +571,6 @@ _e_client_free(E_Client *ec)
evas_object_del(ec->frame);
E_OBJECT(ec)->references--;
#ifdef HAVE_WAYLAND
e_uuid_store_entry_del(ec->uuid);
#endif
free(ec);
}
@ -2346,10 +2343,6 @@ e_client_new(E_Pixmap *cp, int first_map, int internal)
if (!ec) return NULL;
e_object_del_func_set(E_OBJECT(ec), E_OBJECT_CLEANUP_FUNC(_e_client_del));
#ifdef HAVE_WAYLAND
uuid_generate(ec->uuid);
#endif
ec->focus_policy_override = E_FOCUS_LAST;
ec->w = 1;
ec->h = 1;

@ -686,9 +686,7 @@ struct E_Client
E_Focus_Policy focus_policy_override;
#ifdef HAVE_WAYLAND
uuid_t uuid;
#endif
Eina_Stringshare *uuid;
Eina_Bool override : 1;
Eina_Bool input_only : 1;

@ -1603,15 +1603,13 @@ _e_comp_wl_compositor_cb_surface_create(struct wl_client *client, struct wl_reso
ec = e_client_new(ep, 0, 0);
}
if (ec)
{
if (ec->new_client)
e_comp->new_clients--;
ec->new_client = 0;
if ((!ec->client.w) && (ec->client.h))
ec->client.w = ec->client.h = 1;
ec->comp_data->surface = res;
}
if (ec->new_client)
e_comp->new_clients--;
ec->new_client = 0;
if ((!ec->client.w) && (ec->client.h))
ec->client.w = ec->client.h = 1;
ec->comp_data->surface = res;
ec->netwm.pid = pid;
/* set reference to pixmap so we can fetch it later */
DBG("\tUsing Client: %p", ec);

@ -1,8 +1,10 @@
#define E_COMP_WL
#include "e.h"
#include <uuid.h>
#include "e_comp_wl_screenshooter_server.h"
#include "session-recovery-server-protocol.h"
#include "session-recovery.h"
#include "www-protocol.h"
static void
@ -24,9 +26,62 @@ _e_comp_wl_extensions_client_move_end(void *d EINA_UNUSED, E_Client *ec)
}
static void
_e_comp_wl_sr_cb_provide_uuid(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, const char *uuid)
_e_comp_wl_session_recovery_get_uuid(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *surface)
{
DBG("Provide UUID callback called for UUID: %s", uuid);
E_Client *ec;
uuid_t u;
char uuid[37];
ec = wl_resource_get_user_data(surface);
if (e_object_is_del(E_OBJECT(ec))) return;
if (ec->internal || ec->uuid) return;
uuid_generate(u);
uuid_unparse_lower(u, uuid);
eina_stringshare_replace(&ec->uuid, uuid);
zwp_e_session_recovery_send_create_uuid(resource, surface, uuid);
if (ec->remember)
e_remember_unuse(ec->remember);
ec->remember = e_remember_new();
e_remember_use(ec->remember);
ec->remember->apply = E_REMEMBER_APPLY_POS | E_REMEMBER_APPLY_DESKTOP |
E_REMEMBER_APPLY_LAYER | E_REMEMBER_APPLY_ZONE | E_REMEMBER_APPLY_UUID;
e_remember_update(ec);
}
static void
_e_comp_wl_session_recovery_set_uuid(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, struct wl_resource *surface, const char *uuid)
{
E_Client *ec;
E_Remember *rem;
ec = wl_resource_get_user_data(surface);
if (e_object_is_del(E_OBJECT(ec))) return;
if (ec->internal || ec->uuid) return; //FIXME: error
eina_stringshare_replace(&ec->uuid, uuid);
rem = e_remember_find_usable(ec);
if ((!rem) || (rem == ec->remember)) return;
if (ec->remember)
e_remember_unuse(ec->remember);
ec->remember = rem;
e_remember_use(rem);
e_remember_apply(rem, ec);
ec->re_manage = 1;
}
static void
_e_comp_wl_session_recovery_destroy_uuid(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, struct wl_resource *surface, const char *uuid)
{
E_Client *ec;
ec = wl_resource_get_user_data(surface);
if (!eina_streq(ec->uuid, uuid)) return; //FIXME: error
eina_stringshare_replace(&ec->uuid, NULL);
e_remember_unuse(ec->remember);
e_remember_del(ec->remember);
ec->remember = e_remember_find_usable(ec);
if (!ec->remember) return;
e_remember_use(ec->remember);
e_remember_apply(ec->remember, ec);
}
static void
@ -145,7 +200,9 @@ _e_comp_wl_www_cb_create(struct wl_client *client, struct wl_resource *resource,
static const struct zwp_e_session_recovery_interface _e_session_recovery_interface =
{
_e_comp_wl_sr_cb_provide_uuid,
_e_comp_wl_session_recovery_get_uuid,
_e_comp_wl_session_recovery_set_uuid,
_e_comp_wl_session_recovery_destroy_uuid,
};
static const struct screenshooter_interface _e_screenshooter_interface =

@ -384,6 +384,8 @@ _e_config_edd_init(Eina_Bool old)
E_CONFIG_VAL(D, T, prop.desktop_file, STR);
E_CONFIG_VAL(D, T, prop.offer_resistance, UCHAR);
E_CONFIG_VAL(D, T, prop.opacity, UCHAR);
E_CONFIG_VAL(D, T, uuid, STR);
E_CONFIG_VAL(D, T, pid, INT);
_e_config_color_class_edd = E_CONFIG_DD_NEW("E_Color_Class", E_Color_Class);
#undef T

@ -157,5 +157,4 @@
# include "e_comp_wl.h"
# include "e_comp_wl_data.h"
# include "e_comp_wl_input.h"
# include "e_uuid_store.h"
#endif

@ -536,19 +536,6 @@ main(int argc, char **argv)
_e_main_shutdown_push(e_alert_shutdown);
#endif
#if 0
//#ifdef HAVE_WAYLAND
/* init uuid store for window/surface properties */
TS("E_UUID_Store Init");
if (!e_uuid_store_init())
{
e_error_message_show(_("Enlightenment cannot initialize its UUID store.\n"));
_e_main_shutdown(-1);
}
TS("E_UUID_Store Init Done");
_e_main_shutdown_push(e_uuid_store_shutdown);
#endif
TS("E Directories Init");
/* setup directories we will be using for configurations storage etc. */
if (!_e_main_dirs_init())

File diff suppressed because it is too large Load Diff

@ -35,6 +35,7 @@ typedef struct _E_Remember E_Remember;
#define E_REMEMBER_APPLY_FULLSCREEN (1 << 15)
#define E_REMEMBER_APPLY_OFFER_RESISTANCE (1 << 16)
#define E_REMEMBER_APPLY_OPACITY (1 << 17)
#define E_REMEMBER_APPLY_UUID (1 << 18)
#define E_REMEMBER_INTERNAL_DIALOGS (1 << 0)
#define E_REMEMBER_INTERNAL_FM_WINS (1 << 1)
@ -109,6 +110,8 @@ struct _E_Remember
const char *desktop_file;
unsigned char opacity;
} prop;
Eina_Stringshare *uuid;
int pid;
};
EINTERN int e_remember_init(E_Startup_Mode mode);
@ -124,5 +127,7 @@ E_API void e_remember_match_update(E_Remember *rem);
E_API void e_remember_update(E_Client *ec);
E_API int e_remember_default_match_set(E_Remember *rem, E_Client *ec);
E_API void e_remember_internal_save(void);
E_API void e_remember_apply(E_Remember *rem, E_Client *ec);
#endif
#endif

@ -1,210 +0,0 @@
/* vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0
*/
/* 1. Create mmaped memory blob, name the memory object
* 2. Fill in table and keep it up-to-date
* 3. (optional) Write the whole blob into a file on disk for later use)
*/
#include <e.h>
#include <sys/mman.h>
/* Use anonymous mapping if we don't want a persistent file on the disk */
#define OBJECT_NAME "/e_uuid_store"
#define TABLE_SIZE 10*eina_cpu_page_size()
struct uuid_store *store;
void
e_uuid_dump(void)
{
struct uuid_table *table;
int i;
char uuid_string[37];
if (store == NULL) return;
table = store->table;
if (table == NULL) return;
INF("Dump UUID table:");
for (i = 0; i < UUID_STORE_TABLE_SIZE -1; i++)
{
if (uuid_is_null(table->entries[i].uuid)) continue;
uuid_unparse(table->entries[i].uuid, uuid_string);
INF("UUID %s, x=%i, y=%i, width=%i, heigth=%i", uuid_string, table->entries[i].x,
table->entries[i].y, table->entries[i].width,
table->entries[i].heigth);
}
}
/**
* Initialize the UUID store
*
* @returns 1 if init was successful, 0 on failure
*/
EINTERN int
e_uuid_store_init(void)
{
/* FIXME think about refcounting here */
eina_init();
store = calloc(1, sizeof(struct uuid_store));
if (store == NULL) return 0;
/* Try to open existing SHM object */
store->shmfd = shm_open(OBJECT_NAME, O_RDWR, S_IRWXU | S_IRWXG);
if (store->shmfd < 0 && errno == ENOENT)
{
INF("shm_open failed to open an existing file %s", OBJECT_NAME);
if (!e_uuid_store_reload()) return 0;
}
else if (store->shmfd < 0)
{
INF("shm_open failed");
return 0;
}
/* Adjust in memory blob to our given table size */
/* FIXME: How can we make sure we have the right size for our given table? */
if (ftruncate(store->shmfd, TABLE_SIZE) < 0)
{
ERR("ftruncate failed: %s", strerror(errno));
return 0;
}
store->table = (struct uuid_table *)mmap(NULL, TABLE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, store->shmfd, 0);
if (store->table == NULL)
{
ERR("mmap failed");
return 0;
}
INF("mmaped blob with size %i created", TABLE_SIZE);
if (store->table->version)
INF("UUID table with version %i", store->table->version);
else
store->table->version = 1;
INF("UUID table with %i entries", store->table->entry_count);
return 1;
}
EINTERN int
e_uuid_store_shutdown(void)
{
/* Cleanup for shutdown */
if (shm_unlink(OBJECT_NAME) != 0)
{
ERR("shm_unlink failed");
return 0;
}
close(store->shmfd);
free(store);
eina_shutdown();
return 1;
}
Eina_Bool
e_uuid_store_reload(void)
{
/* After crash reload the table with its POSIX object name from memory */
store->shmfd = shm_open(OBJECT_NAME, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG);
if (store->shmfd < 0)
{
INF("shm_open failed");
return EINA_FALSE;
}
return EINA_TRUE;
}
Eina_Bool
e_uuid_store_entry_del(uuid_t uuid)
{
struct uuid_table *table;
int i;
char uuid_string[37];
if (store == NULL) return EINA_FALSE;
table = store->table;
if (table == NULL) return EINA_FALSE;
/* Search through uuid list and delete if found */
for (i = 0; i < UUID_STORE_TABLE_SIZE -1; i++)
{
if (!uuid_compare(table->entries[i].uuid, uuid))
{
uuid_clear(table->entries[i].uuid);
table->entries[i].x = 0;
table->entries[i].x = 0;
table->entries[i].width = 0;
table->entries[i].heigth = 0;
table->entry_count--;
uuid_unparse(uuid, uuid_string);
DBG("Removed entry with UUID %s", uuid_string);
return EINA_TRUE;
}
}
uuid_unparse(uuid, uuid_string);
DBG("NOT removed entry with UUID %s. Entry not found.", uuid_string);
return EINA_FALSE;
}
/* FIXME: Think about having _add and _update functions instead only update */
Eina_Bool
e_uuid_store_entry_update(uuid_t uuid, E_Client *ec)
{
struct uuid_table *table;
int i, index = -1;
char uuid_string[37];
if (store == NULL) return EINA_FALSE;
table = store->table;
if (table == NULL) return EINA_FALSE;
/* Search through uuid list if it already exist if yes update */
for (i = 0; i < UUID_STORE_TABLE_SIZE -1; i++)
{
if (!uuid_compare(table->entries[i].uuid, uuid))
{
table->entries[i].x = ec->x;
table->entries[i].y = ec->y;
table->entries[i].width = ec->client.w;
table->entries[i].heigth = ec->client.h;
uuid_unparse(uuid, uuid_string);
DBG("Updated entry with UUID %s", uuid_string);
return EINA_TRUE;
}
}
/* Find first empty entry */
for (i = 0; i < UUID_STORE_TABLE_SIZE -1; i++)
{
if (uuid_is_null(table->entries[i].uuid))
index = i;
}
if (index == -1)
{
ERR("UUID table full");
return EINA_FALSE;
}
/* We do not have this UUID in the table yet. Create it */
table->entries[index].x = ec->x;
table->entries[index].y = ec->y;
table->entries[index].width = ec->client.w;
table->entries[index].heigth = ec->client.h;
uuid_copy(table->entries[index].uuid, uuid);
table->entry_count++;
uuid_unparse(table->entries[index].uuid, uuid_string);
DBG("Created entry with UUID %s", uuid_string);
return EINA_TRUE;
}

@ -1,36 +0,0 @@
#ifndef E_UUID_STORE_H
#define E_UUID_STORE_H
/* vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0
*/
#define UUID_STORE_TABLE_SIZE 100
struct table_entry {
uuid_t uuid;
/* data structure for per application properties */
Evas_Coord x, y;
Evas_Coord width, heigth;
unsigned int virtual_desktop;
int flags;
};
struct uuid_table {
int version; /* Version to allow future extensions */
unsigned int entry_count; /* Entry counter to allow excat memory consuptions needs? */
/* Global settings like current virtual desktop, screen setup, etc */
struct table_entry entries[UUID_STORE_TABLE_SIZE]; /* FIXME make this more adjustable */
};
struct uuid_store {
struct uuid_table *table;
int shmfd;
};
EINTERN int e_uuid_store_init(void);
EINTERN int e_uuid_store_shutdown(void);
E_API void e_uuid_dump(void);
E_API Eina_Bool e_uuid_store_reload(void);
E_API Eina_Bool e_uuid_store_entry_del(uuid_t uuid);
E_API Eina_Bool e_uuid_store_entry_update(uuid_t uuid, E_Client *ec);
#endif

@ -1,43 +0,0 @@
#ifndef E_SESSION_RECOVERY_SERVER_PROTOCOL_H
#define E_SESSION_RECOVERY_SERVER_PROTOCOL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include "wayland-server.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_interface {
/**
* provide_uuid - (none)
* @uuid: (none)
*/
void (*provide_uuid)(struct wl_client *client,
struct wl_resource *resource,
const char *uuid);
};
#define ZWP_E_SESSION_RECOVERY_UUID 0
#define ZWP_E_SESSION_RECOVERY_UUID_SINCE_VERSION 1
static inline void
zwp_e_session_recovery_send_uuid(struct wl_resource *resource_, const char *uuid)
{
wl_resource_post_event(resource_, ZWP_E_SESSION_RECOVERY_UUID, uuid);
}
#ifdef __cplusplus
}
#endif
#endif

@ -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,
};

@ -0,0 +1,62 @@
#ifndef E_SESSION_RECOVERY_SERVER_PROTOCOL_H
#define E_SESSION_RECOVERY_SERVER_PROTOCOL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stddef.h>
#include "wayland-server.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_interface {
/**
* get_uuid - (none)
* @surface: (none)
*/
void (*get_uuid)(struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *surface);
/**
* set_uuid - (none)
* @surface: (none)
* @uuid: (none)
*/
void (*set_uuid)(struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *surface,
const char *uuid);
/**
* destroy_uuid - (none)
* @surface: (none)
* @uuid: (none)
*/
void (*destroy_uuid)(struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *surface,
const char *uuid);
};
#define ZWP_E_SESSION_RECOVERY_CREATE_UUID 0
#define ZWP_E_SESSION_RECOVERY_CREATE_UUID_SINCE_VERSION 1
static inline void
zwp_e_session_recovery_send_create_uuid(struct wl_resource *resource_, struct wl_resource *surface, const char *uuid)
{
wl_resource_post_event(resource_, ZWP_E_SESSION_RECOVERY_CREATE_UUID, surface, uuid);
}
#ifdef __cplusplus
}
#endif
#endif

@ -1,10 +1,19 @@
<protocol name="e_session_recovery">
<interface name="zwp_e_session_recovery" version="1">
<request name="provide_uuid">
<request name="get_uuid">
<arg name="surface" type="object" interface="wl_surface"/>
</request>
<request name="set_uuid">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="uuid" type="string"/>
</request>
<request name="destroy_uuid">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="uuid" type="string"/>
</request>
<event name="uuid">
<event name="create_uuid">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="uuid" type="string"/>
</event>
</interface>

Loading…
Cancel
Save