#ifdef HAVE_CONFIG_H # include #endif #include #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"