evas/gesture: Fix up a couple of APIs, add some FIXME

Some things have clearly not been tested. Some APIs have not been
modified after repeated review comments. C++ failed to build due to
"long" being used as a namespace.

Remaining issues:
 - The original finger_list API was broken by design. I didn't try to
   replace it yet.
 - Long tap is also broken by design: if no move happens the recognizer
   gets no event, and doesn't trigger anything when the timeout is
   reached. An API or event is lacking here.
 - Only 2 very basic gestures have been implemented. All the gestures
   from elm_gesture_layer need to be covered. None of the multi touch
   support has been really implemented, except for a single bool flag.
 - The configuration must be loaded from elm_config, passed on to the
   recognizers.
 - Some micro optimization may be required, especially if the input
   device is high frequency (eg. 1KHz gaming mouse).
This commit is contained in:
Jean-Philippe Andre 2017-10-19 11:05:28 +09:00
parent 20fad2e78e
commit 0a13e15c7d
19 changed files with 235 additions and 351 deletions

View File

@ -339,6 +339,7 @@ tests_evas_cxx_cxx_compile_test_SOURCES = tests/evas_cxx/cxx_compile_test.cc
tests_evas_cxx_cxx_compile_test_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ tests_evas_cxx_cxx_compile_test_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-I$(top_builddir)/src/lib/efl/interfaces/ \ -I$(top_builddir)/src/lib/efl/interfaces/ \
-I$(top_builddir)/src/lib/evas/canvas/ \ -I$(top_builddir)/src/lib/evas/canvas/ \
-I$(top_builddir)/src/lib/evas/gesture/ \
-I$(top_builddir)/src/lib/evas/include/ \ -I$(top_builddir)/src/lib/evas/include/ \
-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/evas_cxx\" \ -DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/evas_cxx\" \
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/evas_cxx\" \ -DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/evas_cxx\" \

View File

