add handler for triggering xdg-shell data cleanup on client del

in the case of internal windows, the client is deleted before any surfaces
are destroyed. this requires a special case to perform cleanups in order to
prevent client objects from leaking
This commit is contained in:
Mike Blumenkrantz 2016-12-01 12:11:38 -05:00
parent 41e60d251e
commit 8173c06c4d
4 changed files with 49 additions and 12 deletions

View File

@ -16,7 +16,8 @@ e_shell_surface_destroy(struct wl_resource *resource)
/* get the client for this resource */
ec = wl_resource_get_user_data(resource);
if (!ec) return;
if (e_object_is_del(E_OBJECT(ec))) return;
/* client may be passed here during DEL hook */
if (!ec->comp_data) return;
if (ec->comp_data->grab)
{
@ -143,6 +144,16 @@ e_shell_surface_mouse_down_helper(E_Client *ec, E_Binding_Event_Mouse_Button *ev
e_focus_event_mouse_down(ec);
}
EINTERN E_Shell_Data *
e_shell_data_new(unsigned int version)
{
E_Shell_Data *shd;
shd = E_NEW(E_Shell_Data, 1);
shd->version = version;
return shd;
}
E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Wl_Desktop_Shell" };
E_API void *

View File

@ -11,6 +11,7 @@ EINTERN void e_shell_surface_destroy(struct wl_resource *resource);
EINTERN void e_shell_surface_cb_destroy(struct wl_resource *resource);
EINTERN void e_shell_surface_parent_set(E_Client *ec, struct wl_resource *parent_resource);
EINTERN void e_shell_surface_mouse_down_helper(E_Client *ec, E_Binding_Event_Mouse_Button *ev, Eina_Bool move);
EINTERN E_Shell_Data *e_shell_data_new(unsigned int version);
EINTERN Eina_Bool e_xdg_shell_v5_init(void);
EINTERN Eina_Bool e_xdg_shell_v6_init(void);
@ -24,6 +25,7 @@ struct E_Shell_Data
Eina_List *pending;
struct wl_resource *surface;
void *shell;
unsigned int version;
Eina_Bool fullscreen : 1;
Eina_Bool maximized : 1;
Eina_Bool activated : 1;

View File

@ -686,7 +686,7 @@ _e_xdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resour
cdata->shell.ping = _e_xdg_shell_surface_ping;
cdata->shell.map = _e_xdg_shell_surface_map;
cdata->shell.unmap = _e_xdg_shell_surface_unmap;
cdata->shell.data = E_NEW(E_Shell_Data, 1);
cdata->shell.data = e_shell_data_new(5);
cdata->is_xdg_surface = EINA_TRUE;
/* set toplevel client properties */
@ -776,7 +776,7 @@ _e_xdg_shell_cb_popup_get(struct wl_client *client, struct wl_resource *resource
cdata->shell.ping = _e_xdg_shell_surface_ping;
cdata->shell.map = _e_xdg_shell_surface_map;
cdata->shell.unmap = _e_xdg_shell_surface_unmap;
cdata->shell.data = E_NEW(E_Shell_Data, 1);
cdata->shell.data = e_shell_data_new(5);
cdata->is_xdg_surface = EINA_TRUE;
if (!ec->internal)
@ -878,6 +878,16 @@ _e_xdg_shell_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t
NULL, NULL);
}
static void
_xdg5_client_hook_del(void *d EINA_UNUSED, E_Client *ec)
{
E_Shell_Data *shd = ec->comp_data->shell.data;
if (shd && (shd->version != 5)) return;
if (ec->comp_data->shell.surface)
e_shell_surface_cb_destroy(ec->comp_data->shell.surface);
}
EINTERN Eina_Bool
e_xdg_shell_v5_init(void)
{
@ -888,5 +898,6 @@ e_xdg_shell_v5_init(void)
ERR("Could not create xdg_shell global");
return EINA_FALSE;
}
e_client_hook_add(E_CLIENT_HOOK_DEL, _xdg5_client_hook_del, NULL);
return EINA_TRUE;
}

View File

@ -1266,7 +1266,7 @@ _e_xdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resour
"Client already has XDG shell surface");
return;
}
shd = cdata->shell.data = E_NEW(E_Shell_Data, 1);
shd = cdata->shell.data = e_shell_data_new(6);
shd->width = shd->height = -1;
/* try to create a shell surface */
@ -1320,6 +1320,19 @@ static const struct zxdg_shell_v6_interface _e_xdg_shell_interface =
_e_xdg_shell_cb_pong
};
static void
_xdg6_client_destroy(E_Client *ec)
{
E_Shell_Data *shd;
shd = ec->comp_data->shell.data;
if (shd && (shd->version != 6)) return;
if (ec->comp_data->shell.surface)
e_shell_surface_cb_destroy(ec->comp_data->shell.surface);
if (shd)
e_shell_surface_cb_destroy(shd->surface);
}
static void
_e_xdg_shell_cb_unbind(struct wl_resource *resource)
{
@ -1334,16 +1347,9 @@ _e_xdg_shell_cb_unbind(struct wl_resource *resource)
EINA_LIST_REVERSE_FOREACH_SAFE(v->surfaces, l, ll, res)
{
E_Client *ec = wl_resource_get_user_data(res);
E_Shell_Data *shd;
if (!e_object_is_del(E_OBJECT(ec)))
{
if (ec->comp_data->shell.surface)
e_shell_surface_cb_destroy(ec->comp_data->shell.surface);
shd = ec->comp_data->shell.data;
if (shd)
e_shell_surface_cb_destroy(shd->surface);
}
_xdg6_client_destroy(ec);
v->surfaces = eina_list_remove_list(v->surfaces, l);
}
@ -1374,6 +1380,12 @@ _e_xdg_shell_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t
v, _e_xdg_shell_cb_unbind);
}
static void
_xdg6_client_hook_del(void *d EINA_UNUSED, E_Client *ec)
{
_xdg6_client_destroy(ec);
}
EINTERN Eina_Bool
e_xdg_shell_v6_init(void)
{
@ -1384,5 +1396,6 @@ e_xdg_shell_v6_init(void)
ERR("Could not create xdg_shell global");
return EINA_FALSE;
}
e_client_hook_add(E_CLIENT_HOOK_DEL, _xdg6_client_hook_del, NULL);
return EINA_TRUE;
}