summaryrefslogtreecommitdiff
path: root/src/lib/evas/gesture/efl_canvas_gesture_touch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/evas/gesture/efl_canvas_gesture_touch.c')
-rw-r--r--src/lib/evas/gesture/efl_canvas_gesture_touch.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/lib/evas/gesture/efl_canvas_gesture_touch.c b/src/lib/evas/gesture/efl_canvas_gesture_touch.c
new file mode 100644
index 0000000000..9f997f59e6
--- /dev/null
+++ b/src/lib/evas/gesture/efl_canvas_gesture_touch.c
@@ -0,0 +1,169 @@
+#include "efl_canvas_gesture_private.h"
+
+#define MY_CLASS EFL_CANVAS_GESTURE_TOUCH_CLASS
+
+typedef struct _Pointer_Data
+{
+ struct
+ {
+ Eina_Vector2 pos;
+ double timestamp;
+ } start, prev, cur;
+ Efl_Pointer_Action action;
+} Pointer_Data;
+
+typedef struct _Efl_Canvas_Gesture_Touch_Data
+{
+ Efl_Canvas_Gesture_Touch_State state;
+ Eina_Hash *touch_points;
+ int touch_down;
+ Eina_Bool multi_touch;
+ Eo *target;
+} Efl_Canvas_Gesture_Touch_Data;
+
+
+// This event object accumulates all the touch points
+// that are directed to a particular object from the
+// first finger down to the last finger up
+
+static void _hash_free_cb(Pointer_Data *point)
+{
+ free(point);
+}
+
+static inline void
+_touch_points_reset(Efl_Canvas_Gesture_Touch_Data *pd)
+{
+ eina_hash_free(pd->touch_points);
+ pd->touch_points = eina_hash_int32_new(EINA_FREE_CB(_hash_free_cb));
+ pd->touch_down = 0;
+ pd->state = EFL_GESTURE_TOUCH_UNKNOWN;
+}
+
+EOLIAN static Efl_Object *
+_efl_canvas_gesture_touch_efl_object_constructor(Eo *obj, Efl_Canvas_Gesture_Touch_Data *pd)
+{
+ obj = efl_constructor(efl_super(obj, MY_CLASS));
+ _touch_points_reset(pd);
+ return obj;
+}
+
+EOLIAN static void
+_efl_canvas_gesture_touch_efl_object_destructor(Eo *obj, Efl_Canvas_Gesture_Touch_Data *pd)
+{
+ eina_hash_free(pd->touch_points);
+ efl_destructor(efl_super(obj, MY_CLASS));
+}
+
+EOLIAN static Efl_Canvas_Gesture_Touch_State
+_efl_canvas_gesture_touch_state_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
+{
+ return pd->state;
+}
+
+EOLIAN static void
+_efl_canvas_gesture_touch_point_record(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd,
+ int id, Eina_Vector2 pos, double timestamp, Efl_Pointer_Action action)
+{
+ Pointer_Data *point = eina_hash_find(pd->touch_points, &id);
+
+ if (action == EFL_POINTER_ACTION_DOWN)
+ pd->touch_down++;
+ else if ((action == EFL_POINTER_ACTION_UP) ||
+ (action == EFL_POINTER_ACTION_CANCEL))
+ pd->touch_down--;
+ EINA_SAFETY_ON_FALSE_GOTO(pd->touch_down >= 0, bad_fingers);
+
+ if (point)
+ {
+ // the point already exists. update the cur and prev point
+ point->prev = point->cur;
+ point->cur.pos = pos;
+ point->cur.timestamp = timestamp;
+ }
+ else
+ {
+ // new finger
+ if (!id && (action != EFL_POINTER_ACTION_DOWN))
+ {
+ // discard any other event
+ return;
+ }
+ point = calloc(1, sizeof(Pointer_Data));
+ if (!point) return;
+ point->start.pos = point->prev.pos = point->cur.pos = pos;
+ point->start.timestamp = point->prev.timestamp = point->cur.timestamp = timestamp;
+
+ // add to the hash
+ eina_hash_add(pd->touch_points, &id, point);
+ // FIXME: finger_list was broken
+ if (id)
+ pd->multi_touch = EINA_TRUE;
+ }
+ point->action = action;
+
+ if (!id && (action == EFL_POINTER_ACTION_DOWN))
+ {
+ pd->state = EFL_GESTURE_TOUCH_BEGIN;
+ }
+ else if ((action == EFL_POINTER_ACTION_UP) && (pd->touch_down == 0))
+ {
+ pd->state = EFL_GESTURE_TOUCH_END;
+ }
+ else
+ {
+ pd->state = EFL_GESTURE_TOUCH_UPDATE;
+ }
+ return;
+
+bad_fingers:
+ ERR("Inconsistent touch events received!");
+ _touch_points_reset(pd);
+}
+
+EOLIAN static Eina_Bool
+_efl_canvas_gesture_touch_multi_touch_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
+{
+ return pd->multi_touch;
+}
+
+EOLIAN static Eina_Vector2
+_efl_canvas_gesture_touch_start_point_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
+{
+ int tool = 0;
+ Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
+ Eina_Vector2 vec = { 0, 0 };
+
+ if (!point)
+ return vec;
+
+ return point->start.pos;
+}
+
+EOLIAN static Eina_Vector2
+_efl_canvas_gesture_touch_delta(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd, int tool)
+{
+ Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
+ Eina_Vector2 vec = { 0, 0 };
+
+ if (!point)
+ return vec;
+
+ eina_vector2_subtract(&vec, &point->cur.pos, &point->prev.pos);
+ return vec;
+}
+
+EOLIAN static Eina_Vector2
+_efl_canvas_gesture_touch_distance(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd, int tool)
+{
+ Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
+ Eina_Vector2 vec = { 0, 0 };
+
+ if (!point)
+ return vec;
+
+ eina_vector2_subtract(&vec, &point->cur.pos, &point->start.pos);
+ return vec;
+}
+
+#include "efl_canvas_gesture_touch.eo.c"