summaryrefslogtreecommitdiff
path: root/src/event.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/event.c')
-rw-r--r--src/event.c930
1 files changed, 661 insertions, 269 deletions
diff --git a/src/event.c b/src/event.c
index 0604c11..64f46ca 100644
--- a/src/event.c
+++ b/src/event.c
@@ -29,7 +29,8 @@
#include <Eina.h>
#include <Ecore.h>
#include <dlog.h>
-#include <livebox-errno.h>
+#include <dynamicbox_errno.h>
+#include <dynamicbox_conf.h>
#include "util.h"
#include "debug.h"
@@ -37,13 +38,18 @@
#include "event.h"
#define EVENT_CH 'e'
+#define EVENT_EXIT 'x'
-#if !defined(ABS_MT_TOOL_X)
-#define ABS_MT_TOOL_X 0x3c /* Center X tool position */
-#endif
+#define PRESSURE 10
+#define DELAY_COMPENSATOR 0.1f
-#if !defined(ABS_MT_TOOL_Y)
-#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */
+#if !defined(EVIOCSCLOCKID)
+/**
+ * @note
+ * I just copy this from the latest input.h file.
+ * It could not be compatible with the latest one.
+ */
+#define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */
#endif
int errno;
@@ -58,13 +64,20 @@ static struct info {
Ecore_Fd_Handler *event_handler;
struct event_data event_data;
+ struct event_data skipped_event_data;
Eina_List *event_listener_list;
Eina_List *reactivate_list;
+
+ enum event_handler_activate_type event_handler_activated;
+ int timestamp_updated;
} s_info = {
+ .event_handler_activated = EVENT_HANDLER_DEACTIVATED,
.event_list = NULL,
.handle = -1,
.event_handler = NULL,
+ .evt_pipe = { -1, -1 },
+ .tcb_pipe = { -1, -1 },
.event_data = {
.x = -1,
@@ -74,105 +87,369 @@ static struct info {
.keycode = 0,
},
+ .skipped_event_data = {
+ .x = -1,
+ .y = -1,
+ .device = -1,
+ .slot = -1,
+ .keycode = 0,
+ },
+
.event_listener_list = NULL,
.reactivate_list = NULL,
+ .timestamp_updated = 0,
};
struct event_listener {
int (*event_cb)(enum event_state state, struct event_data *event, void *data);
void *cbdata;
+ enum event_state prev_state;
enum event_state state;
-#if defined(_USE_ECORE_TIME_GET)
double tv;
-#else
- struct timeval tv; /* Recording Activate / Deactivate time */
-#endif
int x; /* RelX */
int y; /* RelY */
};
-static int activate_thread(void);
+static int event_control_fini(void);
HAPI int event_init(void)
{
int ret;
+
ret = pthread_mutex_init(&s_info.event_list_lock, NULL);
if (ret != 0) {
ErrPrint("Mutex: %s\n", strerror(ret));
- return LB_STATUS_ERROR_FAULT;
+ return DBOX_STATUS_ERROR_FAULT;
}
- return LB_STATUS_SUCCESS;
+
+ return DBOX_STATUS_ERROR_NONE;
}
HAPI int event_fini(void)
{
int ret;
+
+ event_control_fini();
+
ret = pthread_mutex_destroy(&s_info.event_list_lock);
if (ret != 0) {
ErrPrint("Mutex destroy failed: %s\n", strerror(ret));
}
- return LB_STATUS_SUCCESS;
+
+ return DBOX_STATUS_ERROR_NONE;
}
-static inline int processing_input_event(struct input_event *event)
+/*
+ * This function can be called Event Thread.
+ */
+static int push_event_item(void)
{
struct event_data *item;
- switch (event->type) {
- case EV_SYN:
- switch (event->code) {
- break;
- case SYN_CONFIG:
- break;
- case SYN_MT_REPORT:
- case SYN_REPORT:
- if (s_info.event_data.x < 0 || s_info.event_data.y < 0) {
- /* Waiting full event packet */
- break;
- }
+ if (s_info.event_data.x < 0 || s_info.event_data.y < 0) {
+ /* Waiting full event packet */
+ return DBOX_STATUS_ERROR_NONE;
+ }
- item = malloc(sizeof(*item));
- if (item) {
- char event_ch = EVENT_CH;
+ item = malloc(sizeof(*item));
+ if (item) {
+ char event_ch = EVENT_CH;
-#if defined(_USE_ECORE_TIME_GET)
- s_info.event_data.tv = ecore_time_get();
-#else
- if (gettimeofday(&s_info.event_data.tv, NULL) < 0) {
- ErrPrint("gettimeofday: %s\n", strerror(errno));
- }
+ memcpy(item, &s_info.event_data, sizeof(*item));
+
+ CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
+ s_info.event_list = eina_list_append(s_info.event_list, item);
+ CRITICAL_SECTION_END(&s_info.event_list_lock);
+
+ if (write(s_info.evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
+ ErrPrint("Unable to send an event: %s\n", strerror(errno));
+ return DBOX_STATUS_ERROR_IO_ERROR;
+ }
+
+ /* Take a breathe */
+ pthread_yield();
+ } else {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ }
+
+ return DBOX_STATUS_ERROR_NONE;
+}
+
+static double current_time_get(void)
+{
+ double ret;
+
+ if (DYNAMICBOX_CONF_USE_GETTIMEOFDAY) {
+ struct timeval tv;
+ if (gettimeofday(&tv, NULL) < 0) {
+ ErrPrint("gettimeofday: %s\n", strerror(errno));
+ ret = ecore_time_get();
+ } else {
+ ret = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0f);
+ }
+ } else {
+ ret = ecore_time_get();
+ }
+
+ return ret;
+}
+
+static void update_timestamp(struct input_event *event)
+{
+ /*
+ * Input event uses timeval instead of timespec,
+ * but its value is same as MONOTIC CLOCK TIME
+ * So we should handles it properly.
+ */
+ s_info.event_data.tv = (double)event->time.tv_sec + (double)event->time.tv_usec / 1000000.0f;
+ s_info.timestamp_updated = 1;
+}
+
+static void processing_ev_abs(struct input_event *event)
+{
+ switch (event->code) {
+#if defined(ABS_X)
+ case ABS_X:
+ break;
+#endif
+#if defined(ABS_Y)
+ case ABS_Y:
+ break;
+#endif
+#if defined(ABS_Z)
+ case ABS_Z:
+ break;
+#endif
+#if defined(ABS_RX)
+ case ABS_RX:
+ break;
+#endif
+#if defined(ABS_RY)
+ case ABS_RY:
+ break;
+#endif
+#if defined(ABS_RZ)
+ case ABS_RZ:
+ break;
+#endif
+#if defined(ABS_THROTTLE)
+ case ABS_THROTTLE:
+ break;
+#endif
+#if defined(ABS_RUDDER)
+ case ABS_RUDDER:
+ break;
+#endif
+#if defined(ABS_WHEEL)
+ case ABS_WHEEL:
+ break;
+#endif
+#if defined(ABS_GAS)
+ case ABS_GAS:
+ break;
+#endif
+#if defined(ABS_BRAKE)
+ case ABS_BRAKE:
+ break;
+#endif
+#if defined(ABS_HAT0X)
+ case ABS_HAT0X:
+ break;
+#endif
+#if defined(ABS_HAT0Y)
+ case ABS_HAT0Y:
+ break;
+#endif
+#if defined(ABS_HAT1X)
+ case ABS_HAT1X:
+ break;
+#endif
+#if defined(ABS_HAT1Y)
+ case ABS_HAT1Y:
+ break;
+#endif
+#if defined(ABS_HAT2X)
+ case ABS_HAT2X:
+ break;
+#endif
+#if defined(ABS_HAT2Y)
+ case ABS_HAT2Y:
+ break;
+#endif
+#if defined(ABS_HAT3X)
+ case ABS_HAT3X:
+ break;
+#endif
+#if defined(ABS_HAT3Y)
+ case ABS_HAT3Y:
+ break;
+#endif
+#if defined(ABS_PRESSURE)
+ case ABS_PRESSURE:
+ break;
+#endif
+#if defined(ABS_TILT_X)
+ case ABS_TILT_X:
+ break;
+#endif
+#if defined(ABS_TILT_Y)
+ case ABS_TILT_Y:
+ break;
+#endif
+#if defined(ABS_TOOL_WIDTH)
+ case ABS_TOOL_WIDTH:
+ break;
+#endif
+#if defined(ABS_VOLUME)
+ case ABS_VOLUME:
+ break;
+#endif
+#if defined(ABS_MISC)
+ case ABS_MISC:
+ break;
+#endif
+#if defined(ABS_DISTANCE)
+ case ABS_DISTANCE:
+ s_info.event_data.distance = event->value;
+ break;
+#endif
+#if defined(ABS_MT_POSITION_X)
+ case ABS_MT_POSITION_X:
+ s_info.event_data.x = event->value;
+ break;
+#endif
+#if defined(ABS_MT_POSITION_Y)
+ case ABS_MT_POSITION_Y:
+ s_info.event_data.y = event->value;
+ break;
+#endif
+#if defined(ABS_MT_SLOT)
+ case ABS_MT_SLOT:
+ s_info.event_data.slot = event->value;
+ break;
+#endif
+#if defined(ABS_MT_TRACKING_ID)
+ case ABS_MT_TRACKING_ID:
+ s_info.event_data.device = event->value;
+ break;
+#endif
+#if defined(ABS_MT_TOUCH_MAJOR)
+ case ABS_MT_TOUCH_MAJOR:
+ s_info.event_data.touch.major = event->value;
+ break;
+#endif
+#if defined(ABS_MT_TOUCH_MINOR)
+ case ABS_MT_TOUCH_MINOR:
+ s_info.event_data.touch.minor = event->value;
+ break;
+#endif
+#if defined(ABS_MT_WIDTH_MAJOR)
+ case ABS_MT_WIDTH_MAJOR:
+ s_info.event_data.width.major = event->value;
+ break;
+#endif
+#if defined(ABS_MT_WIDTH_MINOR)
+ case ABS_MT_WIDTH_MINOR:
+ s_info.event_data.width.minor = event->value;
+ break;
+#endif
+#if defined(ABS_MT_ORIENTATION)
+ case ABS_MT_ORIENTATION:
+ s_info.event_data.orientation = event->value;
+ break;
#endif
+#if defined(ABS_MT_PRESSURE)
+ case ABS_MT_PRESSURE:
+ s_info.event_data.pressure = event->value;
+ break;
+#endif
+#if defined(ABS_MT_TOOL_X)
+ case ABS_MT_TOOL_X:
+ DbgPrint("TOOL_X: %d\n", event->value);
+ break;
+#endif
+#if defined(ABS_MT_TOOL_Y)
+ case ABS_MT_TOOL_Y:
+ DbgPrint("TOOL_Y: %d\n", event->value);
+ break;
+#endif
+#if defined(ABS_MT_TOOL_TYPE)
+ case ABS_MT_TOOL_TYPE:
+ DbgPrint("TOOL_TYPE: %d\n", event->value);
+ break;
+#endif
+#if defined(ABS_MT_BLOB_ID)
+ case ABS_MT_BLOB_ID:
+ DbgPrint("BLOB_ID: %d\n", event->value);
+ break;
+#endif
+#if defined(ABS_MT_DISTANCE)
+ case ABS_MT_DISTANCE:
+ DbgPrint("DISTANCE: %d\n", event->value);
+ break;
+#endif
+#if defined(ABS_MT_PALM)
+ case ABS_MT_PALM:
+ DbgPrint("PALM: %d\n", event->value);
+ break;
+#endif
+ default:
+#if defined(ABS_MT_COMPONENT)
+ if (event->code == ABS_MT_COMPONENT) {
+ DbgPrint("COMPONENT: %d\n", event->value);
+ break;
+ }
+#endif
+#if defined(ABS_MT_ANGLE)
+ if (event->code == ABS_MT_ANGLE) {
+ DbgPrint("ANGLE: %d\n", event->value);
+ break;
+ }
+#endif
+#if defined(ABS_MT_SUMSIZE)
+ if (event->code == ABS_MT_SUMSIZE) {
+ DbgPrint("SUMSIZE: %d\n", event->value);
+ break;
+ }
+#endif
+ break;
+ }
- memcpy(item, &s_info.event_data, sizeof(*item));
+ return;
+}
- CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
- s_info.event_list = eina_list_append(s_info.event_list, item);
- CRITICAL_SECTION_END(&s_info.event_list_lock);
+/*
+ * Called by Event Thread
+ */
+static inline int processing_input_event(struct input_event *event)
+{
+ int ret;
- if (write(s_info.evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
- ErrPrint("Unable to send an event: %s\n", strerror(errno));
- return LB_STATUS_ERROR_IO;
- }
+ if (s_info.timestamp_updated == 0) {
+ update_timestamp(event);
+ }
- /* Take a breathe */
- pthread_yield();
- } else {
- ErrPrint("Heap: %s\n", strerror(errno));
+ switch (event->type) {
+ case EV_SYN:
+ switch (event->code) {
+ case SYN_CONFIG:
+ break;
+ case SYN_MT_REPORT:
+ case SYN_REPORT:
+ s_info.timestamp_updated = 0;
+ ret = push_event_item();
+ if (ret < 0) {
+ return ret;
}
- if (s_info.event_data.device < 0) {
- s_info.event_data.x = -1;
- s_info.event_data.y = -1;
- s_info.event_data.slot = -1;
- }
break;
- /*
+#if defined(SYN_DROPPED)
case SYN_DROPPED:
DbgPrint("EV_SYN, SYN_DROPPED\n");
break;
- */
+#endif
default:
DbgPrint("EV_SYN, 0x%x\n", event->code);
break;
@@ -183,66 +460,25 @@ static inline int processing_input_event(struct input_event *event)
s_info.event_data.keycode = event->value;
break;
case EV_REL:
+ DbgPrint("EV_REL: 0x%X\n", event->value);
break;
case EV_ABS:
- switch (event->code) {
- case ABS_DISTANCE:
- s_info.event_data.distance = event->value;
- break;
- case ABS_MT_TOOL_X:
- case ABS_MT_TOOL_Y:
- break;
- case ABS_MT_POSITION_X:
- s_info.event_data.x = event->value;
- break;
- case ABS_MT_POSITION_Y:
- s_info.event_data.y = event->value;
- break;
- case ABS_MT_SLOT:
- s_info.event_data.slot = event->value;
- break;
- case ABS_MT_TRACKING_ID:
- s_info.event_data.device = event->value;
- break;
- case ABS_MT_TOUCH_MAJOR:
- s_info.event_data.touch.major = event->value;
- break;
- case ABS_MT_TOUCH_MINOR:
- s_info.event_data.touch.minor = event->value;
- break;
- case ABS_MT_WIDTH_MAJOR:
- s_info.event_data.width.major = event->value;
- break;
- case ABS_MT_WIDTH_MINOR:
- s_info.event_data.width.minor = event->value;
- break;
- default:
- DbgPrint("EV_ABS, 0x%x\n", event->code);
- break;
- }
+ processing_ev_abs(event);
break;
case EV_MSC:
- break;
case EV_SW:
- break;
case EV_LED:
- break;
case EV_SND:
- break;
case EV_REP:
- break;
case EV_FF:
- break;
case EV_PWR:
- break;
case EV_FF_STATUS:
- break;
default:
DbgPrint("0x%X, 0x%X\n", event->type, event->code);
break;
}
- return LB_STATUS_SUCCESS;
+ return DBOX_STATUS_ERROR_NONE;
}
static void *event_thread_main(void *data)
@@ -254,8 +490,7 @@ static void *event_thread_main(void *data)
int offset = 0;
int readsize = 0;
int fd;
-
- DbgPrint("Initiated\n");
+ char event_ch;
while (1) {
FD_ZERO(&set);
@@ -274,7 +509,7 @@ static void *event_thread_main(void *data)
break;
} else if (ret == 0) {
ErrPrint("Timeout expired\n");
- ret = LB_STATUS_ERROR_TIMEOUT;
+ ret = DBOX_STATUS_ERROR_TIMEOUT;
break;
}
@@ -282,7 +517,7 @@ static void *event_thread_main(void *data)
readsize = read(s_info.handle, ptr + offset, sizeof(input_event) - offset);
if (readsize < 0) {
ErrPrint("Unable to read device: %s / fd: %d / offset: %d / size: %d - %d\n", strerror(errno), s_info.handle, offset, sizeof(input_event), readsize);
- ret = LB_STATUS_ERROR_FAULT;
+ ret = DBOX_STATUS_ERROR_FAULT;
break;
}
@@ -290,48 +525,104 @@ static void *event_thread_main(void *data)
if (offset == sizeof(input_event)) {
offset = 0;
if (processing_input_event(&input_event) < 0) {
- ret = LB_STATUS_ERROR_FAULT;
+ ret = DBOX_STATUS_ERROR_FAULT;
break;
}
}
- }
-
- if (FD_ISSET(s_info.tcb_pipe[PIPE_READ], &set)) {
- char event_ch;
+ /*
+ * If there is input event,
+ * Try again to get the input event.
+ */
+ } else if (!s_info.timestamp_updated && FD_ISSET(s_info.tcb_pipe[PIPE_READ], &set)) {
+ /*!
+ * Check the s_info.timestamp_updated flag.
+ * If it is not ZERO, it means, there is event to be processed.
+ * So we have to wait it to be finished.
+ */
if (read(s_info.tcb_pipe[PIPE_READ], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
ErrPrint("Unable to read TCB_PIPE: %s\n", strerror(errno));
}
- ret = LB_STATUS_ERROR_CANCEL;
+ ret = DBOX_STATUS_ERROR_CANCEL;
break;
}
}
+ event_ch = EVENT_EXIT;
+ if (write(s_info.evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
+ ErrPrint("Unable to send an event: %s\n", strerror(errno));
+ }
+
return (void *)ret;
}
+static int invoke_event_cb(struct event_listener *listener, struct event_data *item)
+{
+ struct event_data modified_item;
+
+ memcpy(&modified_item, item, sizeof(modified_item));
+
+ modified_item.x -= listener->x;
+ modified_item.y -= listener->y;
+
+ if (!DYNAMICBOX_CONF_USE_EVENT_TIME) {
+ item->tv = current_time_get();
+ }
+
+ if (listener->event_cb(listener->state, &modified_item, listener->cbdata) < 0) {
+ if (eina_list_data_find(s_info.event_listener_list, listener)) {
+ s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
+ DbgFree(listener);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static inline void clear_all_listener_list(void)
{
struct event_listener *listener;
enum event_state next_state;
+ struct event_data event_data;
+ struct event_data *p_event_data;
Eina_List *l;
Eina_List *n;
- s_info.event_handler = NULL;
- CLOSE_PIPE(s_info.evt_pipe);
+ DbgPrint("event listeners: %d\n", eina_list_count(s_info.event_listener_list));
+
+ if (s_info.event_data.x == -1 || s_info.event_data.y == -1) {
+ memcpy(&s_info.event_data, &s_info.skipped_event_data, sizeof(s_info.event_data));
+ DbgPrint("Use skipped event: %dx%d\n", s_info.skipped_event_data.x, s_info.skipped_event_data.y);
+ }
while (s_info.event_listener_list) {
EINA_LIST_FOREACH_SAFE(s_info.event_listener_list, l, n, listener) {
+
+ DbgPrint("listener[%p] prev[%x] state[%x]\n", listener, listener->prev_state, listener->state);
+
switch (listener->state) {
case EVENT_STATE_ACTIVATE:
+ p_event_data = &s_info.event_data;
next_state = EVENT_STATE_ACTIVATED;
break;
case EVENT_STATE_ACTIVATED:
+ p_event_data = &s_info.event_data;
next_state = EVENT_STATE_DEACTIVATE;
break;
case EVENT_STATE_DEACTIVATE:
- next_state = EVENT_STATE_DEACTIVATED;
+ memcpy(&event_data, &s_info.event_data, sizeof(event_data));
+ p_event_data = &event_data;
+
+ if (listener->prev_state == EVENT_STATE_ACTIVATE) {
+ /* There is no move event. we have to emulate it */
+ DbgPrint ("Let's emulate move event (%dx%d)\n", p_event_data->x, p_event_data->y);
+ listener->state = EVENT_STATE_ACTIVATE;
+ next_state = EVENT_STATE_ACTIVATED;
+ } else {
+ next_state = EVENT_STATE_DEACTIVATED;
+ }
break;
case EVENT_STATE_DEACTIVATED:
default:
@@ -340,19 +631,32 @@ static inline void clear_all_listener_list(void)
continue;
}
- if (listener->event_cb(listener->state, &s_info.event_data, listener->cbdata) < 0) {
- if (eina_list_data_find(s_info.event_listener_list, listener)) {
- s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
- DbgFree(listener);
- continue;
- }
+ if (invoke_event_cb(listener, p_event_data)) {
+ continue;
}
+ /*!
+ * Changing state of listener will affect to the event collecting thread.
+ */
+ listener->prev_state = listener->state;
listener->state = next_state;
}
}
}
+static int compare_timestamp(struct event_listener *listener, struct event_data *item)
+{
+ int ret;
+ if (listener->tv > item->tv) {
+ ret = 1;
+ } else if (listener->tv < item->tv) {
+ ret = -1;
+ } else {
+ ret = 0;
+ }
+ return ret;
+}
+
static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler)
{
int fd;
@@ -362,8 +666,6 @@ static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler)
Eina_List *l;
Eina_List *n;
enum event_state next_state;
- enum event_state cur_state;
- struct event_data modified_item;
fd = ecore_main_fd_handler_fd_get(handler);
if (fd < 0) {
@@ -376,6 +678,37 @@ static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler)
return ECORE_CALLBACK_CANCEL;
}
+ if (event_ch == EVENT_EXIT) {
+ /*!
+ * If the master gets event exit from evt_pipe,
+ * The event item list should be empty.
+ */
+ if (!s_info.event_list) {
+ /* This callback must has to clear all listeners in this case */
+ ecore_main_fd_handler_del(s_info.event_handler);
+ s_info.event_handler = NULL;
+ clear_all_listener_list();
+
+ EINA_LIST_FREE(s_info.reactivate_list, listener) {
+ s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
+ }
+ DbgPrint("Reactivate: %p\n", s_info.event_listener_list);
+
+ if (s_info.event_listener_list) {
+ if (event_activate_thread(EVENT_HANDLER_ACTIVATED_BY_MOUSE_SET) < 0) {
+ EINA_LIST_FREE(s_info.event_listener_list, listener) {
+ (void)listener->event_cb(EVENT_STATE_ERROR, NULL, listener->cbdata);
+ }
+ }
+ }
+
+ DbgPrint("Event read callback finshed (%p)\n", s_info.event_listener_list);
+ return ECORE_CALLBACK_CANCEL;
+ } else {
+ ErrPrint("Something goes wrong, the event_list is not flushed\n");
+ }
+ }
+
CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
item = eina_list_nth(s_info.event_list, 0);
if (item) {
@@ -383,108 +716,86 @@ static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler)
}
CRITICAL_SECTION_END(&s_info.event_list_lock);
- if (item) {
- EINA_LIST_FOREACH_SAFE(s_info.event_listener_list, l, n, listener) {
- switch (listener->state) {
- case EVENT_STATE_ACTIVATE:
-#if defined(_USE_ECORE_TIME_GET)
- if (listener->tv > item->tv) {
- continue;
- }
-#else
- if (timercmp(&listener->tv, &item->tv, >)) {
- /* Ignore previous events before activating this listener */
- continue;
- }
-#endif
-
- next_state = EVENT_STATE_ACTIVATED;
- cur_state = listener->state;
- break;
- case EVENT_STATE_DEACTIVATE:
-#if defined(_USE_ECORE_TIME_GET)
- if (listener->tv > item->tv) {
- /* Consuming all events occurred while activating this listener */
- cur_state = EVENT_STATE_ACTIVATED;
- next_state = EVENT_STATE_ACTIVATED;
- break;
- }
-#else
- if (timercmp(&listener->tv, &item->tv, >)) {
- /* Consuming all events occurred while activating this listener */
- cur_state = EVENT_STATE_ACTIVATED;
- next_state = EVENT_STATE_ACTIVATED;
- break;
- }
-#endif
-
- cur_state = listener->state;
- next_state = EVENT_STATE_DEACTIVATED;
- break;
- case EVENT_STATE_ACTIVATED:
- cur_state = listener->state;
- next_state = listener->state;
- break;
- case EVENT_STATE_DEACTIVATED:
- default:
- /* Remove this from the list */
- /* Check the item again. the listener can be deleted from the callback */
- if (eina_list_data_find(s_info.event_listener_list, listener)) {
- s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
- DbgFree(listener);
- }
+ if (!item) {
+ ErrPrint("There is no remained event\n");
+ return ECORE_CALLBACK_RENEW;
+ }
+ EINA_LIST_FOREACH_SAFE(s_info.event_listener_list, l, n, listener) {
+ switch (listener->state) {
+ case EVENT_STATE_ACTIVATE:
+ if (compare_timestamp(listener, item) > 0) {
+ memcpy(&s_info.skipped_event_data, item, sizeof(s_info.skipped_event_data));
continue;
}
- memcpy(&modified_item, item, sizeof(modified_item));
- modified_item.x -= listener->x;
- modified_item.y -= listener->y;
-
- if (listener->event_cb(cur_state, &modified_item, listener->cbdata) < 0) {
- if (eina_list_data_find(s_info.event_listener_list, listener)) {
- s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
- DbgFree(listener);
+ next_state = EVENT_STATE_ACTIVATED;
+ break;
+ case EVENT_STATE_DEACTIVATE:
+ if (compare_timestamp(listener, item) < 0) {
+ /* Consuming all events occurred while activating this listener */
+ listener->prev_state = listener->state;
+ listener->state = EVENT_STATE_ACTIVATED;
+ if (invoke_event_cb(listener, item) == 1) {
+ /* listener is deleted */
continue;
}
- }
-
- listener->state = next_state;
- }
- DbgFree(item);
- }
+ listener->prev_state = listener->state;
+ listener->state = EVENT_STATE_DEACTIVATE;
+ } else {
+ memcpy(&s_info.skipped_event_data, item, sizeof(s_info.skipped_event_data));
+ }
- if (s_info.handle < 0 && !s_info.event_list) {
- /* This callback must has to clear all listeners in this case */
- clear_all_listener_list();
+ /* Do not terminate this listener, until this mets EVENT_EXIT */
+ continue;
+ case EVENT_STATE_ACTIVATED:
+ if (compare_timestamp(listener, item) > 0) {
+ DbgPrint("Drop event (%lf > %lf)\n", listener->tv, item->tv);
+ memcpy(&s_info.skipped_event_data, item, sizeof(s_info.skipped_event_data));
+ continue;
+ }
+ next_state = listener->state;
+ break;
+ case EVENT_STATE_DEACTIVATED:
+ default:
+ /* Remove this from the list */
+ /* Check the item again. the listener can be deleted from the callback */
+ if (eina_list_data_find(s_info.event_listener_list, listener)) {
+ s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
+ DbgFree(listener);
+ }
- EINA_LIST_FREE(s_info.reactivate_list, listener) {
- s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
+ continue;
}
- if (s_info.event_listener_list) {
- if (activate_thread() < 0) {
- EINA_LIST_FREE(s_info.event_listener_list, listener) {
- (void)listener->event_cb(EVENT_STATE_ERROR, NULL, listener->cbdata);
- }
- }
+ if (invoke_event_cb(listener, item) == 1) {
+ continue;
}
- return ECORE_CALLBACK_CANCEL;
+ listener->prev_state = listener->state;
+ listener->state = next_state;
}
+ DbgFree(item);
+
return ECORE_CALLBACK_RENEW;
}
-static int activate_thread(void)
+static int event_control_init(void)
{
int status;
+ unsigned int clockId = CLOCK_MONOTONIC;
+
+ DbgPrint("Initializing event controller\n");
+ if (s_info.handle != -1) {
+ return DBOX_STATUS_ERROR_NONE;
+ }
- s_info.handle = open(INPUT_PATH, O_RDONLY);
+ s_info.handle = open(DYNAMICBOX_CONF_INPUT_PATH, O_RDONLY);
if (s_info.handle < 0) {
ErrPrint("Unable to access the device: %s\n", strerror(errno));
- return LB_STATUS_ERROR_IO;
+ return DBOX_STATUS_ERROR_IO_ERROR;
}
if (fcntl(s_info.handle, F_SETFD, FD_CLOEXEC) < 0) {
@@ -495,6 +806,13 @@ static int activate_thread(void)
ErrPrint("Error: %s\n", strerror(errno));
}
+ if (DYNAMICBOX_CONF_USE_EVENT_TIME && !DYNAMICBOX_CONF_USE_GETTIMEOFDAY) {
+ DbgPrint("Change timestamp to monotonic\n");
+ if (ioctl(s_info.handle, EVIOCSCLOCKID, &clockId) < 0) {
+ ErrPrint("Error: %s\n", strerror(errno));
+ }
+ }
+
status = pipe2(s_info.evt_pipe, O_CLOEXEC);
if (status < 0) {
ErrPrint("Unable to prepare evt pipe: %s\n", strerror(errno));
@@ -502,7 +820,7 @@ static int activate_thread(void)
ErrPrint("Failed to close handle: %s\n", strerror(errno));
}
s_info.handle = -1;
- return LB_STATUS_ERROR_FAULT;
+ return DBOX_STATUS_ERROR_FAULT;
}
status = pipe2(s_info.tcb_pipe, O_CLOEXEC);
@@ -513,39 +831,98 @@ static int activate_thread(void)
}
s_info.handle = -1;
CLOSE_PIPE(s_info.evt_pipe);
- return LB_STATUS_ERROR_FAULT;
+ return DBOX_STATUS_ERROR_FAULT;
}
- s_info.event_handler = ecore_main_fd_handler_add(s_info.evt_pipe[PIPE_READ], ECORE_FD_READ, event_read_cb, NULL, NULL, NULL);
- if (!s_info.event_handler) {
+ return DBOX_STATUS_ERROR_NONE;
+}
+
+/*!
+ * This function must has to be called after event collecting thread is terminated
+ */
+static int event_control_fini(void)
+{
+ DbgPrint("Finalizing event controller\n");
+ if (s_info.handle != -1) {
if (close(s_info.handle) < 0) {
- ErrPrint("Failed to close handle: %s\n", strerror(errno));
+ ErrPrint("Unable to release the fd: %s\n", strerror(errno));
}
+
s_info.handle = -1;
+ }
- CLOSE_PIPE(s_info.tcb_pipe);
- CLOSE_PIPE(s_info.evt_pipe);
- return LB_STATUS_ERROR_FAULT;
+ if (!eina_list_count(s_info.event_list)) {
+ if (s_info.event_handler) {
+ ecore_main_fd_handler_del(s_info.event_handler);
+ s_info.event_handler = NULL;
+ }
+ clear_all_listener_list();
}
- status = pthread_create(&s_info.tid, NULL, event_thread_main, NULL);
- if (status != 0) {
- ErrPrint("Failed to initiate the thread: %s\n", strerror(status));
+ CLOSE_PIPE(s_info.tcb_pipe);
+ CLOSE_PIPE(s_info.evt_pipe);
+
+ return DBOX_STATUS_ERROR_NONE;
+}
+
+int event_activate_thread(enum event_handler_activate_type activate_type)
+{
+ int ret;
+
+ ret = event_control_init();
+ if (ret != DBOX_STATUS_ERROR_NONE) {
+ return ret;
+ }
+
+ if (s_info.event_handler) {
+ ErrPrint("Event handler is already registered\n");
+ return DBOX_STATUS_ERROR_ALREADY;
+ }
+
+ s_info.event_handler = ecore_main_fd_handler_add(s_info.evt_pipe[PIPE_READ], ECORE_FD_READ, event_read_cb, NULL, NULL, NULL);
+ if (!s_info.event_handler) {
+ ErrPrint("Failed to add monitor for EVT READ\n");
+ return DBOX_STATUS_ERROR_FAULT;
+ }
+
+ ret = pthread_create(&s_info.tid, NULL, event_thread_main, NULL);
+ if (ret != 0) {
+ ErrPrint("Failed to initiate the thread: %s\n", strerror(ret));
ecore_main_fd_handler_del(s_info.event_handler);
s_info.event_handler = NULL;
+ return DBOX_STATUS_ERROR_FAULT;
+ }
- if (close(s_info.handle) < 0) {
- ErrPrint("close: %s\n", strerror(errno));
- }
- s_info.handle = -1;
+ DbgPrint("Event handler activated\n");
+ s_info.event_handler_activated = activate_type;
+ return DBOX_STATUS_ERROR_NONE;
+}
- CLOSE_PIPE(s_info.tcb_pipe);
- CLOSE_PIPE(s_info.evt_pipe);
- return LB_STATUS_ERROR_FAULT;
+int event_deactivate_thread(enum event_handler_activate_type activate_type)
+{
+ int status;
+ void *ret;
+ char event_ch = EVENT_CH;
+
+ if (s_info.event_handler_activated != activate_type) {
+ ErrPrint("Event handler activate type is mismatched\n");
+ return DBOX_STATUS_ERROR_INVALID_PARAMETER;
}
- DbgPrint("Event handler activated\n");
- return LB_STATUS_SUCCESS;
+ /* Terminating thread */
+ if (write(s_info.tcb_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
+ ErrPrint("Unable to write tcb_pipe: %s\n", strerror(errno));
+ }
+
+ status = pthread_join(s_info.tid, &ret);
+ if (status != 0) {
+ ErrPrint("Failed to join a thread: %s\n", strerror(errno));
+ } else {
+ DbgPrint("Thread returns: %p\n", ret);
+ }
+
+ s_info.event_handler_activated = EVENT_HANDLER_DEACTIVATED;
+ return DBOX_STATUS_ERROR_NONE;
}
/*!
@@ -554,36 +931,38 @@ static int activate_thread(void)
HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
{
struct event_listener *listener;
- int ret = LB_STATUS_SUCCESS;
+ int ret = DBOX_STATUS_ERROR_NONE;
+ Eina_List *l;
+
+ EINA_LIST_FOREACH(s_info.event_listener_list, l, listener) {
+ if (listener->event_cb == event_cb && listener->cbdata == data) {
+ ErrPrint("Already registered\n");
+ return DBOX_STATUS_ERROR_ALREADY;
+ }
+ }
listener = malloc(sizeof(*listener));
if (!listener) {
ErrPrint("Heap: %s\n", strerror(errno));
- return LB_STATUS_ERROR_MEMORY;
+ return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
}
-#if defined(_USE_ECORE_TIME_GET)
- listener->tv = ecore_time_get();
-#else
- if (gettimeofday(&listener->tv, NULL) < 0) {
- ErrPrint("gettimeofday: %s\n", strerror(errno));
- DbgFree(listener);
- return LB_STATUS_ERROR_FAULT;
- }
-#endif
+ listener->tv = current_time_get() - DELAY_COMPENSATOR; // Let's use the previous event.
+ DbgPrint("Activated at: %lf (%dx%d)\n", listener->tv, x, y);
listener->event_cb = event_cb;
listener->cbdata = data;
+ listener->prev_state = EVENT_STATE_DEACTIVATED;
listener->state = EVENT_STATE_ACTIVATE;
listener->x = x;
listener->y = y;
- if (s_info.handle < 0) {
+ if (s_info.event_handler_activated == EVENT_HANDLER_DEACTIVATED) {
/*!
* \note
* We don't need to lock to access event_list here.
* If the _sinfo.handle is greater than 0, the event_list will not be touched.
- * But if the s_info.handle is less than 0, it means, there is not thread,
+ * But if the s_info.handle is less than 0, it means, there is no thread,
* so we can access the event_list without lock.
*/
if (s_info.event_list) {
@@ -592,7 +971,7 @@ HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, st
} else {
s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
- if ((ret = activate_thread()) < 0) {
+ if ((ret = event_activate_thread(EVENT_HANDLER_ACTIVATED_BY_MOUSE_SET)) < 0) {
s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
DbgFree(listener);
}
@@ -604,68 +983,81 @@ HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, st
return ret;
}
+HAPI int event_input_fd(void)
+{
+ event_control_init();
+ DbgPrint("Input event handler: %d\n", s_info.handle);
+ return s_info.handle;
+}
+
HAPI int event_deactivate(int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
{
- int status;
- void *ret;
- char event_ch = EVENT_CH;
struct event_listener *listener = NULL;
+ struct event_listener *item;
Eina_List *l;
int keep_thread = 0;
- EINA_LIST_FOREACH(s_info.event_listener_list, l, listener) {
- if (listener->event_cb == event_cb && listener->cbdata == data) {
- listener->state = EVENT_STATE_DEACTIVATE;
+ EINA_LIST_FOREACH(s_info.event_listener_list, l, item) {
+ if (item->event_cb == event_cb && item->cbdata == data) {
+ switch (item->state) {
+ case EVENT_STATE_ACTIVATE:
+ case EVENT_STATE_ACTIVATED:
+ item->prev_state = item->state;
+ item->state = EVENT_STATE_DEACTIVATE;
+ listener = item;
+ break;
+ default:
+ /* Item is already deactivated */
+ break;
+ }
}
- keep_thread += (listener->state == EVENT_STATE_ACTIVATE || listener->state == EVENT_STATE_ACTIVATED);
+ keep_thread += (item->state == EVENT_STATE_ACTIVATE || item->state == EVENT_STATE_ACTIVATED);
}
if (!listener) {
- ErrPrint("Listener is not registered\n");
- return LB_STATUS_ERROR_NOT_EXIST;
+ ErrPrint("Listener is not registered or already deactivated\n");
+ return DBOX_STATUS_ERROR_NOT_EXIST;
}
- if (s_info.handle < 0) {
+ if (s_info.event_handler_activated == EVENT_HANDLER_DEACTIVATED) {
ErrPrint("Event handler is not actiavated\n");
+ s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
DbgFree(listener);
- return LB_STATUS_SUCCESS;
+ return DBOX_STATUS_ERROR_NONE;
}
if (keep_thread) {
- return LB_STATUS_SUCCESS;
+ DbgPrint("Keep thread\n");
+ return DBOX_STATUS_ERROR_NONE;
}
- /* Terminating thread */
- if (write(s_info.tcb_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
- ErrPrint("Unable to write tcb_pipe: %s\n", strerror(errno));
- }
+ event_deactivate_thread(EVENT_HANDLER_ACTIVATED_BY_MOUSE_SET);
- status = pthread_join(s_info.tid, &ret);
- if (status != 0) {
- ErrPrint("Failed to join a thread: %s\n", strerror(errno));
- } else {
- DbgPrint("Thread returns: %p\n", ret);
- }
-
- if (close(s_info.handle) < 0) {
- ErrPrint("Unable to release the fd: %s\n", strerror(errno));
- }
+ return DBOX_STATUS_ERROR_NONE;
+}
- s_info.handle = -1;
- DbgPrint("Event handler deactivated\n");
+HAPI int event_reset_cbdata(int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data, void *new_data)
+{
+ struct event_listener *item;
+ Eina_List *l;
+ int updated = 0;
- CLOSE_PIPE(s_info.tcb_pipe);
+ EINA_LIST_FOREACH(s_info.event_listener_list, l, item) {
+ if (item->event_cb == event_cb && item->cbdata == data) {
+ item->cbdata = new_data;
+ updated++;
+ }
+ }
- if (!eina_list_count(s_info.event_list)) {
- ecore_main_fd_handler_del(s_info.event_handler);
- clear_all_listener_list();
+ EINA_LIST_FOREACH(s_info.reactivate_list, l, item) {
+ if (item->event_cb == event_cb && item->cbdata == data) {
+ item->cbdata = new_data;
+ updated++;
+ }
}
- s_info.event_data.x = -1;
- s_info.event_data.y = -1;
- s_info.event_data.slot = -1;
- return LB_STATUS_SUCCESS;
+ return updated;
}
HAPI int event_is_activated(void)