@ -175,7 +175,7 @@ _color_and_icon_set(infra_data *infra, char *name, int n, int max,
static void static void
finger_tap_start(void *data , Efl_Gesture *tap) finger_tap_start(void *data , Efl_Gesture *tap)
{ {
Eina_Vector2 pos = efl_gesture_tap_position_get(tap); Eina_Vector2 pos = efl_gesture_hotspot_get(tap);
_color_and_icon_set(data, TAP_NAME, 1, MAX_TAP, START_COLOR); _color_and_icon_set(data, TAP_NAME, 1, MAX_TAP, START_COLOR);
printf("Tap Gesture started x,y=<%f,%f> \n", pos.x, pos.y); printf("Tap Gesture started x,y=<%f,%f> \n", pos.x, pos.y);
@ -190,7 +190,7 @@ finger_tap_update(void *data , Efl_Gesture *tap EINA_UNUSED)
static void static void
finger_tap_end(void *data , Efl_Gesture *tap) finger_tap_end(void *data , Efl_Gesture *tap)
{ {
Eina_Vector2 pos = efl_gesture_tap_position_get(tap); Eina_Vector2 pos = efl_gesture_hotspot_get(tap);
_color_and_icon_set(data, TAP_NAME, 1, MAX_TAP, END_COLOR); _color_and_icon_set(data, TAP_NAME, 1, MAX_TAP, END_COLOR);
printf("Tap Gesture ended x,y=<%f,%f> \n", pos.x, pos.y); printf("Tap Gesture ended x,y=<%f,%f> \n", pos.x, pos.y);
@ -206,7 +206,7 @@ finger_tap_abort(void *data , Efl_Gesture *tap EINA_UNUSED)
static void static void
finger_long_tap_start(void *data , Efl_Gesture *tap) finger_long_tap_start(void *data , Efl_Gesture *tap)
{ {
Eina_Vector2 pos = efl_gesture_long_tap_position_get(tap); Eina_Vector2 pos = efl_gesture_hotspot_get(tap);
_color_and_icon_set(data, LONG_TAP_NAME, 1, MAX_TAP, START_COLOR); _color_and_icon_set(data, LONG_TAP_NAME, 1, MAX_TAP, START_COLOR);
printf("Long Tap Gesture started x,y=<%f,%f> \n", pos.x, pos.y); printf("Long Tap Gesture started x,y=<%f,%f> \n", pos.x, pos.y);
@ -222,7 +222,7 @@ finger_long_tap_update(void *data , Efl_Gesture *tap EINA_UNUSED)
static void static void
finger_long_tap_end(void *data , Efl_Gesture *tap) finger_long_tap_end(void *data , Efl_Gesture *tap)
{ {
Eina_Vector2 pos = efl_gesture_long_tap_position_get(tap); Eina_Vector2 pos = efl_gesture_hotspot_get(tap);
_color_and_icon_set(data, LONG_TAP_NAME, 1, MAX_TAP, END_COLOR); _color_and_icon_set(data, LONG_TAP_NAME, 1, MAX_TAP, END_COLOR);
printf("Long Tap Gesture ended x,y=<%f,%f> \n",pos.x, pos.y); printf("Long Tap Gesture ended x,y=<%f,%f> \n",pos.x, pos.y);
@ -322,7 +322,7 @@ test_gesture_framework(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
infra_data *infra = _infra_data_alloc(); infra_data *infra = _infra_data_alloc();
win = elm_win_util_standard_add("gesture-layer2", "Gesture Layer 2"); win = elm_win_util_standard_add("gesture-layer2", "Gesture (EO)");
elm_win_autodel_set(win, EINA_TRUE); elm_win_autodel_set(win, EINA_TRUE);
evas_object_smart_callback_add(win, "delete,request", my_win_del, infra); evas_object_smart_callback_add(win, "delete,request", my_win_del, infra);

View File

@ -3,19 +3,6 @@
#define MY_CLASS EFL_GESTURE_LONG_TAP_CLASS #define MY_CLASS EFL_GESTURE_LONG_TAP_CLASS
EOLIAN static void
_efl_gesture_long_tap_position_set(Eo *obj EINA_UNUSED, Efl_Gesture_Long_Tap_Data *pd,
Eina_Vector2 pos)
{
pd->pos = pos;
}
EOLIAN static Eina_Vector2
_efl_gesture_long_tap_position_get(Eo *obj EINA_UNUSED, Efl_Gesture_Long_Tap_Data *pd)
{
return pd->pos;
}
EOLIAN static Efl_Object * EOLIAN static Efl_Object *
_efl_gesture_long_tap_efl_object_constructor(Eo *obj, Efl_Gesture_Long_Tap_Data *pd EINA_UNUSED) _efl_gesture_long_tap_efl_object_constructor(Eo *obj, Efl_Gesture_Long_Tap_Data *pd EINA_UNUSED)
{ {

View File

@ -1,24 +1,11 @@
import efl_gesture_types; import efl_gesture_types;
class Efl.Gesture.Long.Tap(Efl.Gesture) class Efl.Gesture.Long_Tap (Efl.Gesture)
{ {
methods {
@property position {
[[This property holds the type of the gesture.]]
set {
}
get {
}
values {
pos: Eina.Vector2;[[position of the mouse event]]
}
}
}
event_prefix: efl; event_prefix: efl;
events { events {
gesture_long_tap; [[Event for tap gesture]] gesture,long_tap; [[Event for tap gesture]]
} }
implements { implements {
Efl.Object.constructor; Efl.Object.constructor;
Efl.Object.destructor; Efl.Object.destructor;

View File

@ -107,7 +107,6 @@ _efl_gesture_manager_callback_add_hook(Eo *obj, Eo *target, const Efl_Event_Desc
// add it to the gesture context. // add it to the gesture context.
eina_hash_list_append(pd->m_gesture_contex, &target, type); eina_hash_list_append(pd->m_gesture_contex, &target, type);
} }
} }
void void
@ -142,19 +141,15 @@ _efl_gesture_manager_filter_event(Eo *obj, Eo *target, void *event)
{ {
// get the touch event for this particular widget // get the touch event for this particular widget
touch_event = eina_hash_find(pd->m_object_events, &target); touch_event = eina_hash_find(pd->m_object_events, &target);
if (touch_event) if (!touch_event)
{
efl_gesture_touch_point_record(touch_event, pointer_data->tool, pointer_data->cur.x, pointer_data->cur.y,
pointer_data->timestamp, pointer_data->action);
}
else
{ {
touch_event = efl_add(EFL_GESTURE_TOUCH_CLASS, NULL); touch_event = efl_add(EFL_GESTURE_TOUCH_CLASS, NULL);
efl_gesture_touch_point_record(touch_event, pointer_data->tool, pointer_data->cur.x, pointer_data->cur.y,
pointer_data->timestamp, pointer_data->action);
eina_hash_add(pd->m_object_events, &target, touch_event); eina_hash_add(pd->m_object_events, &target, touch_event);
} }
efl_gesture_touch_point_record(touch_event, pointer_data->tool, pointer_data->cur,
pointer_data->timestamp, pointer_data->action);
if (efl_gesture_touch_state_get(touch_event) == EFL_GESTURE_TOUCH_UNKNOWN) if (efl_gesture_touch_state_get(touch_event) == EFL_GESTURE_TOUCH_UNKNOWN)
return; return;

View File

@ -1,24 +1,22 @@
import efl_gesture_types; import efl_gesture_types;
class Efl.Gesture.Manager(Efl.Object) class Efl.Gesture.Manager (Efl.Object)
{ {
methods { methods {
recognizer_register { recognizer_register {
[[This function is called to register a new Efl.Gesture.Recognizer]] [[This function is called to register a new Efl.Gesture.Recognizer]]
params { params {
@in recognizer: Efl.Gesture.Recognizer; [[The gesture recognizer object]] @in recognizer: Efl.Gesture.Recognizer; [[The gesture recognizer object]]
} }
return: ptr(const(Efl.Event.Description)); [[Returns the Efl.Event.Description type the recognizer supports]] return: ptr(const(Efl.Event.Description)); [[Returns the Efl.Event.Description type the recognizer supports]]
} }
recognizer_unregister { recognizer_unregister {
[[This function is called to unregister a Efl.Gesture.Recognizer ]] [[This function is called to unregister a Efl.Gesture.Recognizer]]
params { params {
@in recognizer: Efl.Gesture.Recognizer; [[The gesture recognizer object]] @in recognizer: Efl.Gesture.Recognizer; [[The gesture recognizer object]]
} }
} }
@property config{ @property config {
[[This property holds the config value for the recognizer]] [[This property holds the config value for the recognizer]]
set { set {
} }
@ -28,7 +26,7 @@ class Efl.Gesture.Manager(Efl.Object)
name: string; [[propery name]] name: string; [[propery name]]
} }
values { values {
value: ptr(any_value); [[value of the property]] value: any_value_ptr; [[value of the property]]
} }
} }
} }

View File

@ -31,12 +31,10 @@ struct _Efl_Gesture_Data
struct _Efl_Gesture_Tap_Data struct _Efl_Gesture_Tap_Data
{ {
Eina_Vector2 pos;
}; };
struct _Efl_Gesture_Long_Tap_Data struct _Efl_Gesture_Long_Tap_Data
{ {
Eina_Vector2 pos;
Ecore_Timer *timeout; Ecore_Timer *timeout;
Eina_Bool is_timeout; Eina_Bool is_timeout;
}; };

View File

@ -2,21 +2,17 @@
#define MY_CLASS EFL_GESTURE_RECOGNIZER_CLASS #define MY_CLASS EFL_GESTURE_RECOGNIZER_CLASS
EOLIAN static Eina_Value * EOLIAN static Eina_Value *
_efl_gesture_recognizer_config_get(Eo *obj EINA_UNUSED, Efl_Gesture_Recognizer_Data *pd, const char *name) _efl_gesture_recognizer_config_get(Eo *obj EINA_UNUSED, Efl_Gesture_Recognizer_Data *pd, const char *name)
{ {
return efl_gesture_manager_config_get(pd->manager, name); return efl_gesture_manager_config_get(pd->manager, name);
} }
EOLIAN static void EOLIAN static void
_efl_gesture_recognizer_reset(Eo *obj EINA_UNUSED, Efl_Gesture_Recognizer_Data *pd EINA_UNUSED, _efl_gesture_recognizer_reset(Eo *obj EINA_UNUSED, Efl_Gesture_Recognizer_Data *pd EINA_UNUSED,
Efl_Gesture *gesture EINA_UNUSED) Efl_Gesture *gesture EINA_UNUSED)
{ {
} }
#include "efl_gesture_recognizer.eo.c" #include "efl_gesture_recognizer.eo.c"

View File

@ -1,35 +1,36 @@
import efl_gesture_types; import efl_gesture_types;
abstract Efl.Gesture.Recognizer(Efl.Object) abstract Efl.Gesture.Recognizer (Efl.Object)
{ {
methods { methods {
create @pure_virtual{ create @pure_virtual {
[[This function is called to create a new Efl.Gesture object for the given target]] [[This function is called to create a new Efl.Gesture object for the given target]]
params { params {
@in target: Efl.Object; [[The target widget]] @in target: Efl.Object; [[The target widget]]
} }
return: Efl.Gesture; [[Returns the Efl.Gesture event object]] return: Efl.Gesture; [[Returns the Efl.Gesture event object]]
} }
recognize @pure_virtual{ recognize @pure_virtual {
[[Handles the given event for the watched object, updating the state of the gesture object as required, and returns a suitable result for the current recognition step.]] [[Handles the given event for the watched object.
Updates the state of the gesture object as required, and returns a
suitable result for the current recognition step.
]]
params { params {
@in gesture: Efl.Gesture; [[The gesture object]] @in gesture: Efl.Gesture; [[The gesture object]]
@in watched: Efl.Object; [[The watched object]] @in watched: Efl.Object; [[The watched object]]
@in event: Efl.Gesture.Touch; [[The pointer event]] @in event: Efl.Gesture.Touch; [[The pointer event]]
} }
return: Efl.Gesture.Recognizer.Result; [[Returns the Efl.Gesture event object]] return: Efl.Gesture.Recognizer_Result; [[Returns the Efl.Gesture event object]]
} }
/* FIXME: This function is not used? */
reset { reset {
[[This function is called by the framework to reset a given gesture.]] [[This function is called by the framework to reset a given gesture.]]
params { params {
@in gesture: Efl.Gesture; [[The gesture object]] @in gesture: Efl.Gesture; [[The gesture object]]
} }
} }
@property config{ @property config {
[[This property holds the config value for the recognizer]] [[This property holds the config value for the recognizer]]
get { get {
} }
@ -37,7 +38,7 @@ abstract Efl.Gesture.Recognizer(Efl.Object)
name: string; [[propery name]] name: string; [[propery name]]
} }
values { values {
value: ptr(any_value); [[value of the property]] value: any_value_ptr; [[value of the property]]
} }
} }
} }

View File

@ -4,26 +4,8 @@
#define LONG_TAP_TIME_OUT 0.2 #define LONG_TAP_TIME_OUT 0.2
typedef struct _Efl_Gesture_Recognizer_Long_Tap_Data
{
} Efl_Gesture_Recognizer_Long_Tap_Data;
EOLIAN static Efl_Object *
_efl_gesture_recognizer_long_tap_efl_object_constructor(Eo *obj, Efl_Gesture_Recognizer_Long_Tap_Data *pd EINA_UNUSED)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
return obj;
}
EOLIAN static void
_efl_gesture_recognizer_long_tap_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Gesture_Recognizer_Long_Tap_Data *pd EINA_UNUSED)
{
efl_destructor(efl_super(obj, MY_CLASS));
}
EOLIAN static Efl_Gesture * EOLIAN static Efl_Gesture *
_efl_gesture_recognizer_long_tap_efl_gesture_recognizer_create(Eo *obj, Efl_Gesture_Recognizer_Long_Tap_Data *pd EINA_UNUSED, _efl_gesture_recognizer_long_tap_efl_gesture_recognizer_create(Eo *obj, void *pd EINA_UNUSED,
Efl_Object *target EINA_UNUSED) Efl_Object *target EINA_UNUSED)
{ {
return efl_add(EFL_GESTURE_LONG_TAP_CLASS, obj); return efl_add(EFL_GESTURE_LONG_TAP_CLASS, obj);
@ -34,96 +16,95 @@ _long_tap_timeout_cb(void *data)
{ {
Efl_Gesture_Long_Tap_Data *ltp = data; Efl_Gesture_Long_Tap_Data *ltp = data;
/* FIXME: Needs to propagate this event back to evas! */
ltp->is_timeout = EINA_TRUE; ltp->is_timeout = EINA_TRUE;
return ECORE_CALLBACK_RENEW; return ECORE_CALLBACK_RENEW;
} }
EOLIAN static Efl_Gesture_Recognizer_Result EOLIAN static Efl_Gesture_Recognizer_Result
_efl_gesture_recognizer_long_tap_efl_gesture_recognizer_recognize(Eo *obj EINA_UNUSED, _efl_gesture_recognizer_long_tap_efl_gesture_recognizer_recognize(Eo *obj EINA_UNUSED,
Efl_Gesture_Recognizer_Long_Tap_Data *pd EINA_UNUSED, void *pd EINA_UNUSED,
Efl_Gesture *gesture, Efl_Object *watched EINA_UNUSED, Efl_Gesture *gesture, Efl_Object *watched EINA_UNUSED,
Efl_Gesture_Touch *event) Efl_Gesture_Touch *event)
{ {
double dist_x, dist_y, length, x, y; double length; // Manhattan distance
Eina_Vector2 pos; Eina_Vector2 pos, dist;
Efl_Gesture_Recognizer_Result result = EFL_GESTURE_CANCEL; Efl_Gesture_Recognizer_Result result = EFL_GESTURE_CANCEL;
Efl_Gesture_Long_Tap_Data *ltp = efl_data_scope_get(gesture, EFL_GESTURE_LONG_TAP_CLASS); Efl_Gesture_Long_Tap_Data *ltp = efl_data_scope_get(gesture, EFL_GESTURE_LONG_TAP_CLASS);
switch (efl_gesture_touch_state_get(event)) switch (efl_gesture_touch_state_get(event))
{ {
case EFL_GESTURE_TOUCH_BEGIN: case EFL_GESTURE_TOUCH_BEGIN:
{ {
efl_gesture_touch_start_point(event, &x, &y); pos = efl_gesture_touch_start_point_get(event);
eina_vector2_set(&pos, x, y); efl_gesture_hotspot_set(gesture, pos);
efl_gesture_long_tap_position_set(gesture, pos); if (ltp->timeout)
efl_gesture_hotspot_set(gesture, pos); ecore_timer_del(ltp->timeout);
if (ltp->timeout) ltp->timeout = ecore_timer_add(LONG_TAP_TIME_OUT,
ecore_timer_del(ltp->timeout); _long_tap_timeout_cb, ltp);
ltp->timeout = ecore_timer_add(LONG_TAP_TIME_OUT, result = EFL_GESTURE_MAYBE;
_long_tap_timeout_cb, ltp); break;
result = EFL_GESTURE_MAYBE; }
break; case EFL_GESTURE_TOUCH_UPDATE:
} {
case EFL_GESTURE_TOUCH_UPDATE: if (!efl_gesture_touch_multi_touch_get(event))
{ {
if (!efl_gesture_touch_multi_touch_get(event)) dist = efl_gesture_touch_distance(event, 0);
{ length = fabs(dist.x) + fabs(dist.y);
efl_gesture_touch_distance(event, 0, &dist_x, &dist_y); if (length <= 50) // FIXME config!
length = abs(dist_x) + abs(dist_y); {
if (length <= 50) if (ltp->is_timeout)
{ {
if (ltp->is_timeout) ltp->is_timeout = EINA_FALSE;
{ result = EFL_GESTURE_TRIGGER;
ltp->is_timeout = EINA_FALSE; }
result = EFL_GESTURE_TRIGGER; else
} {
else result = EFL_GESTURE_MAYBE;
{ }
result = EFL_GESTURE_MAYBE; }
} else
} {
else result = EFL_GESTURE_CANCEL;
{ }
result = EFL_GESTURE_CANCEL; }
} break;
} }
break; case EFL_GESTURE_TOUCH_END:
} {
case EFL_GESTURE_TOUCH_END: if (ltp->timeout)
{ ecore_timer_del(ltp->timeout);
if (ltp->timeout) ltp->timeout = NULL;
ecore_timer_del(ltp->timeout); if (efl_gesture_state_get(gesture) != EFL_GESTURE_NONE &&
ltp->timeout = NULL; !efl_gesture_touch_multi_touch_get(event))
if (efl_gesture_state_get(gesture) != EFL_GESTURE_NONE && {
!efl_gesture_touch_multi_touch_get(event)) dist = efl_gesture_touch_distance(event, 0);
{ length = fabs(dist.x) + fabs(dist.y);
efl_gesture_touch_distance(event, 0, &dist_x, &dist_y); if (length <= 50 && ltp->is_timeout) // FIXME config!
length = abs(dist_x) + abs(dist_y); {
if (length <= 50 && ltp->is_timeout) result = EFL_GESTURE_FINISH;
{ }
result = EFL_GESTURE_FINISH; else
} {
else result = EFL_GESTURE_CANCEL;
{ }
result = EFL_GESTURE_CANCEL; }
} break;
} }
break; default:
} break;
default: }
break;
}
return result; return result;
} }
EOLIAN static void EOLIAN static void
_efl_gesture_recognizer_long_tap_efl_gesture_recognizer_reset(Eo *obj, _efl_gesture_recognizer_long_tap_efl_gesture_recognizer_reset(Eo *obj,
Efl_Gesture_Recognizer_Long_Tap_Data *pd EINA_UNUSED, void *pd EINA_UNUSED,
Efl_Gesture *gesture) Efl_Gesture *gesture)
{ {
Efl_Gesture_Long_Tap_Data *ltp; Efl_Gesture_Long_Tap_Data *ltp;
ltp = efl_data_scope_get(gesture, EFL_GESTURE_LONG_TAP_CLASS); ltp = efl_data_scope_get(gesture, EFL_GESTURE_LONG_TAP_CLASS);
eina_vector2_set(&ltp->pos, 0, 0);
if (ltp->timeout) if (ltp->timeout)
ecore_timer_del(ltp->timeout); ecore_timer_del(ltp->timeout);
ltp->timeout = NULL; ltp->timeout = NULL;

View File

@ -1,8 +1,7 @@
class Efl.Gesture.Recognizer.Long.Tap(Efl.Gesture.Recognizer) class Efl.Gesture.Recognizer_Long_Tap (Efl.Gesture.Recognizer)
{ {
data: null;
implements { implements {
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Gesture.Recognizer.create; Efl.Gesture.Recognizer.create;
Efl.Gesture.Recognizer.recognize; Efl.Gesture.Recognizer.recognize;
Efl.Gesture.Recognizer.reset; Efl.Gesture.Recognizer.reset;

View File

@ -2,26 +2,8 @@
#define MY_CLASS EFL_GESTURE_RECOGNIZER_TAP_CLASS #define MY_CLASS EFL_GESTURE_RECOGNIZER_TAP_CLASS
typedef struct _Efl_Gesture_Recognizer_Tap_Data
{
} Efl_Gesture_Recognizer_Tap_Data;
EOLIAN static Efl_Object *
_efl_gesture_recognizer_tap_efl_object_constructor(Eo *obj, Efl_Gesture_Recognizer_Tap_Data *pd EINA_UNUSED)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
return obj;
}
EOLIAN static void
_efl_gesture_recognizer_tap_efl_object_destructor(Eo *obj EINA_UNUSED, Efl_Gesture_Recognizer_Tap_Data *pd EINA_UNUSED)
{
efl_destructor(efl_super(obj, MY_CLASS));
}
EOLIAN static Efl_Gesture * EOLIAN static Efl_Gesture *
_efl_gesture_recognizer_tap_efl_gesture_recognizer_create(Eo *obj, Efl_Gesture_Recognizer_Tap_Data *pd EINA_UNUSED, _efl_gesture_recognizer_tap_efl_gesture_recognizer_create(Eo *obj, void *pd EINA_UNUSED,
Efl_Object *target EINA_UNUSED) Efl_Object *target EINA_UNUSED)
{ {
return efl_add(EFL_GESTURE_TAP_CLASS, obj); return efl_add(EFL_GESTURE_TAP_CLASS, obj);
@ -29,58 +11,45 @@ _efl_gesture_recognizer_tap_efl_gesture_recognizer_create(Eo *obj, Efl_Gesture_R
EOLIAN static Efl_Gesture_Recognizer_Result EOLIAN static Efl_Gesture_Recognizer_Result
_efl_gesture_recognizer_tap_efl_gesture_recognizer_recognize(Eo *obj EINA_UNUSED, _efl_gesture_recognizer_tap_efl_gesture_recognizer_recognize(Eo *obj EINA_UNUSED,
Efl_Gesture_Recognizer_Tap_Data *pd EINA_UNUSED, void *pd EINA_UNUSED,
Efl_Gesture *gesture, Efl_Object *watched EINA_UNUSED, Efl_Gesture *gesture, Efl_Object *watched EINA_UNUSED,
Efl_Gesture_Touch *event EINA_UNUSED) Efl_Gesture_Touch *event EINA_UNUSED)
{ {
double dist_x, dist_y, length, x, y; double length;
Eina_Vector2 pos; Eina_Vector2 pos, dist;
Efl_Gesture_Recognizer_Result result = EFL_GESTURE_CANCEL; Efl_Gesture_Recognizer_Result result = EFL_GESTURE_CANCEL;
switch (efl_gesture_touch_state_get(event)) switch (efl_gesture_touch_state_get(event))
{ {
case EFL_GESTURE_TOUCH_BEGIN: case EFL_GESTURE_TOUCH_BEGIN:
{ {
efl_gesture_touch_start_point(event, &x, &y); pos = efl_gesture_touch_start_point_get(event);
eina_vector2_set(&pos, x, y); efl_gesture_hotspot_set(gesture, pos);
efl_gesture_tap_position_set(gesture, pos); result = EFL_GESTURE_TRIGGER;
efl_gesture_hotspot_set(gesture, pos); break;
result = EFL_GESTURE_TRIGGER; }
break; case EFL_GESTURE_TOUCH_UPDATE:
} case EFL_GESTURE_TOUCH_END:
case EFL_GESTURE_TOUCH_UPDATE: {
case EFL_GESTURE_TOUCH_END: if (efl_gesture_state_get(gesture) != EFL_GESTURE_NONE &&
{ !efl_gesture_touch_multi_touch_get(event))
if (efl_gesture_state_get(gesture) != EFL_GESTURE_NONE && {
!efl_gesture_touch_multi_touch_get(event)) dist = efl_gesture_touch_distance(event, 0);
{ length = fabs(dist.x) + fabs(dist.y);
efl_gesture_touch_distance(event, 0, &dist_x, &dist_y); if (length <= 50) // FIXME config!
length = abs(dist_x) + abs(dist_y); {
if (length <= 50) if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_END)
{ result = EFL_GESTURE_FINISH;
if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_END) else
result = EFL_GESTURE_FINISH; result = EFL_GESTURE_TRIGGER;
else }
result = EFL_GESTURE_TRIGGER; }
} break;
} }
break; default:
} break;
default: }
break;
}
return result; return result;
} }
EOLIAN static void
_efl_gesture_recognizer_tap_efl_gesture_recognizer_reset(Eo *obj,
Efl_Gesture_Recognizer_Tap_Data *pd EINA_UNUSED,
Efl_Gesture *gesture)
{
Efl_Gesture_Tap_Data *tap;
tap = efl_data_scope_get(gesture, EFL_GESTURE_TAP_CLASS);
eina_vector2_set(&tap->pos, 0, 0);
efl_gesture_recognizer_reset(efl_super(obj, MY_CLASS), gesture);
}
#include "efl_gesture_recognizer_tap.eo.c" #include "efl_gesture_recognizer_tap.eo.c"

View File

@ -1,10 +1,8 @@
class Efl.Gesture.Recognizer.Tap(Efl.Gesture.Recognizer) class Efl.Gesture.Recognizer_Tap (Efl.Gesture.Recognizer)
{ {
data: null;
implements { implements {
Efl.Object.constructor;
Efl.Object.destructor;
Efl.Gesture.Recognizer.create; Efl.Gesture.Recognizer.create;
Efl.Gesture.Recognizer.recognize; Efl.Gesture.Recognizer.recognize;
Efl.Gesture.Recognizer.reset;
} }
} }

View File

@ -3,18 +3,6 @@
#define MY_CLASS EFL_GESTURE_TAP_CLASS #define MY_CLASS EFL_GESTURE_TAP_CLASS
EOLIAN static void
_efl_gesture_tap_position_set(Eo *obj EINA_UNUSED, Efl_Gesture_Tap_Data *pd, Eina_Vector2 pos)
{
pd->pos = pos;
}
EOLIAN static Eina_Vector2
_efl_gesture_tap_position_get(Eo *obj EINA_UNUSED, Efl_Gesture_Tap_Data *pd)
{
return pd->pos;
}
EOLIAN static Efl_Object * EOLIAN static Efl_Object *
_efl_gesture_tap_efl_object_constructor(Eo *obj, Efl_Gesture_Tap_Data *pd EINA_UNUSED) _efl_gesture_tap_efl_object_constructor(Eo *obj, Efl_Gesture_Tap_Data *pd EINA_UNUSED)
{ {

View File

@ -2,23 +2,10 @@ import efl_gesture_types;
class Efl.Gesture.Tap(Efl.Gesture) class Efl.Gesture.Tap(Efl.Gesture)
{ {
methods {
@property position {
[[This property holds the type of the gesture.]]
set {
}
get {
}
values {
pos: Eina.Vector2;[[position of the mouse event]]
}
}
}
event_prefix: efl; event_prefix: efl;
events { events {
gesture,tap; [[Event for tap gesture]] gesture,tap; [[Event for tap gesture]]
} }
implements { implements {
Efl.Object.constructor; Efl.Object.constructor;
} }

View File

@ -5,19 +5,18 @@
typedef struct _Pointer_Data typedef struct _Pointer_Data
{ {
struct struct
{ {
double x; Eina_Vector2 pos;
double y; double timestamp;
double timestamp; } start, prev, cur;
} start, prev, cur ;
Efl_Pointer_Action action; Efl_Pointer_Action action;
}Pointer_Data; } Pointer_Data;
typedef struct _Efl_Gesture_Touch_Data typedef struct _Efl_Gesture_Touch_Data
{ {
Efl_Gesture_Touch_State type; Efl_Gesture_Touch_State state;
Eina_Hash *touch_points; Eina_Hash *touch_points;
Eina_List *finger_list; int touch_down;
Eina_Bool multi_touch; Eina_Bool multi_touch;
Eo *target; Eo *target;
} Efl_Gesture_Touch_Data; } Efl_Gesture_Touch_Data;
@ -32,12 +31,20 @@ static void _hash_free_cb(Pointer_Data *point)
free(point); free(point);
} }
static inline void
_touch_points_reset(Efl_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 * EOLIAN static Efl_Object *
_efl_gesture_touch_efl_object_constructor(Eo *obj, Efl_Gesture_Touch_Data *pd) _efl_gesture_touch_efl_object_constructor(Eo *obj, Efl_Gesture_Touch_Data *pd)
{ {
obj = efl_constructor(efl_super(obj, MY_CLASS)); obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->touch_points = eina_hash_int32_new(EINA_FREE_CB(_hash_free_cb)); _touch_points_reset(pd);
return obj; return obj;
} }
@ -51,23 +58,28 @@ _efl_gesture_touch_efl_object_destructor(Eo *obj, Efl_Gesture_Touch_Data *pd)
EOLIAN static Efl_Gesture_Touch_State EOLIAN static Efl_Gesture_Touch_State
_efl_gesture_touch_state_get(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd) _efl_gesture_touch_state_get(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd)
{ {
return pd->type; return pd->state;
} }
EOLIAN static void EOLIAN static void
_efl_gesture_touch_point_record(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd, _efl_gesture_touch_point_record(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd,
int id, double x, double y, double timestamp, Efl_Pointer_Action action) int id, Eina_Vector2 pos, double timestamp, Efl_Pointer_Action action)
{ {
Pointer_Data *point = eina_hash_find(pd->touch_points, &id); 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) if (point)
{ {
// the point already exists. update the cur and prev point // the point already exists. update the cur and prev point
point->prev.x = point->cur.x; point->prev = point->cur;
point->prev.y = point->cur.y; point->cur.pos = pos;
point->prev.timestamp = point->cur.timestamp; point->cur.timestamp = timestamp;
point->cur.x = x;
point->cur.y = y;
point->cur.timestamp = timestamp;
} }
else else
{ {
@ -78,13 +90,13 @@ _efl_gesture_touch_point_record(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd,
return; return;
} }
point = calloc(1, sizeof(Pointer_Data)); point = calloc(1, sizeof(Pointer_Data));
point->start.x = point->prev.x = point->cur.x = x; if (!point) return;
point->start.y = point->prev.y = point->cur.y = y; point->start.pos = point->prev.pos = point->cur.pos = pos;
point->start.timestamp = point->prev.timestamp = point->cur.timestamp = timestamp; point->start.timestamp = point->prev.timestamp = point->cur.timestamp = timestamp;
// add to the hash // add to the hash
eina_hash_add(pd->touch_points, &id, point); eina_hash_add(pd->touch_points, &id, point);
pd->finger_list = eina_list_append(pd->finger_list, &id); // FIXME: finger_list was broken
if (id) if (id)
pd->multi_touch = EINA_TRUE; pd->multi_touch = EINA_TRUE;
} }
@ -92,17 +104,21 @@ _efl_gesture_touch_point_record(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd,
if (!id && (action == EFL_POINTER_ACTION_DOWN)) if (!id && (action == EFL_POINTER_ACTION_DOWN))
{ {
pd->type = EFL_GESTURE_TOUCH_BEGIN; pd->state = EFL_GESTURE_TOUCH_BEGIN;
} }
else if ((action == EFL_POINTER_ACTION_UP) && (eina_list_count(pd->finger_list) == 1)) else if ((action == EFL_POINTER_ACTION_UP) && (pd->touch_down == 0))
{ {
pd->type = EFL_GESTURE_TOUCH_END; pd->state = EFL_GESTURE_TOUCH_END;
} }
else else
{ {
pd->type = EFL_GESTURE_TOUCH_UPDATE; pd->state = EFL_GESTURE_TOUCH_UPDATE;
} }
return;
bad_fingers:
ERR("Inconsistent touch events received!");
_touch_points_reset(pd);
} }
EOLIAN static Eina_Bool EOLIAN static Eina_Bool
@ -111,56 +127,43 @@ _efl_gesture_touch_multi_touch_get(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *
return pd->multi_touch; return pd->multi_touch;
} }
EOLIAN static void EOLIAN static Eina_Vector2
_efl_gesture_touch_start_point(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd, double *x, double *y) _efl_gesture_touch_start_point_get(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd)
{ {
int tool = 0; int tool = 0;
Pointer_Data *point = eina_hash_find(pd->touch_points, &tool); Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
Eina_Vector2 vec = { 0, 0 };
*x = 0; if (!point)
*y = 0; return vec;
if (point) return point->start.pos;
{
*x = point->start.x;
*y = point->start.y;
}
} }
EOLIAN static void EOLIAN static Eina_Vector2
_efl_gesture_touch_delta(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd, int tool, double *x, double *y) _efl_gesture_touch_delta(const Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd, int tool)
{ {
Pointer_Data *point = eina_hash_find(pd->touch_points, &tool); Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
Eina_Vector2 vec = { 0, 0 };
*x = 0; if (!point)
*y = 0; return vec;
if (point) eina_vector2_subtract(&vec, &point->cur.pos, &point->prev.pos);
{ return vec;
*x = point->cur.x - point->prev.x;
*y = point->cur.y - point->prev.y;
}
} }
EOLIAN static void EOLIAN static Eina_Vector2
_efl_gesture_touch_distance(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd, int tool, double *x, double *y) _efl_gesture_touch_distance(const Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd, int tool)
{ {
Pointer_Data *point = eina_hash_find(pd->touch_points, &tool); Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
Eina_Vector2 vec = { 0, 0 };
*x = 0; if (!point)
*y = 0; return vec;
if (point) eina_vector2_subtract(&vec, &point->cur.pos, &point->start.pos);
{ return vec;
*x = point->cur.x - point->start.x;
*y = point->cur.y - point->start.y;
}
}
EOLIAN static const Eina_List *
_efl_gesture_touch_finger_list_get(Eo *obj EINA_UNUSED, Efl_Gesture_Touch_Data *pd)
{
return pd->finger_list;
} }
#include "efl_gesture_touch.eo.c" #include "efl_gesture_touch.eo.c"

View File

@ -1,36 +1,39 @@
import efl_gesture_types; import efl_gesture_types;
import efl_input_types; import efl_input_types;
/* FIXME: This class lacks a lot of useful helpers. */
class Efl.Gesture.Touch(Efl.Object) class Efl.Gesture.Touch(Efl.Object)
{ {
methods { methods {
point_record { point_record {
params { params {
@in tool : int; [[The finger id ]] @in tool : int; [[The finger id ]]
@in x : double; [[The x co-ordinate of the event]] @in pos : Eina.Vector2; [[Position of the event]]
@in y : double; [[The y co-ordinate of the event]]
@in timestamp : double; [[The timestamp of the event]] @in timestamp : double; [[The timestamp of the event]]
@in action : Efl.Pointer.Action; [[action of the event]] @in action : Efl.Pointer.Action; [[action of the event]]
} }
} }
delta { /* FIXME: This is most likely not useful (without timestamps). */
delta @const {
[[Compute the distance between the last two events]]
params { params {
@in tool : int; [[The finger id ]] @in tool : int; [[The finger id ]]
@out x : double; [[The x co-ordinate of the event]]
@out y : double; [[The y co-ordinate of the event]]
} }
return: Eina.Vector2; [[The distance vector.]]
} }
distance { distance @const {
[[Compute the distance between the first touch and the last event.]]
params { params {
@in tool : int; [[The finger id ]] @in tool : int; [[The finger id ]]
@out x : double; [[The x co-ordinate of the event]]
@out y : double; [[The y co-ordinate of the event]]
} }
return: Eina.Vector2; [[The distance vector.]]
} }
start_point { @property start_point {
params { [[Returns the first touch point.]]
@out x : double; [[The x co-ordinate of the event]] get {}
@out y : double; [[The y co-ordinate of the event]] values {
pos: Eina.Vector2; [[The start position.]]
} }
} }
@property multi_touch { @property multi_touch {
@ -45,14 +48,7 @@ class Efl.Gesture.Touch(Efl.Object)
return : Efl.Gesture.Touch.State; [[touch event state]] return : Efl.Gesture.Touch.State; [[touch event state]]
} }
} }
@property finger_list { /* FIXME: finger_list was broken by design - TODO */
get {
[[Get the list of finger id .]]
}
values {
ret: const(list<int>); [[List of finger id]]
}
}
} }
implements { implements {
Efl.Object.constructor; Efl.Object.constructor;

View File

@ -19,7 +19,7 @@ enum Efl.Gesture.State
canceled, [[A gesture was canceled.]] canceled, [[A gesture was canceled.]]
} }
enum Efl.Gesture.Recognizer.Result enum Efl.Gesture.Recognizer_Result
{ {
[[ This enum type describes the state of a gesture recognizer. ]] [[ This enum type describes the state of a gesture recognizer. ]]
legacy: efl_gesture; legacy: efl_gesture;