efl/src/lib/ecore/efl_loop_handler.c

342 lines
9.2 KiB
C

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Ecore.h>
#include "ecore_private.h"
#define MY_CLASS EFL_LOOP_HANDLER_CLASS
//////////////////////////////////////////////////////////////////////////
typedef struct _Efl_Loop_Handler_Data Efl_Loop_Handler_Data;
struct _Efl_Loop_Handler_Data
{
Eo *loop;
Efl_Loop_Data *loop_data;
Ecore_Fd_Handler *handler_fd;
Ecore_Win32_Handler *handler_win32;
void *win32;
int fd;
struct {
unsigned short read;
unsigned short write;
unsigned short error;
unsigned short buffer;
unsigned short prepare;
} references;
Efl_Loop_Handler_Flags flags : 8;
Eina_Bool file : 1;
Eina_Bool constructed : 1;
Eina_Bool finalized : 1;
};
//////////////////////////////////////////////////////////////////////////
static Eina_Bool _cb_handler_fd(void *data, Ecore_Fd_Handler *fd_handler);
static Eina_Bool _cb_handler_buffer(void *data, Ecore_Fd_Handler *fd_handler);
static Eina_Bool _cb_handler_win32(void *data, Ecore_Win32_Handler *win32_handler);
static void _cb_handler_prepare(void *data, Ecore_Fd_Handler *fd_handler);
//////////////////////////////////////////////////////////////////////////
static void
_handler_clear(Efl_Loop_Handler_Data *pd)
{
Eo *obj = pd->loop;
Efl_Loop_Data *loop = pd->loop_data;
if (pd->handler_fd)
{
_ecore_main_fd_handler_del(obj, loop, pd->handler_fd);
pd->handler_fd = NULL;
}
else if (pd->handler_win32)
{
_ecore_main_win32_handler_del(obj, loop, pd->handler_win32);
pd->handler_win32 = NULL;
}
}
static Ecore_Fd_Handler_Flags
_handler_flags_get(Efl_Loop_Handler_Data *pd)
{
return (((pd->flags & EFL_LOOP_HANDLER_FLAGS_READ) &&
(pd->references.read > 0)) ? ECORE_FD_READ : 0) |
(((pd->flags & EFL_LOOP_HANDLER_FLAGS_WRITE) &&
(pd->references.write > 0)) ? ECORE_FD_WRITE : 0) |
(((pd->flags & EFL_LOOP_HANDLER_FLAGS_ERROR) &&
(pd->references.error > 0)) ? ECORE_FD_ERROR : 0);
}
static void
_handler_active_update(Eo *obj, Efl_Loop_Handler_Data *pd)
{
Ecore_Fd_Handler_Flags flags = _handler_flags_get(pd);
ecore_main_fd_handler_active_set(pd->handler_fd, flags);
if (pd->references.prepare)
ecore_main_fd_handler_prepare_callback_set
(pd->handler_fd, _cb_handler_prepare, obj);
else
ecore_main_fd_handler_prepare_callback_set
(pd->handler_fd, NULL, NULL);
}
static void
_handler_reset(Eo *obj, Efl_Loop_Handler_Data *pd)
{
if ((pd->fd < 0) && (!pd->win32))
{
_handler_clear(pd);
return;
}
if ((!pd->constructed) || (!pd->finalized)) return;
if (pd->fd >= 0)
{
Ecore_Fd_Cb buffer_func = NULL;
void *buffer_data = NULL;
if (pd->references.buffer > 0)
{
buffer_func = _cb_handler_buffer;
buffer_data = obj;
}
if (pd->handler_fd)
_handler_active_update(obj, pd);
else
{
pd->handler_fd = _ecore_main_fd_handler_add
(pd->loop, pd->loop_data, obj, pd->fd, _handler_flags_get(pd),
_cb_handler_fd, obj, buffer_func, buffer_data,
pd->file ? EINA_TRUE : EINA_FALSE);
if (pd->handler_fd) _handler_active_update(obj, pd);
}
}
else if (pd->win32)
{
pd->handler_win32 = _ecore_main_win32_handler_add
(pd->loop, pd->loop_data, obj, pd->win32, _cb_handler_win32, obj);
}
}
static Eina_Bool
_event_references_update(Efl_Loop_Handler_Data *pd, const Efl_Event *event, int increment)
{
const Efl_Callback_Array_Item_Full *array = event->info;
int i;
Eina_Bool need_reset = EINA_FALSE;
for (i = 0; array[i].desc != NULL; i++)
{
#define REFERENCES_MAP(_desc, _refs) \
if (array[i].desc == _desc) { \
pd->references._refs += increment; \
need_reset = EINA_TRUE; \
continue; \
}
REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_READ, read);
REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_WRITE, write);
REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_ERROR, error);
REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_BUFFER, buffer);
REFERENCES_MAP(EFL_LOOP_HANDLER_EVENT_PREPARE, prepare);
}
return need_reset;
}
//////////////////////////////////////////////////////////////////////////
static Eina_Bool
_cb_handler_fd(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED)
{
Eo *obj = data;
efl_ref(obj);
if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_READ, NULL);
if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_WRITE, NULL);
if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_ERROR, NULL);
efl_unref(obj);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_cb_handler_buffer(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED)
{
Eo *obj = data;
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_BUFFER, NULL);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_cb_handler_win32(void *data, Ecore_Win32_Handler *win32_handler EINA_UNUSED)
{
Eo *obj = data;
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_READ, NULL);
return ECORE_CALLBACK_RENEW;
}
static void
_cb_handler_prepare(void *data, Ecore_Fd_Handler *fd_handler EINA_UNUSED)
{
Eo *obj = data;
efl_event_callback_call(obj, EFL_LOOP_HANDLER_EVENT_PREPARE, NULL);
}
static void
_cb_event_callback_add(void *data, const Efl_Event *event)
{
Efl_Loop_Handler_Data *pd = data;
if (_event_references_update(pd, event, 1))
_handler_reset(event->object, pd);
}
static void
_cb_event_callback_del(void *data, const Efl_Event *event)
{
Efl_Loop_Handler_Data *pd = data;
if (_event_references_update(pd, event, -1))
_handler_reset(event->object, pd);
}
//////////////////////////////////////////////////////////////////////////
EFL_CALLBACKS_ARRAY_DEFINE(_event_callback_watch,
{ EFL_EVENT_CALLBACK_ADD, _cb_event_callback_add },
{ EFL_EVENT_CALLBACK_DEL, _cb_event_callback_del });
static void
_efl_loop_handler_active_set(Eo *obj, Efl_Loop_Handler_Data *pd, Efl_Loop_Handler_Flags flags)
{
pd->flags = flags;
_handler_reset(obj, pd);
}
static Efl_Loop_Handler_Flags
_efl_loop_handler_active_get(const Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd)
{
return pd->flags;
}
static void
_efl_loop_handler_fd_set(Eo *obj, Efl_Loop_Handler_Data *pd, int fd)
{
pd->fd = fd;
pd->file = EINA_FALSE;
pd->win32 = NULL;
_handler_reset(obj, pd);
}
static int
_efl_loop_handler_fd_get(const Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd)
{
if (pd->win32) return -1;
return pd->file ? -1 : pd->fd;
}
static void
_efl_loop_handler_fd_file_set(Eo *obj, Efl_Loop_Handler_Data *pd, int fd)
{
pd->fd = fd;
pd->file = EINA_TRUE;
pd->win32 = NULL;
_handler_reset(obj, pd);
}
static int
_efl_loop_handler_fd_file_get(const Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd)
{
if (pd->win32) return -1;
return pd->file ? pd->fd : -1;
}
static void
_efl_loop_handler_win32_set(Eo *obj, Efl_Loop_Handler_Data *pd, void *handle)
{
pd->fd = -1;
pd->file = EINA_FALSE;
pd->win32 = handle;
_handler_reset(obj, pd);
}
static void *
_efl_loop_handler_win32_get(const Eo *obj EINA_UNUSED, Efl_Loop_Handler_Data *pd)
{
return pd->win32;
}
static void
_efl_loop_handler_efl_object_parent_set(Eo *obj, Efl_Loop_Handler_Data *pd, Efl_Object *parent)
{
efl_parent_set(efl_super(obj, MY_CLASS), parent);
if ((!pd->constructed) || (!pd->finalized)) return;
_handler_clear(pd);
if (pd->loop)
{
pd->loop_data->fd_handlers_obj = eina_list_remove
(pd->loop_data->fd_handlers_obj, obj);
pd->loop = NULL;
pd->loop_data = NULL;
}
if (parent == NULL) return;
pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS);
pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS);
if (pd->loop_data)
pd->loop_data->fd_handlers_obj =
eina_list_append(pd->loop_data->fd_handlers_obj, obj);
_handler_reset(obj, pd);
}
static Efl_Object *
_efl_loop_handler_efl_object_constructor(Eo *obj, Efl_Loop_Handler_Data *pd)
{
efl_constructor(efl_super(obj, MY_CLASS));
efl_event_callback_array_add(obj, _event_callback_watch(), pd);
pd->constructed = EINA_TRUE;
return obj;
}
static Efl_Object *
_efl_loop_handler_efl_object_finalize(Eo *obj, Efl_Loop_Handler_Data *pd)
{
pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS);
pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS);
if (pd->loop_data)
pd->loop_data->fd_handlers_obj =
eina_list_append(pd->loop_data->fd_handlers_obj, obj);
pd->finalized = EINA_TRUE;
_handler_reset(obj, pd);
return efl_finalize(efl_super(obj, MY_CLASS));
}
static void
_efl_loop_handler_efl_object_destructor(Eo *obj, Efl_Loop_Handler_Data *pd)
{
if (pd->loop_data)
pd->loop_data->fd_handlers_obj =
eina_list_remove(pd->loop_data->fd_handlers_obj, obj);
_handler_clear(pd);
efl_destructor(efl_super(obj, MY_CLASS));
}
#include "efl_loop_handler.eo.c"