From: SubodhKumar Date: Mon, 11 Apr 2016 13:39:01 +0000 (+0530) Subject: Gesture's implementation X-Git-Tag: accepted/tizen/common/20160524.150219~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a965138955e4d0a5989d9d3abbee75c5f5c191f1;p=platform%2Fcore%2Fuifw%2Fe-mod-tizen-screen-reader.git Gesture's implementation Change-Id: I1f7f070a3fcf2cc2e86fb59a06a16ad38e4134a6 --- diff --git a/autogen.sh b/autogen.sh index ab0c7d2..3938e2b 100755 --- a/autogen.sh +++ b/autogen.sh @@ -6,3 +6,4 @@ autoconf libtoolize --copy --force autoheader automake --foreign --add-missing --copy + diff --git a/src/Makefile.am b/src/Makefile.am index 6f439a2..28dd76e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,7 +6,9 @@ LDFLAGS += pkgdir = $(libdir)/enlightenment/modules/$(MODULE)/$(MODULE_ARCH) pkg_LTLIBRARIES = module.la module_la_SOURCES = \ - e_mod_main.c + e_mod_main.c \ + e_screen_reader_config.c \ + e_screen_reader_gestures.c #if HAVE_WAYLAND_ONLY #module_la_SOURCES += e_screen_reader_*.c \ diff --git a/src/e_mod_main.c b/src/e_mod_main.c index 7ba6bbd..0391537 100644 --- a/src/e_mod_main.c +++ b/src/e_mod_main.c @@ -1,10 +1,15 @@ #include "e.h" #include "eina_log.h" #include "e_mod_main.h" +#include +#include #undef DBG -int _log_dom = -1; -#define DBG(...) do EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__); while(0) +int _eina_log_dom = -1; +#define DBG(...) do EINA_LOG_DOM_DBG(_eina_log_dom, __VA_ARGS__); while(0) + +static Eina_Bool g_gesture_navi; +static Eina_List *handlers; EAPI E_Module_Api e_modapi = { @@ -12,23 +17,173 @@ EAPI E_Module_Api e_modapi = "Screen Reader Module of Window Manager" }; +/* Use this util function for gesture enum to string conversion */ +static const char *_gesture_enum_to_string(Gesture g) +{ + switch(g) + { + case ONE_FINGER_HOVER: + return "OneFingerHover"; + case TWO_FINGERS_HOVER: + return "TwoFingersHover"; + case THREE_FINGERS_HOVER: + return "ThreeFingersHover"; + case ONE_FINGER_FLICK_LEFT: + return "OneFingerFlickLeft"; + case ONE_FINGER_FLICK_RIGHT: + return "OneFingerFlickRight"; + case ONE_FINGER_FLICK_UP: + return "OneFingerFlickUp"; + case ONE_FINGER_FLICK_DOWN: + return "OneFingerFlickDown"; + case TWO_FINGERS_FLICK_UP: + return "TwoFingersFlickUp"; + case TWO_FINGERS_FLICK_DOWN: + return "TwoFingersFlickDown"; + case TWO_FINGERS_FLICK_LEFT: + return "TwoFingersFlickLeft"; + case TWO_FINGERS_FLICK_RIGHT: + return "TwoFingersFlickRight"; + case THREE_FINGERS_FLICK_LEFT: + return "ThreeFingersFlickLeft"; + case THREE_FINGERS_FLICK_RIGHT: + return "ThreeFingersFlickRight"; + case THREE_FINGERS_FLICK_UP: + return "ThreeFingersFlickUp"; + case THREE_FINGERS_FLICK_DOWN: + return "ThreeFingersFlickDown"; + case ONE_FINGER_SINGLE_TAP: + return "OneFingerSingleTap"; + case ONE_FINGER_DOUBLE_TAP: + return "OneFingerDoubleTap"; + case ONE_FINGER_TRIPLE_TAP: + return "OneFingerTripleTap"; + case TWO_FINGERS_SINGLE_TAP: + return "TwoFingersSingleTap"; + case TWO_FINGERS_DOUBLE_TAP: + return "TwoFingersDoubleTap"; + case TWO_FINGERS_TRIPLE_TAP: + return "TwoFingersTripleTap"; + case THREE_FINGERS_SINGLE_TAP: + return "ThreeFingersSingleTap"; + case THREE_FINGERS_DOUBLE_TAP: + return "ThreeFingersDoubleTap"; + case THREE_FINGERS_TRIPLE_TAP: + return "ThreeFingersTripleTap"; + case ONE_FINGER_FLICK_LEFT_RETURN: + return "OneFingerFlickLeftReturn"; + case ONE_FINGER_FLICK_RIGHT_RETURN: + return "OneFingerFlickRightReturn"; + case ONE_FINGER_FLICK_UP_RETURN: + return "OneFingerFlickUpReturn"; + case ONE_FINGER_FLICK_DOWN_RETURN: + return "OneFingerFlickDownReturn"; + case TWO_FINGERS_FLICK_LEFT_RETURN: + return "TwoFingersFlickLeftReturn"; + case TWO_FINGERS_FLICK_RIGHT_RETURN: + return "TwoFingersFlickRightReturn"; + case TWO_FINGERS_FLICK_UP_RETURN: + return "TwoFingersFlickUpReturn"; + case TWO_FINGERS_FLICK_DOWN_RETURN: + return "TwoFingersFlickDownReturn"; + case THREE_FINGERS_FLICK_LEFT_RETURN: + return "ThreeFingersFlickLeftReturn"; + case THREE_FINGERS_FLICK_RIGHT_RETURN: + return "ThreeFingersFlickRightReturn"; + case THREE_FINGERS_FLICK_UP_RETURN: + return "ThreeFingersFlickUpReturn"; + case THREE_FINGERS_FLICK_DOWN_RETURN: + return "ThreeFingersFlickDownReturn"; + default: + ERROR("[atspi] dbus: unhandled gesture enum"); + return NULL; + } +} + +int _e_mod_atspi_dbus_broadcast(Gesture_Info *gi) +{ + /* Implement this for gesture broadcast */ + const char *name; + + name = _gesture_enum_to_string(gi->type); + if (!name) return -1; + + INFO("GestureDetected %s (%d %d %d %d %d)", name, gi->x_beg, gi->y_beg, gi->x_end, gi->y_end, gi->state); + return 0; +} + +static Eina_Bool +_gesture_cb(void *data, + int type EINA_UNUSED, + void *event) +{ + Gesture_Info *gi = event; + + if (g_gesture_navi) + _e_mod_atspi_dbus_broadcast(gi); + + return EINA_TRUE; +} + +static void +_events_init(void) +{ +#define HANDLER_APPEND(event, cb) \ + handlers = eina_list_append( \ + handlers, ecore_event_handler_add(event, cb, NULL)); + HANDLER_APPEND(E_EVENT_ATSPI_GESTURE_DETECTED, _gesture_cb); + /* Use this list for other handlers */ +#undef APPEND_HANDLER +} + +static void +_events_shutdown(void) +{ + E_FREE_LIST(handlers, ecore_event_handler_del); +} + EAPI void * e_modapi_init(E_Module *m) { - _log_dom = eina_log_domain_register("e_screen_reader", EINA_COLOR_YELLOW); - if (_log_dom < 0) + _eina_log_dom = eina_log_domain_register("e_screen_reader", EINA_COLOR_YELLOW); + if (!_eina_log_dom) { DBG("Failed @ eina_log_domain_register()..!"); return NULL; } + if (_e_mod_atspi_config_init()) + goto fail; + if (_e_mod_atspi_gestures_init()) + goto fail_gestures; + + _events_init(); + g_gesture_navi = EINA_TRUE; return m; + +fail_gestures: + ERROR("Gestures submodule initialization failed."); + _e_mod_atspi_config_shutdown(); +fail: + ERROR("Module initialization failed."); + + return NULL; } EAPI int e_modapi_shutdown(E_Module *m EINA_UNUSED) { - eina_log_domain_unregister(_log_dom); + if (_eina_log_dom) + { + eina_log_domain_unregister(_eina_log_dom); + _eina_log_dom = 0; + } + + _events_shutdown(); + g_gesture_navi = EINA_FALSE; + _e_mod_atspi_config_save(); + _e_mod_atspi_config_shutdown(); + _e_mod_atspi_gestures_shutdown(); return 1; } diff --git a/src/e_screen_reader_config.c b/src/e_screen_reader_config.c new file mode 100644 index 0000000..15e2bf3 --- /dev/null +++ b/src/e_screen_reader_config.c @@ -0,0 +1,63 @@ +#include +#include +#include + +Gestures_Config *_e_mod_config; + +static E_Config_DD *_conf_edd; + + +static void +_e_mod_config_new(void) +{ + _e_mod_config = E_NEW(Gestures_Config, 1); + + _e_mod_config->one_finger_flick_min_length = 100; + _e_mod_config->one_finger_flick_max_time = 400; + _e_mod_config->one_finger_hover_longpress_timeout = 0.81; + _e_mod_config->two_fingers_hover_longpress_timeout = 0.1; + _e_mod_config->one_finger_tap_timeout = 0.4; + _e_mod_config->one_finger_tap_radius = 100; +} + +int _e_mod_atspi_config_init(void) +{ + DEBUG("Config init"); + _conf_edd = E_CONFIG_DD_NEW("Gestures_Config", Gestures_Config); + +#define T Gestures_Config +#define D _conf_edd + E_CONFIG_VAL(D, T, one_finger_flick_min_length, INT); + E_CONFIG_VAL(D, T, one_finger_flick_max_time, INT); + E_CONFIG_VAL(D, T, one_finger_hover_longpress_timeout, DOUBLE); + E_CONFIG_VAL(D, T, two_fingers_hover_longpress_timeout, DOUBLE); + E_CONFIG_VAL(D, T, one_finger_tap_timeout, DOUBLE); + E_CONFIG_VAL(D, T, one_finger_tap_radius, INT); + + _e_mod_config = e_config_domain_load(E_ATSPI_CFG, _conf_edd); + + if (!_e_mod_config) + { + _e_mod_config_new(); + _e_mod_atspi_config_save(); + INFO("New config file for e-mod-tizen-screen-reader module created."); + } + else + INFO("Config file for e-mod-tizen-screen-reader module loaded successfully."); + + return 0; +} + +int _e_mod_atspi_config_shutdown(void) +{ + DEBUG("Config shutdown"); + E_FREE(_e_mod_config); + E_CONFIG_DD_FREE(_conf_edd); + + return 0; +} + +int _e_mod_atspi_config_save(void) +{ + return e_config_domain_save(E_ATSPI_CFG, _conf_edd, _e_mod_config); +} diff --git a/src/e_screen_reader_config.h b/src/e_screen_reader_config.h new file mode 100644 index 0000000..1c82f94 --- /dev/null +++ b/src/e_screen_reader_config.h @@ -0,0 +1,31 @@ +#ifndef E_SCREEN_READER_CONFIG_H_ +#define E_SCREEN_READER_CONFIG_H_ + +#define E_ATSPI_CFG "module.e-mod-tizen-screen-reader" + +struct _Gestures_Config +{ + // minimal required length of flick gesture (in pixels) + int one_finger_flick_min_length; + // maximal time of gesture + int one_finger_flick_max_time; + // timeout period to activate hover gesture (first longpress timeout) + double one_finger_hover_longpress_timeout; + // tap timeout - maximal ammount of time allowed between seqiential taps + double two_fingers_hover_longpress_timeout; + // tap timeout - maximal ammount of time allowed between seqiential taps + double one_finger_tap_timeout; + // tap radius(in pixels) + int one_finger_tap_radius; +}; + +typedef struct _Gestures_Config Gestures_Config; + +int _e_mod_atspi_config_init(void); +int _e_mod_atspi_config_shutdown(void); +int _e_mod_atspi_config_save(void); + +/*< External config handle - valid after initalization */ +extern Gestures_Config *_e_mod_config; + +#endif /* E_SCREEN_READER_CONFIG_H_ */ diff --git a/src/e_screen_reader_gestures.c b/src/e_screen_reader_gestures.c new file mode 100644 index 0000000..36d6cb9 --- /dev/null +++ b/src/e_screen_reader_gestures.c @@ -0,0 +1,1098 @@ +#include "e.h" +#include "e_comp.h" +#include "e_screen_reader_private.h" + + +#define HISTORY_MAX 8 +#define LONGPRESS_TIMEOUT 0.4 + +typedef enum { + FLICK_DIRECTION_UNDEFINED, + FLICK_DIRECTION_DOWN, + FLICK_DIRECTION_UP, + FLICK_DIRECTION_LEFT, + FLICK_DIRECTION_RIGHT, + FLICK_DIRECTION_DOWN_RETURN, + FLICK_DIRECTION_UP_RETURN, + FLICK_DIRECTION_LEFT_RETURN, + FLICK_DIRECTION_RIGHT_RETURN, +} flick_direction_e; + +typedef enum { + GESTURE_NOT_STARTED = 0, // Gesture is ready to start + GESTURE_ONGOING, // Gesture in progress. + GESTURE_FINISHED, // Gesture finished - should be emited + GESTURE_ABORTED // Gesture aborted +} gesture_state_e; + +typedef enum { + ONE_FINGER_GESTURE = 1, + TWO_FINGERS_GESTURE, + THREE_FINGERS_GESTURE +} gesture_type_e; + +struct _Cover +{ + Evas_Object *gesture_rect; /**< Gesture rectangle */ + unsigned int n_taps; /**< Number of fingers touching screen */ + unsigned int event_time; + + struct { + gesture_state_e state; // current state of gesture + unsigned int timestamp[3]; // time of gesture; + int finger[3]; // finger number which initiates gesture + int x_org[3], y_org[3]; // coorinates of finger down event + int x_end[3], y_end[3]; // coorinates of finger up event + flick_direction_e dir; // direction of flick + int n_fingers; // number of fingers in gesture + int n_fingers_left; // number of fingers in gesture + // still touching screen + Eina_Bool finger_out[3]; // finger is out of the finger boundary + Eina_Bool return_flick[3]; + } flick_gesture; + + struct { + gesture_state_e state; // currest gesture state + int x[2], y[2]; + int n_fingers; + int finger[2]; + unsigned int timestamp; // time of gesture; + unsigned int last_emission_time; // last time of gesture emission + Ecore_Timer *timer; + Eina_Bool longpressed; + } hover_gesture; + + struct { + Eina_Bool started; // indicates if taps recognition process has started + Eina_Bool pressed; // indicates if finger is down + int n_taps; // number of taps captures in sequence + int finger[3]; // device id of finget + Ecore_Timer *timer; // sequence expiration timer + int x_org[3], y_org[3]; // coordinates of first tap + gesture_type_e tap_type; + } tap_gesture_data; +}; +typedef struct _Cover Cover; + +int E_EVENT_ATSPI_GESTURE_DETECTED; + +static Cover *cover; +static Eina_List *handlers; +static void _gesture_init(void); +static void _gesture_shutdown(void); +static void _hover_event_emit(Cover *cov, int state); + +static void +_gesture_info_free(void *data, void *info) +{ + free(data); +} + +static void _event_emit(Gesture g, int x, int y, int x_e, int y_e, int state) +{ + Gesture_Info *info = calloc(sizeof(Gesture_Info), 1); + EINA_SAFETY_ON_NULL_RETURN(info); + + info->type = g; + info->x_beg = x; + info->x_end = x_e; + info->y_beg = y; + info->y_end = y_e; + info->state = state; + + ecore_event_add(E_EVENT_ATSPI_GESTURE_DETECTED, info, _gesture_info_free, NULL); +} + +static void +_flick_gesture_mouse_down(Ecore_Event_Mouse_Button *ev, Cover *cov) +{ + if (cov->flick_gesture.state == GESTURE_NOT_STARTED) + { + cov->flick_gesture.state = GESTURE_ONGOING; + cov->flick_gesture.finger[0] = ev->multi.device; + cov->flick_gesture.x_org[0] = ev->root.x; + cov->flick_gesture.y_org[0] = ev->root.y; + cov->flick_gesture.timestamp[0] = ev->timestamp; + cov->flick_gesture.n_fingers = 1; + cov->flick_gesture.n_fingers_left = 1; + cov->flick_gesture.dir = FLICK_DIRECTION_UNDEFINED; + cov->flick_gesture.finger_out[0] = EINA_FALSE; + cov->flick_gesture.return_flick[0] = EINA_FALSE; + } + else if (cov->flick_gesture.state == GESTURE_ONGOING) + { + // abort gesture if too many fingers touched screen + if ((cov->n_taps > 3) || (cov->flick_gesture.n_fingers > 2)) + { + cov->flick_gesture.state = GESTURE_ABORTED; + return; + } + + cov->flick_gesture.x_org[cov->flick_gesture.n_fingers] = ev->root.x; + cov->flick_gesture.y_org[cov->flick_gesture.n_fingers] = ev->root.y; + cov->flick_gesture.timestamp[cov->flick_gesture.n_fingers] = ev->timestamp; + cov->flick_gesture.finger[cov->flick_gesture.n_fingers] = ev->multi.device; + cov->flick_gesture.n_fingers++; + cov->flick_gesture.n_fingers_left++; + if (cov->flick_gesture.n_fingers < 3) /* n_fingers == 3 makes out of bounds write */ + { + cov->flick_gesture.finger_out[cov->flick_gesture.n_fingers] = EINA_FALSE; + cov->flick_gesture.return_flick[cov->flick_gesture.n_fingers] = EINA_FALSE; + } + } +} + +static Eina_Bool +_flick_gesture_time_check(unsigned int event_time, unsigned int gesture_time) +{ + DEBUG("Flick time: %d", event_time - gesture_time); + if ((event_time - gesture_time) < _e_mod_config->one_finger_flick_max_time * 2) //Double time because of the possible of return flick + return EINA_TRUE; + else + return EINA_FALSE; +} + +static Eina_Bool +_flick_gesture_length_check(int x, int y, int x_org, int y_org) +{ + int dx = x - x_org; + int dy = y - y_org; + + if ((dx * dx + dy * dy) > (_e_mod_config->one_finger_flick_min_length * + _e_mod_config->one_finger_flick_min_length)) + return EINA_TRUE; + else + return EINA_FALSE; +} + +static flick_direction_e +_flick_gesture_direction_get(int x, int y, int x_org, int y_org) +{ + int dx = x - x_org; + int dy = y - y_org; + + if ((dy < 0) && (abs(dx) < -dy)) + return FLICK_DIRECTION_UP; + if ((dy > 0) && (abs(dx) < dy)) + return FLICK_DIRECTION_DOWN; + if ((dx > 0) && (dx > abs(dy))) + return FLICK_DIRECTION_RIGHT; + if ((dx < 0) && (-dx > abs(dy))) + return FLICK_DIRECTION_LEFT; + + return FLICK_DIRECTION_UNDEFINED; +} + +static void +_flick_event_emit(Cover *cov) +{ + int ax, ay, axe, aye, i, type = -1; + ax = ay = axe = aye = 0; + + for (i = 0; i < cov->flick_gesture.n_fingers; i++) + { + ax += cov->flick_gesture.x_org[i]; + ay += cov->flick_gesture.y_org[i]; + axe += cov->flick_gesture.x_end[i]; + aye += cov->flick_gesture.y_end[i]; + } + + ax /= cov->flick_gesture.n_fingers; + ay /= cov->flick_gesture.n_fingers; + axe /= cov->flick_gesture.n_fingers; + aye /= cov->flick_gesture.n_fingers; + + if (cov->flick_gesture.dir == FLICK_DIRECTION_LEFT) + { + if (cov->flick_gesture.n_fingers == 1) + type = ONE_FINGER_FLICK_LEFT; + if (cov->flick_gesture.n_fingers == 2) + type = TWO_FINGERS_FLICK_LEFT; + if (cov->flick_gesture.n_fingers == 3) + type = THREE_FINGERS_FLICK_LEFT; + } + else if (cov->flick_gesture.dir == FLICK_DIRECTION_RIGHT) + { + if (cov->flick_gesture.n_fingers == 1) + type = ONE_FINGER_FLICK_RIGHT; + if (cov->flick_gesture.n_fingers == 2) + type = TWO_FINGERS_FLICK_RIGHT; + if (cov->flick_gesture.n_fingers == 3) + type = THREE_FINGERS_FLICK_RIGHT; + } + else if (cov->flick_gesture.dir == FLICK_DIRECTION_UP) + { + if (cov->flick_gesture.n_fingers == 1) + type = ONE_FINGER_FLICK_UP; + if (cov->flick_gesture.n_fingers == 2) + type = TWO_FINGERS_FLICK_UP; + if (cov->flick_gesture.n_fingers == 3) + type = THREE_FINGERS_FLICK_UP; + } + else if (cov->flick_gesture.dir == FLICK_DIRECTION_DOWN) + { + if (cov->flick_gesture.n_fingers == 1) + type = ONE_FINGER_FLICK_DOWN; + if (cov->flick_gesture.n_fingers == 2) + type = TWO_FINGERS_FLICK_DOWN; + if (cov->flick_gesture.n_fingers == 3) + type = THREE_FINGERS_FLICK_DOWN; + } + else if (cov->flick_gesture.dir == FLICK_DIRECTION_DOWN_RETURN) + { + if (cov->flick_gesture.n_fingers == 1) + type = ONE_FINGER_FLICK_DOWN_RETURN; + if (cov->flick_gesture.n_fingers == 2) + type = TWO_FINGERS_FLICK_DOWN_RETURN; + if (cov->flick_gesture.n_fingers == 3) + type = THREE_FINGERS_FLICK_DOWN_RETURN; + } + else if (cov->flick_gesture.dir == FLICK_DIRECTION_UP_RETURN) + { + if (cov->flick_gesture.n_fingers == 1) + type = ONE_FINGER_FLICK_UP_RETURN; + if (cov->flick_gesture.n_fingers == 2) + type = TWO_FINGERS_FLICK_UP_RETURN; + if (cov->flick_gesture.n_fingers == 3) + type = THREE_FINGERS_FLICK_UP_RETURN; + } + else if (cov->flick_gesture.dir == FLICK_DIRECTION_LEFT_RETURN) + { + if (cov->flick_gesture.n_fingers == 1) + type = ONE_FINGER_FLICK_LEFT_RETURN; + if (cov->flick_gesture.n_fingers == 2) + type = TWO_FINGERS_FLICK_LEFT_RETURN; + if (cov->flick_gesture.n_fingers == 3) + type = THREE_FINGERS_FLICK_LEFT_RETURN; + } + else if (cov->flick_gesture.dir == FLICK_DIRECTION_RIGHT_RETURN) + { + if (cov->flick_gesture.n_fingers == 1) + type = ONE_FINGER_FLICK_RIGHT_RETURN; + if (cov->flick_gesture.n_fingers == 2) + type = TWO_FINGERS_FLICK_RIGHT_RETURN; + if (cov->flick_gesture.n_fingers == 3) + type = THREE_FINGERS_FLICK_RIGHT_RETURN; + } + _event_emit(type, ax, ay, axe, aye, 2); +} + +static void +_flick_gesture_mouse_up(Ecore_Event_Mouse_Button *ev, Cover *cov) +{ + if (cov->flick_gesture.state == GESTURE_ONGOING) + { + int i; + // check if fingers match + for (i = 0; i < cov->flick_gesture.n_fingers; i++) + { + if (cov->flick_gesture.finger[i] == ev->multi.device) + break; + } + if (i == cov->flick_gesture.n_fingers) + { + DEBUG("Finger id not recognized. Gesture aborted."); + cov->flick_gesture.state = GESTURE_ABORTED; + goto end; + } + + // check if flick for given finger is valid + if (!_flick_gesture_time_check(ev->timestamp, + cov->flick_gesture.timestamp[i])) + { + DEBUG("finger flick gesture timeout expired. Gesture aborted."); + cov->flick_gesture.state = GESTURE_ABORTED; + goto end; + } + + // check minimal flick length + if (!_flick_gesture_length_check(ev->root.x, ev->root.y, + cov->flick_gesture.x_org[i], + cov->flick_gesture.y_org[i])) + { + if (!cov->flick_gesture.finger_out[i]) + { + DEBUG("Minimal gesture length not reached and no return flick. Gesture aborted."); + cov->flick_gesture.state = GESTURE_ABORTED; + goto end; + } + cov->flick_gesture.return_flick[i] = EINA_TRUE; + } + + flick_direction_e s = cov->flick_gesture.return_flick[i] ? + cov->flick_gesture.dir : + _flick_gesture_direction_get(ev->root.x, ev->root.y, + cov->flick_gesture.x_org[i], + cov->flick_gesture.y_org[i]); + + cov->flick_gesture.n_fingers_left--; + + if ((cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED || + cov->flick_gesture.dir > FLICK_DIRECTION_RIGHT) + && cov->flick_gesture.return_flick[i] == EINA_FALSE) + { + DEBUG("Flick gesture"); + cov->flick_gesture.dir = s; + } + + // gesture is valid only if all flicks are in same direction + if (cov->flick_gesture.dir != s) + { + DEBUG("Flick in different direction. Gesture aborted."); + cov->flick_gesture.state = GESTURE_ABORTED; + goto end; + } + + cov->flick_gesture.x_end[i] = ev->root.x; + cov->flick_gesture.y_end[i] = ev->root.y; + + if (!cov->flick_gesture.n_fingers_left) + { + _flick_event_emit(cov); + cov->flick_gesture.state = GESTURE_NOT_STARTED; + } + } + +end: + // if no finger is touching a screen, gesture will be reseted. + if ((cov->flick_gesture.state == GESTURE_ABORTED) && (cov->n_taps == 0)) + { + DEBUG("Restet flick gesture"); + cov->flick_gesture.state = GESTURE_NOT_STARTED; + } +} + +static void +_flick_gesture_mouse_move(Ecore_Event_Mouse_Move *ev, Cover *cov) +{ + if (cov->flick_gesture.state == GESTURE_ONGOING) + { + int i; + for(i = 0; i < cov->flick_gesture.n_fingers; ++i) + { + if (cov->flick_gesture.finger[i] == ev->multi.device) + break; + } + if (i == cov->flick_gesture.n_fingers) + { + if (cov->flick_gesture.n_fingers >= 3) //that is because of the EFL bug. Mouse move event before mouse down(!) + { + ERROR("Finger id not recognized. Gesture aborted."); + cov->flick_gesture.state = GESTURE_ABORTED; + return; + } + } + if(!cov->flick_gesture.finger_out[i]) + { + int dx = ev->root.x - cov->flick_gesture.x_org[i]; + int dy = ev->root.y - cov->flick_gesture.y_org[i]; + + if (dx < 0) dx *= -1; + if (dy < 0) dy *= -1; + + if (dx > _e_mod_config->one_finger_flick_min_length) + { + cov->flick_gesture.finger_out[i] = EINA_TRUE; + if (ev->root.x > cov->flick_gesture.x_org[i]) + { + if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED || + cov->flick_gesture.dir == FLICK_DIRECTION_RIGHT_RETURN) + { + cov->flick_gesture.dir = FLICK_DIRECTION_RIGHT_RETURN; + } + else + { + ERROR("Invalid direction, abort"); + cov->flick_gesture.state = GESTURE_ABORTED; + } + } + else + { + if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED || + cov->flick_gesture.dir == FLICK_DIRECTION_LEFT_RETURN) + { + cov->flick_gesture.dir = FLICK_DIRECTION_LEFT_RETURN; + } + else + { + ERROR("Invalid direction, abort"); + cov->flick_gesture.state = GESTURE_ABORTED; + } + } + return; + } + + else if (dy > _e_mod_config->one_finger_flick_min_length) + { + cov->flick_gesture.finger_out[i] = EINA_TRUE; + if (ev->root.y > cov->flick_gesture.y_org[i]) + { + if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED || + cov->flick_gesture.dir == FLICK_DIRECTION_DOWN_RETURN) + { + cov->flick_gesture.dir = FLICK_DIRECTION_DOWN_RETURN; + } + else + { + ERROR("Invalid direction, abort"); + cov->flick_gesture.state = GESTURE_ABORTED; + } + } + else + { + if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED || + cov->flick_gesture.dir == FLICK_DIRECTION_UP_RETURN) + { + cov->flick_gesture.dir = FLICK_DIRECTION_UP_RETURN; + } + else + { + ERROR("Invalid direction, abort"); + cov->flick_gesture.state = GESTURE_ABORTED; + } + } + return; + } + } + } + return; +} + +static Eina_Bool +_on_hover_timeout(void *data) +{ + Cover *cov = data; + DEBUG("Hover timer expierd"); + + cov->hover_gesture.longpressed = EINA_TRUE; + cov->hover_gesture.timer = NULL; + + if (cov->hover_gesture.last_emission_time == -1) + { + _hover_event_emit(cov, 0); + cov->hover_gesture.last_emission_time = cov->event_time; + } + return EINA_FALSE; +} + +static void +_hover_gesture_timer_reset(Cover *cov, double time) +{ + DEBUG("Hover timer reset"); + cov->hover_gesture.longpressed = EINA_FALSE; + if (cov->hover_gesture.timer) + { + ecore_timer_reset(cov->hover_gesture.timer); + return; + } + cov->hover_gesture.timer = ecore_timer_add(time, _on_hover_timeout, cov); +} + +static void +_hover_gesture_mouse_down(Ecore_Event_Mouse_Button *ev, Cover *cov) +{ + if (cov->hover_gesture.state == GESTURE_NOT_STARTED && + cov->n_taps == 1) + { + cov->hover_gesture.state = GESTURE_ONGOING; + cov->hover_gesture.timestamp = ev->timestamp; + cov->hover_gesture.last_emission_time = -1; + cov->hover_gesture.x[0] = ev->root.x; + cov->hover_gesture.y[0] = ev->root.y; + cov->hover_gesture.finger[0] = ev->multi.device; + cov->hover_gesture.n_fingers = 1; + _hover_gesture_timer_reset(cov, _e_mod_config->one_finger_hover_longpress_timeout); + } + if (cov->hover_gesture.state == GESTURE_ONGOING && + cov->n_taps == 2) + { + if (cov->hover_gesture.longpressed) + { + _hover_event_emit(cov, 2); + goto abort; + } + cov->hover_gesture.timestamp = -1; + cov->hover_gesture.last_emission_time = -1; + cov->hover_gesture.x[1] = ev->root.x; + cov->hover_gesture.y[1] = ev->root.y; + cov->hover_gesture.finger[1] = ev->multi.device; + cov->hover_gesture.n_fingers = 2; + cov->hover_gesture.longpressed = EINA_TRUE; + if (cov->hover_gesture.timer) + ecore_timer_del(cov->hover_gesture.timer); + cov->hover_gesture.timer = NULL; + _hover_event_emit(cov, 0); + } + // abort gesture if more then 2 fingers touched screen + if ((cov->hover_gesture.state == GESTURE_ONGOING) && + cov->n_taps > 2) + { + DEBUG("More then 2 finged. Abort hover gesture"); + _hover_event_emit(cov, 2); + goto abort; + } + return; + +abort: + cov->hover_gesture.state = GESTURE_ABORTED; + if (cov->hover_gesture.timer) + ecore_timer_del(cov->hover_gesture.timer); + cov->hover_gesture.timer = NULL; +} + +static void +_hover_gesture_mouse_up(Ecore_Event_Mouse_Button *ev, Cover *cov) +{ + int i; + if (cov->hover_gesture.state == GESTURE_ONGOING) + { + + for (i = 0; i < cov->hover_gesture.n_fingers; i++) + { + if (cov->hover_gesture.finger[i] == ev->multi.device) + break; + } + if (i == cov->hover_gesture.n_fingers) + { + DEBUG("Invalid finger id: %d", ev->multi.device); + return; + } + else + { + cov->hover_gesture.state = GESTURE_ABORTED; + if (cov->hover_gesture.timer) + ecore_timer_del(cov->hover_gesture.timer); + cov->hover_gesture.timer = NULL; + // aditionally emit event to complete sequence + if (cov->hover_gesture.longpressed) + _hover_event_emit(cov, 2); + } + } + // reset gesture only if user released all his fingers + if (cov->n_taps == 0) + cov->hover_gesture.state = GESTURE_NOT_STARTED; +} + +static void +_hover_event_emit(Cover *cov, int state) +{ + DEBUG("Emit hover event"); + int ax = 0, ay = 0, j; + for (j = 0; j < cov->hover_gesture.n_fingers; j++) + { + ax += cov->hover_gesture.x[j]; + ay += cov->hover_gesture.y[j]; + } + + ax /= cov->hover_gesture.n_fingers; + ay /= cov->hover_gesture.n_fingers; + + switch (cov->hover_gesture.n_fingers) + { + case 1: + _event_emit(ONE_FINGER_HOVER, ax, ay, ax, ay, state); + break; + case 2: + _event_emit(TWO_FINGERS_HOVER, ax, ay, ax, ay, state); + break; + default: + break; + } +} + +static void +_hover_gesture_mouse_move(Ecore_Event_Mouse_Move *ev, Cover *cov) +{ + if (cov->hover_gesture.state == GESTURE_ONGOING) + { + // check fingers + int i; + if (!cov->hover_gesture.longpressed) + return; + + for (i = 0; i < cov->hover_gesture.n_fingers; i++) + { + if (cov->hover_gesture.finger[i] == ev->multi.device) + break; + } + if (i == cov->hover_gesture.n_fingers) + { + DEBUG("Invalid finger id: %d", ev->multi.device); + return; + } + cov->hover_gesture.x[i] = ev->root.x; + cov->hover_gesture.y[i] = ev->root.y; + _hover_event_emit(cov, 1); + } +} + +static void +_tap_event_emit(Cover *cov) +{ + switch (cov->tap_gesture_data.n_taps) + { + case 1: + if(cov->tap_gesture_data.tap_type == ONE_FINGER_GESTURE) + { + DEBUG("ONE_FINGER_SINGLE_TAP"); + _event_emit(ONE_FINGER_SINGLE_TAP, + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + 2); + } + else if(cov->tap_gesture_data.tap_type == TWO_FINGERS_GESTURE) + { + DEBUG("TWO_FINGERS_SINGLE_TAP"); + _event_emit(TWO_FINGERS_SINGLE_TAP, + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + cov->tap_gesture_data.x_org[1], cov->tap_gesture_data.y_org[1], + 2); + } + else if(cov->tap_gesture_data.tap_type == THREE_FINGERS_GESTURE) + { + DEBUG("THREE_FINGERS_SINGLE_TAP"); + _event_emit(THREE_FINGERS_SINGLE_TAP, + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + cov->tap_gesture_data.x_org[2], cov->tap_gesture_data.y_org[2], + 2); + } + else + { + ERROR("Unknown tap"); + } + break; + case 2: + if(cov->tap_gesture_data.tap_type == ONE_FINGER_GESTURE) + { + DEBUG("ONE_FINGER_DOUBLE_TAP"); + _event_emit(ONE_FINGER_DOUBLE_TAP, + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + 2); + } + else if(cov->tap_gesture_data.tap_type == TWO_FINGERS_GESTURE) + { + DEBUG("TWO_FINGERS_DOUBLE_TAP"); + _event_emit(TWO_FINGERS_DOUBLE_TAP, + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + cov->tap_gesture_data.x_org[1], cov->tap_gesture_data.y_org[1], + 2); + } + else if(cov->tap_gesture_data.tap_type == THREE_FINGERS_GESTURE) + { + DEBUG("THREE_FINGERS_DOUBLE_TAP"); + _event_emit(THREE_FINGERS_DOUBLE_TAP, + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + cov->tap_gesture_data.x_org[2], cov->tap_gesture_data.y_org[2], + 2); + } + else + { + ERROR("Unknown tap"); + } + break; + case 3: + if(cov->tap_gesture_data.tap_type == ONE_FINGER_GESTURE) + { + DEBUG("ONE_FINGER_TRIPLE_TAP"); + _event_emit(ONE_FINGER_TRIPLE_TAP, + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + 2); + } + else if(cov->tap_gesture_data.tap_type == TWO_FINGERS_GESTURE) + { + DEBUG("TWO_FINGERS_TRIPLE_TAP"); + _event_emit(TWO_FINGERS_TRIPLE_TAP, + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + cov->tap_gesture_data.x_org[1], cov->tap_gesture_data.y_org[1], + 2); + } + else if(cov->tap_gesture_data.tap_type == THREE_FINGERS_GESTURE) + { + DEBUG("THREE_FINGERS_TRIPLE_TAP"); + _event_emit(THREE_FINGERS_TRIPLE_TAP, + cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0], + cov->tap_gesture_data.x_org[2], cov->tap_gesture_data.y_org[2], + 2); + } + else + { + ERROR("Unknown tap"); + } + break; + default: + ERROR("Unknown tap"); + break; + } +} + +static Eina_Bool +_on_tap_timer_expire(void *data) +{ + Cover *cov = data; + DEBUG("Timer expired"); + + if (cov->tap_gesture_data.started && !cov->tap_gesture_data.pressed) + _tap_event_emit(cov); + + // finish gesture + cov->tap_gesture_data.started = EINA_FALSE; + cov->tap_gesture_data.timer = NULL; + cov->tap_gesture_data.tap_type = ONE_FINGER_GESTURE; + cov->tap_gesture_data.finger[0] = -1; + cov->tap_gesture_data.finger[1] = -1; + cov->tap_gesture_data.finger[2] = -1; + + return EINA_FALSE; +} + +static int _tap_gesture_finger_check(Cover *cov, int x, int y) +{ + int dx = x - cov->tap_gesture_data.x_org[0]; + int dy = y - cov->tap_gesture_data.y_org[0]; + + if (cov->tap_gesture_data.finger[0] != -1 && + (dx * dx + dy * dy < _e_mod_config->one_finger_tap_radius * + _e_mod_config->one_finger_tap_radius)) + { + return 0; + } + + dx = x - cov->tap_gesture_data.x_org[1]; + dy = y - cov->tap_gesture_data.y_org[1]; + if (cov->tap_gesture_data.finger[1] != -1 && + (dx * dx + dy * dy < _e_mod_config->one_finger_tap_radius * + _e_mod_config->one_finger_tap_radius)) + { + return 1; + } + + dx = x - cov->tap_gesture_data.x_org[2]; + dy = y - cov->tap_gesture_data.y_org[2]; + if (cov->tap_gesture_data.finger[2] != -1 && + (dx * dx + dy * dy < _e_mod_config->one_finger_tap_radius * + _e_mod_config->one_finger_tap_radius)) + { + return 2; + } + + return -1; +} + +static void +_tap_gestures_mouse_down(Ecore_Event_Mouse_Button *ev, Cover *cov) +{ + if (cov->n_taps > 4) + { + ERROR("Too many fingers"); + return; + } + + cov->tap_gesture_data.pressed = EINA_TRUE; + + if (cov->tap_gesture_data.started == EINA_FALSE) + { + DEBUG("First finger down"); + cov->tap_gesture_data.started = EINA_TRUE; + cov->tap_gesture_data.finger[0] = ev->multi.device; + cov->tap_gesture_data.x_org[0] = ev->root.x; + cov->tap_gesture_data.y_org[0] = ev->root.y; + cov->tap_gesture_data.finger[1] = -1; + cov->tap_gesture_data.finger[2] = -1; + cov->tap_gesture_data.n_taps = 0; + cov->tap_gesture_data.timer = ecore_timer_add( + _e_mod_config->one_finger_tap_timeout, + _on_tap_timer_expire, cov); + cov->tap_gesture_data.tap_type = ONE_FINGER_GESTURE; + } + + else + { + if (ev->multi.device == cov->tap_gesture_data.finger[0]) + { + DEBUG("First finger down"); + + if (_tap_gesture_finger_check(cov, ev->root.x, ev->root.y) == -1) + { + ERROR("Abort gesture"); + cov->tap_gesture_data.started = EINA_FALSE; + ecore_timer_del(cov->tap_gesture_data.timer); + cov->tap_gesture_data.timer = NULL; + cov->tap_gesture_data.tap_type = ONE_FINGER_GESTURE; + cov->tap_gesture_data.finger[0] = -1; + cov->tap_gesture_data.finger[1] = -1; + cov->tap_gesture_data.finger[2] = -1; + _tap_gestures_mouse_down(ev, cov); + return; + } + + cov->tap_gesture_data.x_org[0] = ev->root.x; + cov->tap_gesture_data.y_org[0] = ev->root.y; + } + else if (cov->tap_gesture_data.finger[1] == -1 || + cov->tap_gesture_data.finger[1] == ev->multi.device) + { + DEBUG("Second finger down"); + cov->tap_gesture_data.finger[1] = ev->multi.device; + + cov->tap_gesture_data.x_org[1] = ev->root.x; + cov->tap_gesture_data.y_org[1] = ev->root.y; + if (cov->tap_gesture_data.tap_type < TWO_FINGERS_GESTURE) + cov->tap_gesture_data.tap_type = TWO_FINGERS_GESTURE; + } + else if (cov->tap_gesture_data.finger[2] == -1 || + cov->tap_gesture_data.finger[2] == ev->multi.device) + { + DEBUG("Third finger down"); + cov->tap_gesture_data.finger[2] = ev->multi.device; + + cov->tap_gesture_data.x_org[2] = ev->root.x; + cov->tap_gesture_data.y_org[2] = ev->root.y; + if (cov->tap_gesture_data.tap_type < THREE_FINGERS_GESTURE) + cov->tap_gesture_data.tap_type = THREE_FINGERS_GESTURE; + } + else + { + ERROR("Unknown finger down"); + } + ecore_timer_reset(cov->tap_gesture_data.timer); + } +} + +static void +_tap_gestures_mouse_up(Ecore_Event_Mouse_Button *ev, Cover *cov) +{ + if (cov->tap_gesture_data.timer) + { + cov->tap_gesture_data.pressed = EINA_FALSE; + + if (ev->multi.device == cov->tap_gesture_data.finger[0]) + { + DEBUG("First finger up"); + + int dx = ev->root.x - cov->tap_gesture_data.x_org[0]; + int dy = ev->root.y - cov->tap_gesture_data.y_org[0]; + + if((dx * dx + dy * dy) < _e_mod_config->one_finger_tap_radius * + _e_mod_config->one_finger_tap_radius) + { + if (cov->n_taps == 0) + { + cov->tap_gesture_data.n_taps++; + } + } + else + { + ERROR("Abort gesture"); + cov->tap_gesture_data.started = EINA_FALSE; + } + } + else if (ev->multi.device == cov->tap_gesture_data.finger[1]) + { + DEBUG("Second finger up"); + + int dx = ev->root.x - cov->tap_gesture_data.x_org[1]; + int dy = ev->root.y - cov->tap_gesture_data.y_org[1]; + + if((dx * dx + dy * dy) < _e_mod_config->one_finger_tap_radius * + _e_mod_config->one_finger_tap_radius) + { + if (cov->n_taps == 0) + { + cov->tap_gesture_data.n_taps++; + } + } + else + { + ERROR("Abort gesture"); + cov->tap_gesture_data.started = EINA_FALSE; + } + } + else if (ev->multi.device == cov->tap_gesture_data.finger[2]) + { + DEBUG("Third finger up"); + + int dx = ev->root.x - cov->tap_gesture_data.x_org[2]; + int dy = ev->root.y - cov->tap_gesture_data.y_org[2]; + + if((dx * dx + dy * dy) < _e_mod_config->one_finger_tap_radius * + _e_mod_config->one_finger_tap_radius) + { + if (cov->n_taps == 0) + { + cov->tap_gesture_data.n_taps++; + } + } + else + { + ERROR("Abort gesture"); + cov->tap_gesture_data.started = EINA_FALSE; + } + } + else + { + ERROR("Unknown finger up, abort gesture"); + cov->tap_gesture_data.started = EINA_FALSE; + } + } +} + +static void +_tap_gestures_move(Ecore_Event_Mouse_Move *ev, Cover *cov) +{ + if(_tap_gesture_finger_check(cov, ev->root.x, ev->root.y) == -1) + { + ERROR("Abort gesture"); + cov->tap_gesture_data.started = EINA_FALSE; + ecore_timer_del(cov->tap_gesture_data.timer); + cov->tap_gesture_data.timer = NULL; + cov->tap_gesture_data.tap_type = ONE_FINGER_GESTURE; + cov->tap_gesture_data.finger[0] = -1; + cov->tap_gesture_data.finger[1] = -1; + cov->tap_gesture_data.finger[2] = -1; + return; + } +} + +static Eina_Bool +_cb_mouse_down(void *data EINA_UNUSED, + int type EINA_UNUSED, + void *event) +{ + Ecore_Event_Mouse_Button *ev = event; + + cover->n_taps++; + cover->event_time = ev->timestamp; + + DEBUG("single mouse down: taps: %d Multi :%d", cover->n_taps,ev->multi.device); + + _flick_gesture_mouse_down(ev, cover); + _hover_gesture_mouse_down(ev, cover); + _tap_gestures_mouse_down(ev, cover); + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_cb_mouse_up(void *data EINA_UNUSED, + int type EINA_UNUSED, + void *event) +{ + Ecore_Event_Mouse_Button *ev = event; + + cover->n_taps--; + cover->event_time = ev->timestamp; + + DEBUG("single mouse up,taps: %d Multi :%d", cover->n_taps,ev->multi.device); + + _flick_gesture_mouse_up(ev, cover); + _hover_gesture_mouse_up(ev, cover); + _tap_gestures_mouse_up(ev, cover); + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_cb_mouse_move(void *data EINA_UNUSED, + int type EINA_UNUSED, + void *event) +{ + Ecore_Event_Mouse_Move *ev = event; + + cover->event_time = ev->timestamp; + + _flick_gesture_mouse_move(ev, cover); + _hover_gesture_mouse_move(ev, cover); + _tap_gestures_move(ev, cover); + + return ECORE_CALLBACK_PASS_ON; +} + +static void +_events_init(void) +{ +#define HANDLER_APPEND(event, cb) \ + handlers = eina_list_append( \ + handlers, ecore_event_handler_add(event, cb, NULL)); + HANDLER_APPEND(ECORE_EVENT_MOUSE_BUTTON_DOWN, _cb_mouse_down); + HANDLER_APPEND(ECORE_EVENT_MOUSE_BUTTON_UP, _cb_mouse_up); + HANDLER_APPEND(ECORE_EVENT_MOUSE_MOVE, _cb_mouse_move); +#undef APPEND_HANDLER + + if (!E_EVENT_ATSPI_GESTURE_DETECTED) + E_EVENT_ATSPI_GESTURE_DETECTED = ecore_event_type_new(); +} + +static void +_events_shutdown(void) +{ + E_FREE_LIST(handlers, ecore_event_handler_del); +} + +static Evas_Object *gesture_rectangle; + +static void +_resize_canvas_gesture(Ecore_Evas *ee EINA_UNUSED) +{ + int x, y, w, h; + ecore_evas_geometry_get(e_comp->ee, &x, &y, &w, &h); + DEBUG("Resizing to x: %i, y: %i, w: %i, h:%i", x, y, w, h); + // For testing purpose + evas_object_geometry_set(gesture_rectangle, x, y, 600,800); + + //evas_object_geometry_set(gesture_rectangle, x, y, w, h); +} + +static void +_gesture_init() +{ + DEBUG("Gesture Rect Creation init."); + + cover = E_NEW(Cover, 1); + if (!cover) + { + ERROR("Fatal Memory error!"); + return; + } + + gesture_rectangle = evas_object_rectangle_add(e_comp->evas); + evas_object_layer_set(gesture_rectangle, E_LAYER_MAX); + evas_object_repeat_events_set(gesture_rectangle, EINA_FALSE); + _resize_canvas_gesture(NULL); + evas_object_color_set(gesture_rectangle, 0, 255, 0, 100); + evas_object_show(gesture_rectangle); + cover->gesture_rect = gesture_rectangle; + ecore_evas_callback_resize_set(e_comp->ee, _resize_canvas_gesture); +} + +static void +_gesture_shutdown(void) +{ + evas_object_del(cover->gesture_rect); + gesture_rectangle = NULL; + if (cover->tap_gesture_data.timer) + ecore_timer_del(cover->tap_gesture_data.timer); + if (cover->hover_gesture.timer) + ecore_timer_del(cover->hover_gesture.timer); + free(cover); +} + +int _e_mod_atspi_gestures_init(void) +{ + DEBUG("gesture init"); + _gesture_init(); + _events_init(); + + return 0; +} + +int _e_mod_atspi_gestures_shutdown(void) +{ + DEBUG("gesture shutdown"); + + _events_shutdown(); + _gesture_shutdown(); + + return 0; +} diff --git a/src/e_screen_reader_private.h b/src/e_screen_reader_private.h new file mode 100644 index 0000000..1f2d7f4 --- /dev/null +++ b/src/e_screen_reader_private.h @@ -0,0 +1,74 @@ +#ifndef E_SCREEN_READER_PRIVATE_H_ +#define E_SCREEN_READER_PRIVATE_H_ + +#include "e.h" +#include "e_screen_reader_config.h" +#include "e_comp.h" + +extern int _eina_log_dom; + +#define INFO(...) EINA_LOG_DOM_INFO(_eina_log_dom, __VA_ARGS__); +#define DEBUG(...) EINA_LOG_DOM_DBG(_eina_log_dom, __VA_ARGS__); +#define ERROR(...) EINA_LOG_DOM_ERR(_eina_log_dom, __VA_ARGS__); + +/** + * @brief Accessibility gestures + */ +enum _Gesture { + ONE_FINGER_HOVER, + TWO_FINGERS_HOVER, + THREE_FINGERS_HOVER, + ONE_FINGER_FLICK_LEFT, + ONE_FINGER_FLICK_RIGHT, + ONE_FINGER_FLICK_UP, + ONE_FINGER_FLICK_DOWN, + TWO_FINGERS_FLICK_LEFT, + TWO_FINGERS_FLICK_RIGHT, + TWO_FINGERS_FLICK_UP, + TWO_FINGERS_FLICK_DOWN, + THREE_FINGERS_FLICK_LEFT, + THREE_FINGERS_FLICK_RIGHT, + THREE_FINGERS_FLICK_UP, + THREE_FINGERS_FLICK_DOWN, + ONE_FINGER_SINGLE_TAP, + ONE_FINGER_DOUBLE_TAP, + ONE_FINGER_TRIPLE_TAP, + TWO_FINGERS_SINGLE_TAP, + TWO_FINGERS_DOUBLE_TAP, + TWO_FINGERS_TRIPLE_TAP, + THREE_FINGERS_SINGLE_TAP, + THREE_FINGERS_DOUBLE_TAP, + THREE_FINGERS_TRIPLE_TAP, + ONE_FINGER_FLICK_LEFT_RETURN, + ONE_FINGER_FLICK_RIGHT_RETURN, + ONE_FINGER_FLICK_UP_RETURN, + ONE_FINGER_FLICK_DOWN_RETURN, + TWO_FINGERS_FLICK_LEFT_RETURN, + TWO_FINGERS_FLICK_RIGHT_RETURN, + TWO_FINGERS_FLICK_UP_RETURN, + TWO_FINGERS_FLICK_DOWN_RETURN, + THREE_FINGERS_FLICK_LEFT_RETURN, + THREE_FINGERS_FLICK_RIGHT_RETURN, + THREE_FINGERS_FLICK_UP_RETURN, + THREE_FINGERS_FLICK_DOWN_RETURN, + GESTURES_COUNT, +}; +typedef enum _Gesture Gesture; + +typedef struct { + Gesture type; // Type of recognized gesture + int x_beg, x_end; // (x,y) coordinates when gesture begin + int y_beg, y_end; // (x,y) coordinates when gesture ends + int state; // 0 - begin, 1 - ongoing, 2 - ended +} Gesture_Info; + +int _e_mod_log_init(void); +void _e_mod_log_shutdown(void); + +extern int E_EVENT_ATSPI_GESTURE_DETECTED; + +int _e_mod_atspi_gestures_init(void); +int _e_mod_atspi_gestures_shutdown(void); + + +#endif /* E_SCREEN_READER_PRIVATE_H_ */