efl/src/lib/evas/gesture/efl_canvas_gesture_recogniz...

198 lines
6.2 KiB
C

#include "efl_canvas_gesture_private.h"
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_MOMENTUM_CLASS
#define MOMENTUM_TIMEOUT 50
#define THUMBSCROLL_FRICTION 0.95
#define THUMBSCROLL_MOMENTUM_THRESHOLD 100.0
#define EFL_GESTURE_MINIMUM_MOMENTUM 0.001
EOLIAN static Efl_Canvas_Gesture *
_efl_canvas_gesture_recognizer_momentum_efl_canvas_gesture_recognizer_add(Eo *obj, Efl_Canvas_Gesture_Recognizer_Momentum_Data *pd EINA_UNUSED, Efl_Object *target EINA_UNUSED)
{
return efl_add(EFL_CANVAS_GESTURE_MOMENTUM_CLASS, obj);
}
static void
_momentum_set(Eo *obj,
Efl_Canvas_Gesture_Momentum_Data *md,
Eina_Position2D v1,
Eina_Position2D v2,
unsigned int t1,
unsigned int t2)
{
Evas_Coord velx = 0, vely = 0, vel;
Evas_Coord dx = v2.x - v1.x;
Evas_Coord dy = v2.y - v1.y;
int dt = t2 - t1;
Eina_Value *tf, *tmt;
double thumbscroll_friction, thumbscroll_momentum_threshold;
if (dt > 0)
{
velx = (dx * 1000) / dt;
vely = (dy * 1000) / dt;
}
vel = sqrt((velx * velx) + (vely * vely));
tf = efl_gesture_recognizer_config_get(obj, "thumbscroll_friction");
if (tf) eina_value_get(tf, &thumbscroll_friction);
else thumbscroll_friction = THUMBSCROLL_FRICTION;
tmt = efl_gesture_recognizer_config_get(obj, "thumbscroll_momentum_threshold");
if (tmt) eina_value_get(tmt, &thumbscroll_momentum_threshold);
else thumbscroll_momentum_threshold = THUMBSCROLL_MOMENTUM_THRESHOLD;
if ((thumbscroll_friction > 0.0) &&
(vel > thumbscroll_momentum_threshold)) /* report
* momentum */
{
md->momentum.x = velx;
md->momentum.y = vely;
}
else
{
md->momentum.x = 0;
md->momentum.y = 0;
}
}
static int
_direction_get(Evas_Coord xx1,
Evas_Coord xx2)
{
if (xx2 < xx1) return -1;
if (xx2 > xx1) return 1;
return 0;
}
EOLIAN static Efl_Canvas_Gesture_Recognizer_Result
_efl_canvas_gesture_recognizer_momentum_efl_canvas_gesture_recognizer_recognize(Eo *obj,
Efl_Canvas_Gesture_Recognizer_Momentum_Data *pd,
Efl_Canvas_Gesture *gesture, Efl_Object *watched EINA_UNUSED,
Efl_Canvas_Gesture_Touch *event)
{
Eina_Value *val;
unsigned char glayer_continues_enable;
Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_CANCEL;
Efl_Canvas_Gesture_Momentum_Data *md = efl_data_scope_get(gesture, EFL_CANVAS_GESTURE_MOMENTUM_CLASS);
val = efl_gesture_recognizer_config_get(obj, "glayer_continues_enable");
if (val) eina_value_get(val, &glayer_continues_enable);
else glayer_continues_enable = 1;
//Check the touched to ignore very first event.
//It does not have any meanging of this gesture.
if (glayer_continues_enable && !pd->touched)
{
pd->touched = EINA_TRUE;
return EFL_GESTURE_IGNORE;
}
switch (efl_gesture_touch_state_get(event))
{
case EFL_GESTURE_TOUCH_BEGIN:
case EFL_GESTURE_TOUCH_UPDATE:
{
if (!pd->t_st)
{
if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_BEGIN ||
glayer_continues_enable)
{
pd->t_st = pd->t_end = efl_gesture_touch_cur_timestamp_get(event);
pd->st_line = pd->end_line =
efl_gesture_touch_start_point_get(event);
efl_gesture_hotspot_set(gesture, pd->st_line);
return EFL_GESTURE_TRIGGER;
}
}
if ((efl_gesture_touch_cur_timestamp_get(event) - MOMENTUM_TIMEOUT) >
pd->t_end)
{
pd->st_line = efl_gesture_touch_cur_point_get(event);
pd->t_st = efl_gesture_touch_cur_timestamp_get(event);
pd->xdir = pd->ydir = 0;
}
else
{
int xdir, ydir;
Eina_Position2D cur_p = efl_gesture_touch_cur_point_get(event);
xdir = _direction_get(pd->end_line.x, cur_p.x);
ydir = _direction_get(pd->end_line.y, cur_p.y);
if (xdir && (xdir != pd->xdir))
{
pd->st_line.x = pd->end_line.x;
pd->t_st = pd->t_end;
pd->xdir = xdir;
}
if (ydir && (ydir != pd->ydir))
{
pd->st_line.y = pd->end_line.y;
pd->t_st = pd->t_end;
pd->ydir = ydir;
}
}
pd->end_line = efl_gesture_touch_cur_point_get(event);
pd->t_end = efl_gesture_touch_cur_timestamp_get(event);
efl_gesture_hotspot_set(gesture, pd->end_line);
_momentum_set(obj, md, pd->st_line, efl_gesture_touch_cur_point_get(event),
pd->t_st, efl_gesture_touch_cur_timestamp_get(event));
result = EFL_GESTURE_TRIGGER;
break;
}
case EFL_GESTURE_TOUCH_END:
{
if (!pd->t_st)
{
pd->touched = EINA_FALSE;
return EFL_GESTURE_CANCEL;
}
if ((efl_gesture_touch_cur_timestamp_get(event) - MOMENTUM_TIMEOUT) > pd->t_end)
{
pd->st_line = efl_gesture_touch_cur_point_get(event);
pd->t_st = efl_gesture_touch_cur_timestamp_get(event);
pd->xdir = pd->ydir = 0;
}
pd->end_line = efl_gesture_touch_cur_point_get(event);
pd->t_end = efl_gesture_touch_cur_timestamp_get(event);
efl_gesture_hotspot_set(gesture, pd->end_line);
if ((fabs(md->momentum.x) > EFL_GESTURE_MINIMUM_MOMENTUM) ||
(fabs(md->momentum.y) > EFL_GESTURE_MINIMUM_MOMENTUM))
result = EFL_GESTURE_FINISH;
else
result = EFL_GESTURE_CANCEL;
memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Momentum_Data));
break;
}
default:
break;
}
return result;
}
#include "efl_canvas_gesture_recognizer_momentum.eo.c"