feature: Add support for global_remove in the display listener.

bugfix T151: Catch fatal error from wayland displays and signal apps to exit.

Signed-off-by: Chris Michael <cp.michael@samsung.com>
This commit is contained in:
Chris Michael 2013-06-26 11:52:58 +01:00
parent 6445fea318
commit 3230114ff9
1 changed files with 76 additions and 12 deletions

View File

@ -10,6 +10,7 @@ static Eina_Bool _ecore_wl_shutdown(Eina_Bool close);
static Eina_Bool _ecore_wl_cb_idle_enterer(void *data);
static Eina_Bool _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl);
static void _ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned int id, const char *interface, unsigned int version EINA_UNUSED);
static void _ecore_wl_cb_handle_global_remove(void *data, struct wl_registry *registry EINA_UNUSED, unsigned int id);
static Eina_Bool _ecore_wl_xkb_init(Ecore_Wl_Display *ewd);
static Eina_Bool _ecore_wl_xkb_shutdown(Ecore_Wl_Display *ewd);
static void _ecore_wl_sync_wait(Ecore_Wl_Display *ewd);
@ -18,15 +19,18 @@ static void _ecore_wl_animator_tick_cb_begin(void *data EINA_UNUSED);
static void _ecore_wl_animator_tick_cb_end(void *data EINA_UNUSED);
static void _ecore_wl_animator_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED);
static Eina_Bool _ecore_wl_animator_window_add(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata EINA_UNUSED);
static void _ecore_wl_signal_exit(void);
static void _ecore_wl_signal_exit_free(void *data EINA_UNUSED, void *event);
/* local variables */
static int _ecore_wl_init_count = 0;
static Eina_Bool _ecore_wl_animator_busy = EINA_FALSE;
static Eina_Bool _ecore_wl_fatal_error = EINA_FALSE;
static const struct wl_registry_listener _ecore_wl_registry_listener =
{
_ecore_wl_cb_handle_global,
NULL // handle_global_remove
_ecore_wl_cb_handle_global_remove
};
static const struct wl_callback_listener _ecore_wl_sync_listener =
@ -160,6 +164,8 @@ ecore_wl_init(const char *name)
wl_registry_add_listener(_ecore_wl_disp->wl.registry,
&_ecore_wl_registry_listener, _ecore_wl_disp);
/* NB: Hmmm, should we display_dispatch here ?? */
if (!_ecore_wl_xkb_init(_ecore_wl_disp))
{
ERR("Could not initialize XKB");
@ -348,7 +354,7 @@ _ecore_wl_shutdown(Eina_Bool close)
if (_ecore_wl_disp->idle_enterer)
ecore_idle_enterer_del(_ecore_wl_disp->idle_enterer);
if (close)
if ((close) && (!_ecore_wl_fatal_error))
{
Ecore_Wl_Output *out, *tout;
Ecore_Wl_Input *in, *tin;
@ -399,17 +405,32 @@ static Eina_Bool
_ecore_wl_cb_idle_enterer(void *data)
{
Ecore_Wl_Display *ewd;
int ret;
int ret = 0;
if (_ecore_wl_fatal_error) return ECORE_CALLBACK_CANCEL;
if (!(ewd = data)) return ECORE_CALLBACK_RENEW;
ret = wl_display_get_error(ewd->wl.display);
if (ret < 0) goto err;
ret = wl_display_dispatch_pending(ewd->wl.display);
if (ret < 0) goto err;
ret = wl_display_flush(ewd->wl.display);
if ((ret < 0) && (errno == EAGAIN))
ecore_main_fd_handler_active_set(ewd->fd_hdl,
(ECORE_FD_READ | ECORE_FD_WRITE));
else if (ret < 0)
return ECORE_CALLBACK_RENEW;
err:
if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
{
/* FIXME: need do error processing? */
_ecore_wl_fatal_error = EINA_TRUE;
/* raise exit signal */
_ecore_wl_signal_exit();
}
return ECORE_CALLBACK_RENEW;
@ -419,9 +440,12 @@ static Eina_Bool
_ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl)
{
Ecore_Wl_Display *ewd;
int ret = 0;
/* LOGFN(__FILE__, __LINE__, __FUNCTION__); */
if (_ecore_wl_fatal_error) return ECORE_CALLBACK_CANCEL;
if (!(ewd = data)) return ECORE_CALLBACK_RENEW;
/* FIXME: This should also catch ECORE_FD_ERROR and exit */
@ -429,18 +453,20 @@ _ecore_wl_cb_handle_data(void *data, Ecore_Fd_Handler *hdl)
/* wl_display_dispatch_pending(ewd->wl.display); */
if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_READ))
wl_display_dispatch(ewd->wl.display);
ret = wl_display_dispatch(ewd->wl.display);
else if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_WRITE))
{
int ret = 0;
ret = wl_display_flush(ewd->wl.display);
if (ret == 0)
ecore_main_fd_handler_active_set(hdl, ECORE_FD_READ);
else if ((ret == -1) && (errno != EAGAIN))
{
/* FIXME: need do error processing? */
}
}
if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
{
_ecore_wl_fatal_error = EINA_TRUE;
/* raise exit signal */
_ecore_wl_signal_exit();
}
return ECORE_CALLBACK_RENEW;
@ -508,6 +534,25 @@ _ecore_wl_cb_handle_global(void *data, struct wl_registry *registry, unsigned in
}
}
static void
_ecore_wl_cb_handle_global_remove(void *data, struct wl_registry *registry EINA_UNUSED, unsigned int id)
{
Ecore_Wl_Display *ewd;
Ecore_Wl_Global *global, *tmp;
LOGFN(__FILE__, __LINE__, __FUNCTION__);
ewd = data;
wl_list_for_each_safe(global, tmp, &ewd->globals, link)
{
if (global->id != id) continue;
wl_list_remove(&global->link);
free(global->interface);
free(global);
}
}
static Eina_Bool
_ecore_wl_xkb_init(Ecore_Wl_Display *ewd)
{
@ -601,3 +646,22 @@ _ecore_wl_animator_window_add(const Eina_Hash *hash EINA_UNUSED, const void *key
return EINA_TRUE;
}
static void
_ecore_wl_signal_exit(void)
{
Ecore_Event_Signal_Exit *ev;
if (!(ev = calloc(1, sizeof(Ecore_Event_Signal_Exit))))
return;
ev->quit = 1;
ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, ev,
_ecore_wl_signal_exit_free, NULL);
}
static void
_ecore_wl_signal_exit_free(void *data EINA_UNUSED, void *event)
{
free(event);
}