2011-07-07 07:41:03 -07:00
|
|
|
#include <Elementary.h>
|
|
|
|
#include "elm_priv.h"
|
2012-05-28 09:56:56 -07:00
|
|
|
|
|
|
|
static const char GESTURE_LAYER_SMART_NAME[] = "elm_gesture_layer";
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
/* Some defaults */
|
2012-05-28 09:56:56 -07:00
|
|
|
#define ELM_MOUSE_DEVICE 0
|
2011-07-07 07:41:03 -07:00
|
|
|
/* ELM_GESTURE_NEGATIVE_ANGLE - magic number says we didn't compute this yet */
|
2012-05-28 09:56:56 -07:00
|
|
|
#define ELM_GESTURE_NEGATIVE_ANGLE (-1.0) /* Magic number */
|
|
|
|
#define ELM_GESTURE_MOMENTUM_DELAY 25
|
2011-07-07 07:41:03 -07:00
|
|
|
#define ELM_GESTURE_MOMENTUM_TIMEOUT 50
|
2012-05-28 09:56:56 -07:00
|
|
|
#define ELM_GESTURE_MULTI_TIMEOUT 50
|
2011-11-10 08:06:09 -08:00
|
|
|
#define ELM_GESTURE_MINIMUM_MOMENTUM 0.001
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
/* Some Trigo values */
|
2012-05-28 09:56:56 -07:00
|
|
|
#define RAD_90DEG M_PI_2
|
|
|
|
#define RAD_180DEG M_PI
|
|
|
|
#define RAD_270DEG (M_PI_2 * 3)
|
|
|
|
#define RAD_360DEG (M_PI * 2)
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2011-12-21 00:48:08 -08:00
|
|
|
#define RAD2DEG(x) ((x) * 57.295779513)
|
|
|
|
#define DEG2RAD(x) ((x) / 57.295779513)
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
static void *
|
2012-05-28 09:56:56 -07:00
|
|
|
_glayer_buf_dup(void *buf, size_t size)
|
2011-07-10 04:51:40 -07:00
|
|
|
{
|
|
|
|
void *p;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
p = malloc(size);
|
|
|
|
memcpy(p, buf, size);
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
return p;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
#define COPY_EVENT_INFO(EV) _glayer_buf_dup(EV, sizeof(*EV))
|
|
|
|
|
|
|
|
#define SET_TEST_BIT(P) \
|
|
|
|
do { \
|
|
|
|
P->test = P->fn[ELM_GESTURE_STATE_START].cb || \
|
|
|
|
P->fn[ELM_GESTURE_STATE_MOVE].cb || \
|
|
|
|
P->fn[ELM_GESTURE_STATE_END].cb || \
|
|
|
|
P->fn[ELM_GESTURE_STATE_ABORT].cb; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define IS_TESTED_GESTURE(gesture) \
|
|
|
|
((gesture) ? (gesture)->test : EINA_FALSE)
|
|
|
|
|
|
|
|
#define IS_TESTED(T) \
|
|
|
|
((sd->gesture[T]) ? sd->gesture[T]->test : EINA_FALSE)
|
|
|
|
|
|
|
|
#define ELM_GESTURE_LAYER_DATA_GET(o, sd) \
|
|
|
|
Elm_Gesture_Layer_Smart_Data * sd = evas_object_smart_data_get(o)
|
|
|
|
|
|
|
|
#define ELM_GESTURE_LAYER_DATA_GET_OR_RETURN(o, ptr) \
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(o, ptr); \
|
|
|
|
if (!ptr) \
|
|
|
|
{ \
|
|
|
|
CRITICAL("No widget data for object %p (%s)", \
|
|
|
|
o, evas_object_type_get(o)); \
|
|
|
|
return; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ELM_GESTURE_LAYER_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(o, ptr); \
|
|
|
|
if (!ptr) \
|
|
|
|
{ \
|
|
|
|
CRITICAL("No widget data for object %p (%s)", \
|
|
|
|
o, evas_object_type_get(o)); \
|
|
|
|
return val; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ELM_GESTURE_LAYER_CHECK(obj) \
|
|
|
|
if (!obj || !elm_widget_type_check((obj), \
|
|
|
|
GESTURE_LAYER_SMART_NAME, __func__)) \
|
|
|
|
return
|
|
|
|
|
|
|
|
EVAS_SMART_SUBCLASS_NEW
|
|
|
|
(GESTURE_LAYER_SMART_NAME, _elm_gesture_layer, Elm_Widget_Smart_Class,
|
|
|
|
Elm_Widget_Smart_Class, elm_widget_smart_class_get, NULL);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-17 08:31:34 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* @struct _Pointer_Event
|
|
|
|
* Struct holds pointer-event info
|
|
|
|
* This is a generic pointer event structure
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
struct _Pointer_Event
|
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
Evas_Coord x, y;
|
|
|
|
unsigned int timestamp;
|
|
|
|
int device;
|
2012-05-17 08:31:34 -07:00
|
|
|
Evas_Callback_Type event_type;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* @typedef Pointer_Event
|
|
|
|
* Type for generic pointer event structure
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
typedef struct _Pointer_Event Pointer_Event;
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* @struct _Func_Data
|
|
|
|
* Struct holds callback information.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
struct _Func_Data
|
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
void *user_data; /**< Holds user data to CB (like sd) */
|
2011-07-07 07:41:03 -07:00
|
|
|
Elm_Gesture_Event_Cb cb;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* @typedef Func_Data
|
|
|
|
* type for callback information
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
typedef struct _Func_Data Func_Data;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* @struct _Gesture_Info
|
|
|
|
* Struct holds gesture info
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
struct _Gesture_Info
|
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
Evas_Object *obj;
|
|
|
|
void *data; /**< Holds gesture intemidiate processing data */
|
|
|
|
Func_Data fn[ELM_GESTURE_STATE_ABORT + 1]; /**< Callback info for states */
|
|
|
|
Elm_Gesture_Type g_type; /**< gesture type */
|
|
|
|
Elm_Gesture_State state; /**< gesture state */
|
|
|
|
void *info; /**< Data for the state callback */
|
|
|
|
Eina_Bool test; /**< if true this gesture should be tested on input */
|
2011-07-07 07:41:03 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* @typedef Gesture_Info
|
|
|
|
* Type for _Gesture_Info
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
typedef struct _Gesture_Info Gesture_Info;
|
|
|
|
|
2012-05-17 08:31:34 -07:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
void (*test)(Evas_Object *obj, Pointer_Event *pe,
|
2012-05-28 09:56:56 -07:00
|
|
|
void *event_info, Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type);
|
2012-05-17 08:31:34 -07:00
|
|
|
void (*reset)(Gesture_Info *gesture);
|
2012-05-20 07:56:26 -07:00
|
|
|
void (*cont_reset)(Gesture_Info *gesture); /* Can be NULL. */
|
2012-05-17 08:31:34 -07:00
|
|
|
} Tests_Array_Funcs;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* functions referred by _glayer_tests_array */
|
|
|
|
static void _tap_gesture_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type);
|
2012-05-17 08:31:34 -07:00
|
|
|
static void _tap_gestures_test_reset(Gesture_Info *gesture);
|
2012-05-28 09:56:56 -07:00
|
|
|
static void _n_long_tap_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type);
|
2012-05-17 08:31:34 -07:00
|
|
|
static void _n_long_tap_test_reset(Gesture_Info *gesture);
|
2012-05-28 09:56:56 -07:00
|
|
|
static void _momentum_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type);
|
2012-05-17 08:31:34 -07:00
|
|
|
static void _momentum_test_reset(Gesture_Info *gesture);
|
2012-05-28 09:56:56 -07:00
|
|
|
static void _n_line_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type);
|
2012-05-17 08:31:34 -07:00
|
|
|
static void _line_test_reset(Gesture_Info *gesture);
|
2012-05-28 09:56:56 -07:00
|
|
|
static void _zoom_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type);
|
2012-05-17 08:31:34 -07:00
|
|
|
static void _zoom_test_reset(Gesture_Info *gesture);
|
2012-05-28 09:56:56 -07:00
|
|
|
static void _rotate_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type);
|
2012-05-17 08:31:34 -07:00
|
|
|
static void _rotate_test_reset(Gesture_Info *gesture);
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
static void _event_process(void *data,
|
|
|
|
Evas_Object *obj,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type);
|
|
|
|
|
2012-05-17 08:31:34 -07:00
|
|
|
/* Should be the same order as _Elm_Gesture_Type */
|
2012-05-28 09:56:56 -07:00
|
|
|
static Tests_Array_Funcs _glayer_tests_array[] = {
|
|
|
|
{ NULL, NULL, NULL }, /** Because someone made an awful mistake. */
|
|
|
|
{ _tap_gesture_test, _tap_gestures_test_reset, NULL },
|
|
|
|
/* ELM_GESTURE_N_TAPS */
|
|
|
|
{ _n_long_tap_test, _n_long_tap_test_reset, NULL },
|
|
|
|
/* ELM_GESTURE_N_LONG_TAPS */
|
|
|
|
{ _tap_gesture_test, _tap_gestures_test_reset, NULL },
|
|
|
|
/* ELM_GESTURE_N_DOUBLE_TAPS */
|
|
|
|
{ _tap_gesture_test, _tap_gestures_test_reset, NULL },
|
|
|
|
/* ELM_GESTURE_N_TRIPLE_TAPS */
|
|
|
|
{ _momentum_test, _momentum_test_reset, _momentum_test_reset },
|
|
|
|
/* ELM_GESTURE_MOMENTUM */
|
|
|
|
{ _n_line_test, _line_test_reset, _line_test_reset },
|
|
|
|
/* ELM_GESTURE_N_LINES */
|
|
|
|
{ _n_line_test, _line_test_reset, _line_test_reset },
|
|
|
|
/* ELM_GESTURE_N_FLICKS */
|
|
|
|
{ _zoom_test, _zoom_test_reset, _zoom_test_reset },
|
|
|
|
/* ELM_GESTURE_ZOOM */
|
|
|
|
{ _rotate_test, _rotate_test_reset, _rotate_test_reset },
|
|
|
|
/* ELM_GESTURE_ROTATE */
|
|
|
|
{ NULL, NULL, NULL }
|
2012-05-17 08:31:34 -07:00
|
|
|
};
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* @struct _Event_History
|
|
|
|
* Struct holds event history.
|
|
|
|
* These events are repeated if no gesture found.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
struct _Event_History
|
|
|
|
{
|
|
|
|
EINA_INLIST;
|
2012-05-28 09:56:56 -07:00
|
|
|
void *event;
|
2011-07-07 07:41:03 -07:00
|
|
|
Evas_Callback_Type event_type;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* @typedef Event_History
|
|
|
|
* Type for _Event_History
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
typedef struct _Event_History Event_History;
|
|
|
|
|
|
|
|
/* All *Type structs hold result for the user in 'info' field
|
|
|
|
* The rest is gesture processing intermediate data.
|
|
|
|
* NOTE: info field must be FIRST in the struct.
|
2012-05-28 09:56:56 -07:00
|
|
|
* This is used when reporting ABORT in _event_history_clear() */
|
2011-07-07 07:41:03 -07:00
|
|
|
struct _Taps_Type
|
|
|
|
{
|
|
|
|
Elm_Gesture_Taps_Info info;
|
2012-05-28 09:56:56 -07:00
|
|
|
unsigned int sum_x;
|
|
|
|
unsigned int sum_y;
|
|
|
|
unsigned int n_taps_needed;
|
|
|
|
unsigned int n_taps;
|
|
|
|
Eina_List *l;
|
2011-07-07 07:41:03 -07:00
|
|
|
};
|
|
|
|
typedef struct _Taps_Type Taps_Type;
|
|
|
|
|
2011-08-01 06:09:05 -07:00
|
|
|
struct _Long_Tap_Type
|
|
|
|
{
|
|
|
|
Elm_Gesture_Taps_Info info;
|
2012-05-28 09:56:56 -07:00
|
|
|
Evas_Coord center_x;
|
|
|
|
Evas_Coord center_y;
|
|
|
|
Ecore_Timer *timeout; /* When this expires, long tap STARTed */
|
|
|
|
Eina_List *touched;
|
2011-08-01 06:09:05 -07:00
|
|
|
};
|
|
|
|
typedef struct _Long_Tap_Type Long_Tap_Type;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
struct _Momentum_Type /* Fields used by _line_test() */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
Elm_Gesture_Momentum_Info info;
|
2012-05-28 09:56:56 -07:00
|
|
|
Evas_Coord_Point line_st;
|
|
|
|
Evas_Coord_Point line_end;
|
|
|
|
unsigned int t_st_x; /* Time start on X */
|
|
|
|
unsigned int t_st_y; /* Time start on Y */
|
|
|
|
unsigned int t_end; /* Time end */
|
|
|
|
unsigned int t_up; /* Recent up event time */
|
|
|
|
int xdir, ydir;
|
2011-07-07 07:41:03 -07:00
|
|
|
};
|
|
|
|
typedef struct _Momentum_Type Momentum_Type;
|
|
|
|
|
|
|
|
struct _Line_Data
|
|
|
|
{
|
|
|
|
Evas_Coord_Point line_st;
|
|
|
|
Evas_Coord_Point line_end;
|
2012-05-28 09:56:56 -07:00
|
|
|
Evas_Coord line_length;
|
|
|
|
unsigned int t_st; /* Time start */
|
|
|
|
unsigned int t_end; /* Time end */
|
|
|
|
int device;
|
|
|
|
double line_angle; /* Current angle of line */
|
2011-07-07 07:41:03 -07:00
|
|
|
};
|
|
|
|
typedef struct _Line_Data Line_Data;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
struct _Line_Type /* Fields used by _line_test() */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
Elm_Gesture_Line_Info info;
|
2012-05-28 09:56:56 -07:00
|
|
|
Eina_List *list; /* List of Line_Data */
|
2011-07-07 07:41:03 -07:00
|
|
|
};
|
|
|
|
typedef struct _Line_Type Line_Type;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
struct _Zoom_Type /* Fields used by _zoom_test() */
|
|
|
|
{
|
|
|
|
Elm_Gesture_Zoom_Info info;
|
|
|
|
Pointer_Event zoom_st;
|
|
|
|
Pointer_Event zoom_mv;
|
|
|
|
Pointer_Event zoom_st1;
|
|
|
|
Pointer_Event zoom_mv1;
|
2011-07-07 07:41:03 -07:00
|
|
|
Evas_Event_Mouse_Wheel *zoom_wheel;
|
2012-05-28 09:56:56 -07:00
|
|
|
Evas_Coord zoom_base; /* Holds gap between fingers on
|
|
|
|
* zoom-start */
|
|
|
|
Evas_Coord zoom_distance_tolerance;
|
|
|
|
unsigned int m_st_tm; /* momentum start time */
|
|
|
|
unsigned int m_prev_tm; /* momentum prev time */
|
|
|
|
int dir; /* Direction: 1=zoom-in, (-1)=zoom-out */
|
|
|
|
double m_base; /* zoom value when momentum starts */
|
|
|
|
double next_step;
|
2011-07-07 07:41:03 -07:00
|
|
|
};
|
|
|
|
typedef struct _Zoom_Type Zoom_Type;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
struct _Rotate_Type /* Fields used by _rotation_test() */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
Elm_Gesture_Rotate_Info info;
|
2012-05-28 09:56:56 -07:00
|
|
|
Pointer_Event rotate_st;
|
|
|
|
Pointer_Event rotate_mv;
|
|
|
|
Pointer_Event rotate_st1;
|
|
|
|
Pointer_Event rotate_mv1;
|
|
|
|
unsigned int prev_momentum_tm; /* timestamp of prev_momentum */
|
|
|
|
double prev_momentum; /* Snapshot of momentum 0.01
|
|
|
|
* sec ago */
|
|
|
|
double accum_momentum;
|
|
|
|
double rotate_angular_tolerance;
|
|
|
|
double next_step;
|
2011-07-07 07:41:03 -07:00
|
|
|
};
|
2012-05-28 09:56:56 -07:00
|
|
|
typedef struct _Rotate_Type Rotate_Type;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
typedef struct _Elm_Gesture_Layer_Smart_Data Elm_Gesture_Layer_Smart_Data;
|
|
|
|
struct _Elm_Gesture_Layer_Smart_Data
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
Elm_Widget_Smart_Data base; /* base widget smart data as
|
|
|
|
* first member obligatory, as
|
|
|
|
* we're inheriting from it */
|
|
|
|
|
|
|
|
Evas_Object *target; /* Target Widget */
|
|
|
|
Event_History *event_history_list;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
int line_min_length;
|
|
|
|
Evas_Coord zoom_distance_tolerance;
|
|
|
|
Evas_Coord line_distance_tolerance;
|
|
|
|
double line_angular_tolerance;
|
|
|
|
double zoom_wheel_factor; /* mouse wheel zoom steps */
|
|
|
|
double zoom_finger_factor; /* used for zoom factor */
|
|
|
|
double rotate_angular_tolerance;
|
|
|
|
unsigned int flick_time_limit_ms;
|
|
|
|
double long_tap_start_timeout;
|
|
|
|
Eina_Bool glayer_continues_enable;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
double zoom_step;
|
|
|
|
double rotate_step;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
Gesture_Info *gesture[ELM_GESTURE_LAST];
|
|
|
|
Eina_List *pending; /* List of devices need to refeed
|
|
|
|
* *UP event */
|
|
|
|
Eina_List *touched; /* Information of touched devices */
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-17 08:31:23 -07:00
|
|
|
/* Taps Gestures */
|
2012-05-28 09:56:56 -07:00
|
|
|
Ecore_Timer *gest_taps_timeout; /* When this expires, dbl
|
|
|
|
* click/taps ABORTed */
|
2012-05-17 08:31:23 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
Eina_Bool repeat_events : 1;
|
2011-07-07 07:41:03 -07:00
|
|
|
};
|
|
|
|
|
2011-07-10 04:51:44 -07:00
|
|
|
/* START - Functions to manage touched-device list */
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* This function is used to find if device is touched
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static int
|
2012-05-28 09:56:56 -07:00
|
|
|
_device_compare(const void *data1,
|
|
|
|
const void *data2)
|
|
|
|
{
|
|
|
|
/* Compare the two device numbers */
|
|
|
|
return ((Pointer_Event *)data1)->device - ((Pointer_Event *)data2)->device;
|
2011-07-10 04:51:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
2011-10-10 08:47:34 -07:00
|
|
|
* Remove Pointer Event from touched device list
|
2011-07-10 04:51:44 -07:00
|
|
|
* @param list Pointer to touched device list.
|
|
|
|
* @param Pointer_Event Pointer to PE.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Eina_List *
|
2012-05-28 09:56:56 -07:00
|
|
|
_touched_device_remove(Eina_List *list,
|
|
|
|
Pointer_Event *pe)
|
2011-07-10 04:51:44 -07:00
|
|
|
{
|
2011-11-29 01:20:31 -08:00
|
|
|
Eina_List *lst = NULL;
|
2012-05-28 09:56:56 -07:00
|
|
|
Pointer_Event *p = eina_list_search_unsorted(list, _device_compare, pe);
|
2011-10-10 08:47:34 -07:00
|
|
|
if (p)
|
|
|
|
{
|
2011-11-29 01:20:31 -08:00
|
|
|
lst = eina_list_remove(list, p);
|
2011-10-10 08:47:34 -07:00
|
|
|
free(p);
|
2011-11-29 01:20:31 -08:00
|
|
|
return lst;
|
2011-10-10 08:47:34 -07:00
|
|
|
}
|
2011-07-10 04:51:44 -07:00
|
|
|
|
2011-10-10 08:47:34 -07:00
|
|
|
return list;
|
2011-07-10 04:51:44 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
2011-10-10 08:47:34 -07:00
|
|
|
* Recoed Pointer Event in touched device list
|
|
|
|
* Note: This fuction allocates memory for PE event
|
2012-05-28 09:56:56 -07:00
|
|
|
* This memory is released in _touched_device_remove()
|
2011-07-10 04:51:44 -07:00
|
|
|
* @param list Pointer to touched device list.
|
|
|
|
* @param Pointer_Event Pointer to PE.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Eina_List *
|
2012-05-28 09:56:56 -07:00
|
|
|
_touched_device_add(Eina_List *list,
|
|
|
|
Pointer_Event *pe)
|
2011-07-10 04:51:44 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
Pointer_Event *p = eina_list_search_unsorted(list, _device_compare, pe);
|
|
|
|
|
|
|
|
if (p) /* We like to track device touch-position, overwrite info */
|
|
|
|
{
|
2011-10-10 08:47:34 -07:00
|
|
|
memcpy(p, pe, sizeof(Pointer_Event));
|
|
|
|
return list;
|
2011-07-10 04:51:44 -07:00
|
|
|
}
|
|
|
|
|
2011-11-07 06:31:25 -08:00
|
|
|
if ((pe->event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
|
2012-05-28 09:56:56 -07:00
|
|
|
(pe->event_type == EVAS_CALLBACK_MULTI_DOWN)) /* Add touched
|
|
|
|
* device on DOWN
|
|
|
|
* event only */
|
|
|
|
{
|
2011-11-07 06:31:25 -08:00
|
|
|
p = malloc(sizeof(Pointer_Event));
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Freed in _touched_device_remove() */
|
2011-11-07 06:31:25 -08:00
|
|
|
memcpy(p, pe, sizeof(Pointer_Event));
|
|
|
|
return eina_list_append(list, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
2011-07-10 04:51:44 -07:00
|
|
|
}
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2011-07-10 04:51:44 -07:00
|
|
|
/* END - Functions to manage touched-device list */
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* Get event flag
|
|
|
|
* @param event_info pointer to event.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Evas_Event_Flags
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_flag_get(void *event_info,
|
|
|
|
Evas_Callback_Type event_type)
|
2011-07-10 04:51:40 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
switch (event_type)
|
2011-07-10 04:51:40 -07:00
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_MOUSE_IN:
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((Evas_Event_Mouse_In *)event_info)->event_flags;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_OUT:
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((Evas_Event_Mouse_Out *)event_info)->event_flags;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((Evas_Event_Mouse_Down *)event_info)->event_flags;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((Evas_Event_Mouse_Move *)event_info)->event_flags;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((Evas_Event_Mouse_Up *)event_info)->event_flags;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_WHEEL:
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((Evas_Event_Mouse_Wheel *)event_info)->event_flags;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((Evas_Event_Multi_Down *)event_info)->event_flags;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_MOVE:
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((Evas_Event_Multi_Move *)event_info)->event_flags;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((Evas_Event_Multi_Up *)event_info)->event_flags;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
case EVAS_CALLBACK_KEY_DOWN:
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((Evas_Event_Key_Down *)event_info)->event_flags;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
case EVAS_CALLBACK_KEY_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((Evas_Event_Key_Up *)event_info)->event_flags;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
default:
|
2012-05-28 09:56:56 -07:00
|
|
|
return EVAS_EVENT_FLAG_NONE;
|
2011-07-10 04:51:40 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* Sets event flag to value returned from user callback
|
2012-05-28 09:56:56 -07:00
|
|
|
* @param sd Widget Data
|
2011-07-07 07:41:03 -07:00
|
|
|
* @param event_info pointer to event.
|
|
|
|
* @param event_type what type was ev (mouse down, etc...)
|
|
|
|
* @param ev_flags event flags
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_consume(Elm_Gesture_Layer_Smart_Data *sd,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Evas_Event_Flags ev_flags)
|
|
|
|
{
|
|
|
|
/* Mark EVAS_EVENT_FLAG_ON_HOLD on events that are used by gesture layer */
|
2011-07-10 04:51:44 -07:00
|
|
|
/* ev_flags != EVAS_EVENT_FLAG_NONE means target used event and g-layer */
|
2012-05-28 09:56:56 -07:00
|
|
|
/* should not refeed this event. */
|
2012-03-29 04:09:45 -07:00
|
|
|
if (!event_info)
|
2011-09-08 03:10:27 -07:00
|
|
|
return; /* This happens when restarting gestures */
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!sd->repeat_events) ev_flags |= EVAS_EVENT_FLAG_ON_HOLD;
|
2012-05-10 04:16:13 -07:00
|
|
|
|
|
|
|
if (ev_flags)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
switch (event_type)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
2012-05-28 09:56:56 -07:00
|
|
|
((Evas_Event_Mouse_Down *)event_info)->event_flags |= ev_flags;
|
|
|
|
break;
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
2012-05-28 09:56:56 -07:00
|
|
|
((Evas_Event_Mouse_Move *)event_info)->event_flags |= ev_flags;
|
|
|
|
break;
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
((Evas_Event_Mouse_Up *)event_info)->event_flags |= ev_flags;
|
|
|
|
break;
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_WHEEL:
|
2012-05-28 09:56:56 -07:00
|
|
|
((Evas_Event_Mouse_Wheel *)event_info)->event_flags |= ev_flags;
|
|
|
|
break;
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
2012-05-28 09:56:56 -07:00
|
|
|
((Evas_Event_Multi_Down *)event_info)->event_flags |= ev_flags;
|
|
|
|
break;
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_MOVE:
|
2012-05-28 09:56:56 -07:00
|
|
|
((Evas_Event_Multi_Move *)event_info)->event_flags |= ev_flags;
|
|
|
|
break;
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
((Evas_Event_Multi_Up *)event_info)->event_flags |= ev_flags;
|
|
|
|
break;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
case EVAS_CALLBACK_KEY_DOWN:
|
2012-05-28 09:56:56 -07:00
|
|
|
((Evas_Event_Key_Down *)event_info)->event_flags |= ev_flags;
|
|
|
|
break;
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
case EVAS_CALLBACK_KEY_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
((Evas_Event_Key_Up *)event_info)->event_flags |= ev_flags;
|
|
|
|
break;
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
default:
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* Report current state of a gesture by calling user callback.
|
|
|
|
* @param gesture what gesture state we report.
|
|
|
|
* @param info inforamtion for user callback
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Evas_Event_Flags
|
2012-05-28 09:56:56 -07:00
|
|
|
_state_report(Gesture_Info *gesture,
|
|
|
|
void *info)
|
|
|
|
{
|
|
|
|
/* We report current state (START, MOVE, END, ABORT), once */
|
2011-07-07 07:41:03 -07:00
|
|
|
if ((gesture->state != ELM_GESTURE_STATE_UNDEFINED) &&
|
2012-05-28 09:56:56 -07:00
|
|
|
(gesture->fn[gesture->state].cb)) /* Fill state-info struct and
|
|
|
|
* send ptr to user
|
|
|
|
* callback */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
return gesture->fn[gesture->state].cb(
|
2012-05-28 09:56:56 -07:00
|
|
|
gesture->fn[gesture->state].user_data, info);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return EVAS_EVENT_FLAG_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* Update state for a given gesture.
|
|
|
|
* We may update gesture state to:
|
2012-05-28 09:56:56 -07:00
|
|
|
* - @c UNDEFINED - current input did not start gesure yet.
|
|
|
|
* - @c START - gesture started according to input.
|
|
|
|
* - @c MOVE - gusture in progress.
|
|
|
|
* - @c END - gesture completed according to input.
|
|
|
|
* - @c ABORT - input does not matches gesure.
|
2011-07-07 07:41:03 -07:00
|
|
|
* note that we may move from UNDEFINED to ABORT
|
|
|
|
* because we may detect that gesture will not START
|
|
|
|
* with a given input.
|
|
|
|
*
|
|
|
|
* @param g given gesture to change state.
|
|
|
|
* @param s gesure new state.
|
|
|
|
* @param info buffer to be sent to user callback on report_state.
|
|
|
|
* @param force makes report_state to report the new-state even
|
|
|
|
* if its same as current state. Works for MOVE - gesture in progress.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Evas_Event_Flags
|
2012-05-28 09:56:56 -07:00
|
|
|
_state_set(Gesture_Info *g,
|
|
|
|
Elm_Gesture_State s,
|
|
|
|
void *info,
|
|
|
|
Eina_Bool force)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
Elm_Gesture_State old_state;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
if ((g->state == s) && (!force))
|
|
|
|
return EVAS_EVENT_FLAG_NONE;
|
|
|
|
|
|
|
|
old_state = g->state;
|
|
|
|
|
|
|
|
g->state = s;
|
|
|
|
g->info = info; /* Information for user callback */
|
|
|
|
if ((g->state == ELM_GESTURE_STATE_ABORT) ||
|
2012-05-28 09:56:56 -07:00
|
|
|
(g->state == ELM_GESTURE_STATE_END))
|
2011-07-07 07:41:03 -07:00
|
|
|
g->test = EINA_FALSE;
|
|
|
|
|
|
|
|
if ((g->state != ELM_GESTURE_STATE_UNDEFINED) &&
|
2012-05-28 09:56:56 -07:00
|
|
|
(!((old_state == ELM_GESTURE_STATE_UNDEFINED) &&
|
|
|
|
(s == ELM_GESTURE_STATE_ABORT))))
|
|
|
|
return _state_report(g, g->info);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
return EVAS_EVENT_FLAG_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This resets all gesture states and sets test-bit.
|
|
|
|
* this is used for restarting gestures to listen to input.
|
|
|
|
* happens after we complete a gesture or no gesture was detected.
|
2012-05-28 09:56:56 -07:00
|
|
|
* @param sd Widget data of the gesture-layer object.
|
2011-07-07 07:41:03 -07:00
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_states_reset(Elm_Gesture_Layer_Smart_Data *sd)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
Gesture_Info *p;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++)
|
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
p = sd->gesture[i];
|
2011-07-07 07:41:03 -07:00
|
|
|
if (p)
|
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
_state_set(p, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
|
2011-07-07 07:41:03 -07:00
|
|
|
SET_TEST_BIT(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
2012-05-28 09:56:56 -07:00
|
|
|
* This function is used to save input events in an abstract struct
|
|
|
|
* to be used later by getsure-testing functions.
|
2011-07-07 07:41:03 -07:00
|
|
|
*
|
2012-05-28 09:56:56 -07:00
|
|
|
* @param data The gesture-layer object.
|
|
|
|
* @param event_info Pointer to recent input event.
|
|
|
|
* @param event_type Recent input event type.
|
|
|
|
* @param pe The abstract data-struct (output).
|
2011-07-07 07:41:03 -07:00
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
2011-09-08 03:10:27 -07:00
|
|
|
static Eina_Bool
|
2012-05-28 09:56:56 -07:00
|
|
|
_pointer_event_make(void *data __UNUSED__,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Pointer_Event *pe)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
memset(pe, '\0', sizeof(*pe));
|
|
|
|
switch (event_type)
|
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
|
|
|
pe->x = ((Evas_Event_Mouse_Down *)event_info)->canvas.x;
|
|
|
|
pe->y = ((Evas_Event_Mouse_Down *)event_info)->canvas.y;
|
|
|
|
pe->timestamp = ((Evas_Event_Mouse_Down *)event_info)->timestamp;
|
|
|
|
pe->device = ELM_MOUSE_DEVICE;
|
|
|
|
break;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
|
|
|
pe->x = ((Evas_Event_Mouse_Up *)event_info)->canvas.x;
|
|
|
|
pe->y = ((Evas_Event_Mouse_Up *)event_info)->canvas.y;
|
|
|
|
pe->timestamp = ((Evas_Event_Mouse_Up *)event_info)->timestamp;
|
|
|
|
pe->device = ELM_MOUSE_DEVICE;
|
|
|
|
break;
|
2011-09-08 03:10:27 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
|
|
|
pe->x = ((Evas_Event_Mouse_Move *)event_info)->cur.canvas.x;
|
|
|
|
pe->y = ((Evas_Event_Mouse_Move *)event_info)->cur.canvas.y;
|
|
|
|
pe->timestamp = ((Evas_Event_Mouse_Move *)event_info)->timestamp;
|
|
|
|
pe->device = ELM_MOUSE_DEVICE;
|
|
|
|
break;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
|
|
|
pe->x = ((Evas_Event_Multi_Down *)event_info)->canvas.x;
|
|
|
|
pe->y = ((Evas_Event_Multi_Down *)event_info)->canvas.y;
|
|
|
|
pe->timestamp = ((Evas_Event_Multi_Down *)event_info)->timestamp;
|
|
|
|
pe->device = ((Evas_Event_Multi_Down *)event_info)->device;
|
|
|
|
break;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
|
|
|
pe->x = ((Evas_Event_Multi_Up *)event_info)->canvas.x;
|
|
|
|
pe->y = ((Evas_Event_Multi_Up *)event_info)->canvas.y;
|
|
|
|
pe->timestamp = ((Evas_Event_Multi_Up *)event_info)->timestamp;
|
|
|
|
pe->device = ((Evas_Event_Multi_Up *)event_info)->device;
|
|
|
|
break;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_MOVE:
|
|
|
|
pe->x = ((Evas_Event_Multi_Move *)event_info)->cur.canvas.x;
|
|
|
|
pe->y = ((Evas_Event_Multi_Move *)event_info)->cur.canvas.y;
|
|
|
|
pe->timestamp = ((Evas_Event_Multi_Move *)event_info)->timestamp;
|
|
|
|
pe->device = ((Evas_Event_Multi_Move *)event_info)->device;
|
|
|
|
break;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
default:
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
pe->event_type = event_type;
|
2011-07-07 07:41:03 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function copies input events.
|
|
|
|
* We copy event info before adding it to history.
|
|
|
|
* The memory is freed when we clear history.
|
|
|
|
*
|
|
|
|
* @param event the event to copy
|
|
|
|
* @param event_type event type to copy
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void *
|
|
|
|
_event_info_copy(void *event,
|
|
|
|
Evas_Callback_Type event_type)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
switch (event_type)
|
2012-05-16 01:44:17 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
|
|
|
return COPY_EVENT_INFO((Evas_Event_Mouse_Down *)event);
|
|
|
|
break;
|
2012-05-16 01:44:17 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
|
|
|
return COPY_EVENT_INFO((Evas_Event_Mouse_Move *)event);
|
|
|
|
break;
|
2011-07-10 07:10:57 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
|
|
|
return COPY_EVENT_INFO((Evas_Event_Mouse_Up *)event);
|
|
|
|
break;
|
2011-07-10 07:10:57 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_WHEEL:
|
|
|
|
return COPY_EVENT_INFO((Evas_Event_Mouse_Wheel *)event);
|
|
|
|
break;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
|
|
|
return COPY_EVENT_INFO((Evas_Event_Multi_Down *)event);
|
|
|
|
break;
|
2011-08-01 06:09:05 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_MOVE:
|
|
|
|
return COPY_EVENT_INFO((Evas_Event_Multi_Move *)event);
|
|
|
|
break;
|
2011-08-01 06:09:05 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
|
|
|
return COPY_EVENT_INFO((Evas_Event_Multi_Up *)event);
|
|
|
|
break;
|
2012-05-17 08:31:29 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_KEY_DOWN:
|
|
|
|
return COPY_EVENT_INFO((Evas_Event_Key_Down *)event);
|
|
|
|
break;
|
2012-05-17 08:31:29 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_KEY_UP:
|
|
|
|
return COPY_EVENT_INFO((Evas_Event_Key_Up *)event);
|
|
|
|
break;
|
2011-08-01 06:09:05 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
default:
|
|
|
|
return NULL;
|
2012-02-24 04:21:22 -08:00
|
|
|
}
|
2011-08-01 06:09:05 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_event_history_add(Evas_Object *obj,
|
|
|
|
void *event,
|
|
|
|
Evas_Callback_Type event_type)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
Event_History *ev;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
ev = malloc(sizeof(Event_History));
|
|
|
|
ev->event = _event_info_copy(event, event_type); /* Freed on
|
|
|
|
* _event_history_clear */
|
|
|
|
ev->event_type = event_type;
|
|
|
|
sd->event_history_list = (Event_History *)eina_inlist_append(
|
|
|
|
EINA_INLIST_GET(sd->event_history_list), EINA_INLIST_GET(ev));
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/**
|
|
|
|
* For all _mouse_* / multi_* functions wethen send this event to
|
|
|
|
* _event_process function.
|
|
|
|
*
|
|
|
|
* @param data The gesture-layer object.
|
|
|
|
* @param event_info Pointer to recent input event.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
2011-07-07 07:41:03 -07:00
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_mouse_down_cb(void *data,
|
|
|
|
Evas *e __UNUSED__,
|
|
|
|
Evas_Object *obj __UNUSED__,
|
|
|
|
void *event_info)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
if (((Evas_Event_Mouse_Down *)event_info)->button != 1)
|
|
|
|
return; /* We only process left-click at the moment */
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_DOWN);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_mouse_move_cb(void *data,
|
|
|
|
Evas *e __UNUSED__,
|
|
|
|
Evas_Object *obj __UNUSED__,
|
|
|
|
void *event_info)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_MOVE);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_key_down_cb(void *data,
|
|
|
|
Evas *e __UNUSED__,
|
|
|
|
Evas_Object *obj __UNUSED__,
|
|
|
|
void *event_info)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_process(data, obj, event_info, EVAS_CALLBACK_KEY_DOWN);
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
static void
|
|
|
|
_key_up_cb(void *data,
|
|
|
|
Evas *e __UNUSED__,
|
|
|
|
Evas_Object *obj __UNUSED__,
|
|
|
|
void *event_info)
|
|
|
|
{
|
|
|
|
_event_process(data, obj, event_info, EVAS_CALLBACK_KEY_UP);
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
static void
|
|
|
|
_mouse_up_cb(void *data,
|
|
|
|
Evas *e __UNUSED__,
|
|
|
|
Evas_Object *obj __UNUSED__,
|
|
|
|
void *event_info)
|
|
|
|
{
|
|
|
|
if (((Evas_Event_Mouse_Up *)event_info)->button != 1)
|
|
|
|
return; /* We only process left-click at the moment */
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_UP);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_mouse_wheel_cb(void *data,
|
|
|
|
Evas *e __UNUSED__,
|
|
|
|
Evas_Object *obj __UNUSED__,
|
|
|
|
void *event_info)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_WHEEL);
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
static void
|
|
|
|
_multi_down_cb(void *data,
|
|
|
|
Evas *e __UNUSED__,
|
|
|
|
Evas_Object *obj __UNUSED__,
|
|
|
|
void *event_info)
|
|
|
|
{
|
2012-06-26 17:27:18 -07:00
|
|
|
/* Skip the mouse duplicates. */
|
|
|
|
if (((Evas_Event_Multi_Down *) event_info)->device == 0) return;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_DOWN);
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
static void
|
|
|
|
_multi_move_cb(void *data,
|
|
|
|
Evas *e __UNUSED__,
|
|
|
|
Evas_Object *obj __UNUSED__,
|
|
|
|
void *event_info)
|
|
|
|
{
|
2012-06-26 17:27:18 -07:00
|
|
|
/* Skip the mouse duplicates. */
|
|
|
|
if (((Evas_Event_Multi_Move *) event_info)->device == 0) return;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_MOVE);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
static void
|
|
|
|
_multi_up_cb(void *data,
|
|
|
|
Evas *e __UNUSED__,
|
|
|
|
Evas_Object *obj __UNUSED__,
|
|
|
|
void *event_info)
|
|
|
|
{
|
2012-06-26 17:27:18 -07:00
|
|
|
/* Skip the mouse duplicates. */
|
|
|
|
if (((Evas_Event_Multi_Up *) event_info)->device == 0) return;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_UP);
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* We register callbacks when gesture layer is attached to an object
|
|
|
|
* or when its enabled after disable.
|
|
|
|
*
|
|
|
|
* @param obj The gesture-layer object.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_callbacks_register(Evas_Object *obj)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!sd->target) return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->target, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, obj);
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->target, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb, obj);
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->target, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, obj);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->target, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, obj);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->target, EVAS_CALLBACK_MULTI_DOWN, _multi_down_cb, obj);
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->target, EVAS_CALLBACK_MULTI_MOVE, _multi_move_cb, obj);
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->target, EVAS_CALLBACK_MULTI_UP, _multi_up_cb, obj);
|
|
|
|
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->target, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, obj);
|
|
|
|
evas_object_event_callback_add
|
|
|
|
(sd->target, EVAS_CALLBACK_KEY_UP, _key_up_cb, obj);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* We unregister callbacks when gesture layer is disabled.
|
|
|
|
*
|
|
|
|
* @param obj The gesture-layer object.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_callbacks_unregister(Evas_Object *obj)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!sd->target) return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
evas_object_event_callback_del
|
|
|
|
(sd->target, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb);
|
|
|
|
evas_object_event_callback_del
|
|
|
|
(sd->target, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move_cb);
|
|
|
|
evas_object_event_callback_del
|
|
|
|
(sd->target, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
evas_object_event_callback_del
|
|
|
|
(sd->target, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
evas_object_event_callback_del
|
|
|
|
(sd->target, EVAS_CALLBACK_MULTI_DOWN, _multi_down_cb);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
evas_object_event_callback_del
|
|
|
|
(sd->target, EVAS_CALLBACK_MULTI_MOVE, _multi_move_cb);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
evas_object_event_callback_del
|
|
|
|
(sd->target, EVAS_CALLBACK_MULTI_UP, _multi_up_cb);
|
|
|
|
|
|
|
|
evas_object_event_callback_del
|
|
|
|
(sd->target, EVAS_CALLBACK_KEY_DOWN, _key_down_cb);
|
|
|
|
evas_object_event_callback_del
|
|
|
|
(sd->target, EVAS_CALLBACK_KEY_UP, _key_up_cb);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
* This function is used to find if device number
|
|
|
|
* is found in a list of devices.
|
|
|
|
* The list contains devices for refeeding *UP event
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static int
|
2012-05-28 09:56:56 -07:00
|
|
|
_device_in_pending_cmp(const void *data1,
|
|
|
|
const void *data2)
|
|
|
|
{
|
|
|
|
/* Compare the two device numbers */
|
|
|
|
return ((intptr_t)data1) - ((intptr_t)data2);
|
2011-07-10 04:51:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
2012-05-28 09:56:56 -07:00
|
|
|
* This functions returns pending-device node
|
2011-07-10 04:51:40 -07:00
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Eina_List *
|
2012-05-28 09:56:56 -07:00
|
|
|
_device_is_pending(Eina_List *list,
|
|
|
|
void *event,
|
|
|
|
Evas_Callback_Type event_type)
|
2011-07-10 04:51:40 -07:00
|
|
|
{
|
|
|
|
int device = ELM_MOUSE_DEVICE;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
switch (event_type)
|
2011-07-10 04:51:40 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
|
|
|
device = ((Evas_Event_Multi_Up *)event)->device;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return NULL;
|
2011-07-10 04:51:40 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return eina_list_search_unsorted_list
|
|
|
|
(list, _device_in_pending_cmp, (void *)(intptr_t)device);
|
2011-07-10 04:51:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
2012-05-28 09:56:56 -07:00
|
|
|
* This functions adds device to refeed-pending device list
|
2011-07-10 04:51:40 -07:00
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Eina_List *
|
2012-05-28 09:56:56 -07:00
|
|
|
_pending_device_add(Eina_List *list,
|
|
|
|
void *event,
|
|
|
|
Evas_Callback_Type event_type)
|
2011-07-10 04:51:40 -07:00
|
|
|
{
|
|
|
|
int device = ELM_MOUSE_DEVICE;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
|
|
|
switch (event_type)
|
2011-07-10 04:51:40 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
|
|
|
device = ((Evas_Event_Multi_Down *)event)->device;
|
|
|
|
break;
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
default:
|
2012-05-28 09:56:56 -07:00
|
|
|
return list;
|
2011-07-10 04:51:40 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!eina_list_search_unsorted_list
|
|
|
|
(list, _device_in_pending_cmp, (void *)(intptr_t)device))
|
|
|
|
{
|
|
|
|
return eina_list_append(list, (void *)(intptr_t)device);
|
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
2011-07-10 04:51:40 -07:00
|
|
|
}
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function reports ABORT to all none-detected gestures
|
|
|
|
* Then resets test bits for all desired gesures
|
|
|
|
* and clears input-events history.
|
|
|
|
* note: if no gesture was detected, events from history list
|
|
|
|
* are streamed to the widget because it's unused by layer.
|
|
|
|
* user may cancel refeed of events by setting repeat events.
|
|
|
|
*
|
|
|
|
* @param obj The gesture-layer object.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
2011-09-08 03:10:27 -07:00
|
|
|
static Eina_Bool
|
2011-07-07 07:41:03 -07:00
|
|
|
_event_history_clear(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
Gesture_Info *p;
|
|
|
|
Evas *e = evas_object_evas_get(obj);
|
|
|
|
Eina_Bool gesture_found = EINA_FALSE;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
|
|
|
|
2012-02-24 04:21:22 -08:00
|
|
|
for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
p = sd->gesture[i];
|
2011-07-07 07:41:03 -07:00
|
|
|
if (p)
|
|
|
|
{
|
|
|
|
if (p->state == ELM_GESTURE_STATE_END)
|
2012-05-20 07:56:32 -07:00
|
|
|
{
|
|
|
|
gesture_found = EINA_TRUE;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
else
|
|
|
|
{ /* Report ABORT to all gestures that still not finished */
|
2012-05-28 09:56:56 -07:00
|
|
|
_state_set(p, ELM_GESTURE_STATE_ABORT, sd->gesture[i]->info,
|
|
|
|
EINA_FALSE);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_states_reset(sd); /* we are ready to start testing for gestures again */
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2011-10-17 01:12:45 -07:00
|
|
|
/* Clear all gestures intermediate data */
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
|
|
|
/* FIXME: +1 because of the mistake in the enum. */
|
|
|
|
Gesture_Info **gitr = sd->gesture + 1;
|
|
|
|
Tests_Array_Funcs *fitr = _glayer_tests_array + 1;
|
|
|
|
for (; fitr->reset; fitr++, gitr++)
|
|
|
|
{
|
|
|
|
if (IS_TESTED_GESTURE(*gitr))
|
|
|
|
fitr->reset(*gitr);
|
|
|
|
}
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
/* Disable gesture layer so refeeded events won't be consumed by it */
|
2012-05-28 09:56:56 -07:00
|
|
|
_callbacks_unregister(obj);
|
|
|
|
while (sd->event_history_list)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
Event_History *t;
|
2012-05-28 09:56:56 -07:00
|
|
|
t = sd->event_history_list;
|
|
|
|
Eina_List *pending = _device_is_pending
|
|
|
|
(sd->pending, sd->event_history_list->event,
|
|
|
|
sd->event_history_list->event_type);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
/* Refeed events if no gesture matched input */
|
2012-05-28 09:56:56 -07:00
|
|
|
if (pending || ((!gesture_found) && (!sd->repeat_events)))
|
2011-07-10 04:51:40 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
evas_event_refeed_event(e, sd->event_history_list->event,
|
|
|
|
sd->event_history_list->event_type);
|
2011-07-10 04:51:40 -07:00
|
|
|
|
2011-07-10 04:51:44 -07:00
|
|
|
if (pending)
|
2011-07-10 04:51:40 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
sd->pending = eina_list_remove_list(sd->pending, pending);
|
2011-07-10 04:51:40 -07:00
|
|
|
}
|
|
|
|
else
|
2011-10-25 02:51:41 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
sd->pending = _pending_device_add
|
|
|
|
(sd->pending, sd->event_history_list->event,
|
|
|
|
sd->event_history_list->event_type);
|
2011-10-25 02:51:41 -07:00
|
|
|
}
|
2011-07-10 04:51:40 -07:00
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
free(sd->event_history_list->event);
|
|
|
|
sd->event_history_list = (Event_History *)eina_inlist_remove(
|
|
|
|
EINA_INLIST_GET(sd->event_history_list),
|
|
|
|
EINA_INLIST_GET(sd->event_history_list));
|
2011-07-07 07:41:03 -07:00
|
|
|
free(t);
|
|
|
|
}
|
2012-05-28 09:56:56 -07:00
|
|
|
_callbacks_register(obj);
|
2011-09-08 03:10:27 -07:00
|
|
|
return EINA_TRUE;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2011-07-10 04:51:40 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
2012-05-28 09:56:56 -07:00
|
|
|
* if gesture was NOT detected AND we only have gestures in ABORT state
|
|
|
|
* we clear history immediately to be ready for input.
|
2011-07-10 04:51:40 -07:00
|
|
|
*
|
2012-05-28 09:56:56 -07:00
|
|
|
* @param obj The gesture-layer object.
|
|
|
|
* @return TRUE on event history_clear
|
2011-07-10 04:51:40 -07:00
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
2012-05-28 09:56:56 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_clear_if_finished(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
Eina_Bool reset_s = EINA_TRUE, all_undefined = EINA_TRUE;
|
|
|
|
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
|
|
|
|
|
|
|
/* Clear history if all we have aborted gestures */
|
|
|
|
for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++)
|
|
|
|
{ /* If no gesture started and all we have aborted gestures, reset all */
|
|
|
|
Gesture_Info *p = sd->gesture[i];
|
|
|
|
|
|
|
|
if ((p) && (p->state != ELM_GESTURE_STATE_UNDEFINED))
|
|
|
|
{
|
|
|
|
if ((p->state == ELM_GESTURE_STATE_START) ||
|
|
|
|
(p->state == ELM_GESTURE_STATE_MOVE))
|
|
|
|
reset_s = EINA_FALSE;
|
|
|
|
|
|
|
|
all_undefined = EINA_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reset_s && (!all_undefined))
|
|
|
|
return _event_history_clear(obj);
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function restartes line, flick, zoom and rotate gestures
|
|
|
|
* when gesture-layer continues-gestures enabled.
|
|
|
|
* Example of continues-gesture:
|
|
|
|
* When doing a line, user stops moving finger but keeps fingers on touch.
|
|
|
|
* This will cause line-end, then as user continues moving his finger
|
|
|
|
* it re-starts line gesture.
|
|
|
|
* When continue mode is disabled, user has to lift finger from touch
|
|
|
|
* to end a gesture. Them touch-again to start a new one.
|
|
|
|
*
|
|
|
|
* @param data The gesture-layer object.
|
|
|
|
* @param sd gesture layer widget data.
|
|
|
|
* @param states_reset flag that marks gestures were reset in history clear.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
_continues_gestures_restart(void *data,
|
|
|
|
Eina_Bool states_reset)
|
2011-07-10 04:51:40 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_DATA_GET(data, sd);
|
|
|
|
|
|
|
|
/* Test all the gestures */
|
|
|
|
{
|
|
|
|
/* FIXME: +1 because of the mistake in the enum. */
|
|
|
|
Gesture_Info **gitr = sd->gesture + 1;
|
|
|
|
Tests_Array_Funcs *fitr = _glayer_tests_array + 1;
|
|
|
|
for (; fitr->test; fitr++, gitr++)
|
|
|
|
{
|
|
|
|
Gesture_Info *g = *gitr;
|
|
|
|
Eina_Bool tmp = (g) ?
|
|
|
|
((states_reset) || ((g->state != ELM_GESTURE_STATE_START)
|
|
|
|
&& (g->state != ELM_GESTURE_STATE_MOVE)))
|
|
|
|
: EINA_FALSE;
|
|
|
|
if (tmp && fitr->cont_reset)
|
|
|
|
{
|
|
|
|
fitr->cont_reset(g);
|
|
|
|
_state_set(g, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
|
|
|
|
SET_TEST_BIT(g);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function the core-function where input handling is done.
|
|
|
|
* Here we get user input and stream it to gesture testing.
|
|
|
|
* We notify user about any gestures with new state:
|
|
|
|
* Valid states are:
|
|
|
|
* START - gesture started.
|
|
|
|
* MOVE - gesture is ongoing.
|
|
|
|
* END - gesture was completed.
|
|
|
|
* ABORT - gesture was aborted after START, MOVE (will NOT be completed)
|
|
|
|
*
|
|
|
|
* We also check if a gesture was detected, then reset event history
|
|
|
|
* If no gestures were found we reset gesture test flag
|
|
|
|
* after streaming event-history to widget.
|
|
|
|
* (stream to the widget all events not consumed as a gesture)
|
|
|
|
*
|
|
|
|
* @param data The gesture-layer object.
|
|
|
|
* @param event_info Pointer to recent input event.
|
|
|
|
* @param event_type Recent input event type.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
_event_process(void *data,
|
|
|
|
Evas_Object *obj __UNUSED__,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type)
|
|
|
|
{
|
|
|
|
Pointer_Event _pe;
|
|
|
|
Pointer_Event *pe = NULL;
|
|
|
|
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(data, sd);
|
|
|
|
|
|
|
|
/* Start testing candidate gesture from here */
|
|
|
|
if (_pointer_event_make(data, event_info, event_type, &_pe))
|
|
|
|
pe = &_pe;
|
|
|
|
|
|
|
|
/* Test all the gestures */
|
|
|
|
{
|
|
|
|
/* FIXME: +1 because of the mistake in the enum. */
|
|
|
|
Gesture_Info **gitr = sd->gesture + 1;
|
|
|
|
Tests_Array_Funcs *fitr = _glayer_tests_array + 1;
|
|
|
|
for (; fitr->test; fitr++, gitr++)
|
|
|
|
{
|
|
|
|
if (IS_TESTED_GESTURE(*gitr))
|
|
|
|
fitr->test(data, pe, event_info, event_type, (*gitr)->g_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_event_flag_get(event_info, event_type) & EVAS_EVENT_FLAG_ON_HOLD)
|
|
|
|
_event_history_add(data, event_info, event_type);
|
|
|
|
|
|
|
|
/* we maintain list of touched devices */
|
|
|
|
/* We also use move to track current device x.y pos */
|
|
|
|
if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
|
|
|
|
(event_type == EVAS_CALLBACK_MULTI_DOWN) ||
|
|
|
|
(event_type == EVAS_CALLBACK_MOUSE_MOVE) ||
|
|
|
|
(event_type == EVAS_CALLBACK_MULTI_MOVE))
|
2011-07-10 04:51:40 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
sd->touched = _touched_device_add(sd->touched, pe);
|
2011-07-10 04:51:40 -07:00
|
|
|
}
|
2012-05-28 09:56:56 -07:00
|
|
|
else if ((event_type == EVAS_CALLBACK_MOUSE_UP) ||
|
|
|
|
(event_type == EVAS_CALLBACK_MULTI_UP))
|
|
|
|
{
|
|
|
|
sd->touched = _touched_device_remove(sd->touched, pe);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Report current states and clear history if needed */
|
|
|
|
Eina_Bool states_reset = _clear_if_finished(data);
|
|
|
|
if (sd->glayer_continues_enable)
|
|
|
|
_continues_gestures_restart(data, states_reset);
|
2011-07-10 04:51:40 -07:00
|
|
|
}
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
static Eina_Bool
|
2012-05-28 09:56:56 -07:00
|
|
|
_inside(Evas_Coord xx1,
|
|
|
|
Evas_Coord yy1,
|
|
|
|
Evas_Coord xx2,
|
|
|
|
Evas_Coord yy2)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
int w = elm_config_finger_size_get() >> 1; /* Finger size devided by 2 */
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (xx1 < (xx2 - w))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
if (xx1 > (xx2 + w))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
if (yy1 < (yy2 - w))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
if (yy1 > (yy2 + w))
|
|
|
|
return EINA_FALSE;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* All *test_reset() funcs are called to clear
|
|
|
|
* gesture intermediate data.
|
|
|
|
* This happens when we need to reset our tests.
|
|
|
|
* for example when gesture is detected or all ABORTed. */
|
2011-07-07 07:41:03 -07:00
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_tap_gestures_test_reset(Gesture_Info *gesture)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
Eina_List *data;
|
|
|
|
Pointer_Event *pe;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(gesture);
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(gesture->obj, sd);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (sd->gest_taps_timeout)
|
|
|
|
{
|
|
|
|
ecore_timer_del(sd->gest_taps_timeout);
|
|
|
|
sd->gest_taps_timeout = NULL;
|
|
|
|
}
|
2011-07-10 04:51:44 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!gesture->data)
|
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
EINA_LIST_FREE (((Taps_Type *)gesture->data)->l, data)
|
|
|
|
EINA_LIST_FREE (data, pe)
|
|
|
|
free(pe);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
memset(gesture->data, 0, sizeof(Taps_Type));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* All *test_reset() funcs are called to clear
|
|
|
|
* gesture intermediate data.
|
|
|
|
* This happens when we need to reset our tests.
|
|
|
|
* for example when gesture is detected or all ABORTed. */
|
|
|
|
static void
|
|
|
|
_n_long_tap_test_reset(Gesture_Info *gesture)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
Pointer_Event *p;
|
|
|
|
Long_Tap_Type *st;
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(gesture);
|
|
|
|
if (!gesture->data) return;
|
|
|
|
|
|
|
|
st = gesture->data;
|
|
|
|
|
2012-10-01 00:36:27 -07:00
|
|
|
EINA_LIST_FOREACH(st->touched, l, p)
|
2012-05-28 09:56:56 -07:00
|
|
|
free(p);
|
|
|
|
|
|
|
|
eina_list_free(st->touched);
|
|
|
|
if (st->timeout)
|
|
|
|
{
|
|
|
|
ecore_timer_del(st->timeout);
|
|
|
|
st->timeout = NULL;
|
|
|
|
}
|
|
|
|
memset(gesture->data, 0, sizeof(Long_Tap_Type));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_momentum_test_reset(Gesture_Info *gesture)
|
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(gesture);
|
|
|
|
if (!gesture->data) return;
|
|
|
|
|
|
|
|
memset(gesture->data, 0, sizeof(Momentum_Type));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_line_data_reset(Line_Data *st)
|
|
|
|
{
|
|
|
|
if (!st)
|
|
|
|
return;
|
|
|
|
|
|
|
|
memset(st, 0, sizeof(Line_Data));
|
|
|
|
st->line_angle = ELM_GESTURE_NEGATIVE_ANGLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_line_test_reset(Gesture_Info *gesture)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
Line_Type *st;
|
|
|
|
Eina_List *list;
|
|
|
|
Line_Data *t_line;
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(gesture);
|
|
|
|
if (!gesture->data) return;
|
|
|
|
|
|
|
|
st = gesture->data;
|
|
|
|
list = st->list;
|
|
|
|
|
2012-10-01 00:36:27 -07:00
|
|
|
EINA_LIST_FOREACH(list, l, t_line)
|
2012-05-28 09:56:56 -07:00
|
|
|
free(t_line);
|
|
|
|
|
|
|
|
eina_list_free(list);
|
|
|
|
st->list = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_zoom_test_reset(Gesture_Info *gesture)
|
|
|
|
{
|
|
|
|
Zoom_Type *st;
|
|
|
|
Evas_Modifier_Mask mask;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN(gesture);
|
|
|
|
if (!gesture->data) return;
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(gesture->obj, sd);
|
|
|
|
|
|
|
|
st = gesture->data;
|
|
|
|
mask = evas_key_modifier_mask_get(
|
|
|
|
evas_object_evas_get(sd->target), "Control");
|
|
|
|
evas_object_key_ungrab(sd->target, "Control_L", mask, 0);
|
|
|
|
evas_object_key_ungrab(sd->target, "Control_R", mask, 0);
|
|
|
|
|
|
|
|
memset(st, 0, sizeof(Zoom_Type));
|
|
|
|
st->zoom_distance_tolerance = sd->zoom_distance_tolerance;
|
|
|
|
st->info.zoom = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_rotate_test_reset(Gesture_Info *gesture)
|
|
|
|
{
|
|
|
|
Rotate_Type *st;
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(gesture);
|
|
|
|
if (!gesture->data) return;
|
|
|
|
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(gesture->obj, sd);
|
|
|
|
st = gesture->data;
|
|
|
|
|
|
|
|
memset(st, 0, sizeof(Rotate_Type));
|
|
|
|
st->info.base_angle = ELM_GESTURE_NEGATIVE_ANGLE;
|
|
|
|
st->rotate_angular_tolerance = sd->rotate_angular_tolerance;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2012-05-28 09:56:56 -07:00
|
|
|
_match_fingers_compare(const void *data1,
|
|
|
|
const void *data2)
|
|
|
|
{
|
|
|
|
/* Compare coords of first item in list to cur coords */
|
2011-07-07 07:41:03 -07:00
|
|
|
const Pointer_Event *pe1 = eina_list_data_get(data1);
|
|
|
|
const Pointer_Event *pe2 = data2;
|
|
|
|
|
|
|
|
if (_inside(pe1->x, pe1->y, pe2->x, pe2->y))
|
|
|
|
return 0;
|
|
|
|
else if (pe1->x < pe2->x)
|
|
|
|
return -1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pe1->x == pe2->x)
|
|
|
|
return pe1->y - pe2->y;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2012-05-28 09:56:56 -07:00
|
|
|
_pe_device_compare(const void *data1,
|
|
|
|
const void *data2)
|
|
|
|
{
|
|
|
|
/* Compare device of first item in list to our pe device */
|
2011-11-07 06:31:20 -08:00
|
|
|
const Pointer_Event *pe1 = eina_list_data_get(data1);
|
2011-07-07 07:41:03 -07:00
|
|
|
const Pointer_Event *pe2 = data2;
|
|
|
|
|
|
|
|
/* Only match if last was a down event */
|
|
|
|
if ((pe1->event_type != EVAS_CALLBACK_MULTI_DOWN) &&
|
2012-05-28 09:56:56 -07:00
|
|
|
(pe1->event_type != EVAS_CALLBACK_MOUSE_DOWN))
|
2011-07-07 07:41:03 -07:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (pe1->device == pe2->device)
|
|
|
|
return 0;
|
|
|
|
else if (pe1->device < pe2->device)
|
|
|
|
return -1;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
static Eina_List *
|
|
|
|
_pointer_event_record(Taps_Type *st,
|
|
|
|
Eina_List *pe_list,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
Elm_Gesture_Layer_Smart_Data *sd,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type)
|
|
|
|
{
|
|
|
|
/* Keep copy of pe and record it in list */
|
2011-07-07 07:41:03 -07:00
|
|
|
Pointer_Event *p = malloc(sizeof(Pointer_Event));
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
memcpy(p, pe, sizeof(Pointer_Event));
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_consume(sd, event_info, event_type, EVAS_EVENT_FLAG_NONE);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
st->sum_x += pe->x;
|
|
|
|
st->sum_y += pe->y;
|
|
|
|
st->n_taps++;
|
|
|
|
|
|
|
|
/* This will also update middle-point to report to user later */
|
|
|
|
st->info.x = st->sum_x / st->n_taps;
|
|
|
|
st->info.y = st->sum_y / st->n_taps;
|
|
|
|
st->info.timestamp = pe->timestamp;
|
|
|
|
|
|
|
|
if (!pe_list)
|
|
|
|
{
|
|
|
|
pe_list = eina_list_append(pe_list, p);
|
|
|
|
st->l = eina_list_append(st->l, pe_list);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pe_list = eina_list_append(pe_list, p);
|
|
|
|
|
|
|
|
return pe_list;
|
|
|
|
}
|
|
|
|
|
2011-07-10 07:10:57 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
2012-05-16 01:44:17 -07:00
|
|
|
* This function checks if the tap gesture is done.
|
2011-10-17 01:12:45 -07:00
|
|
|
*
|
|
|
|
* @param data gesture info pointer
|
2012-05-16 01:44:17 -07:00
|
|
|
* @return EINA_TRUE if it is done.
|
2011-10-17 01:12:45 -07:00
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
2012-05-16 01:44:17 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_tap_gesture_check_finish(Gesture_Info *gesture)
|
|
|
|
{
|
2011-10-17 01:12:45 -07:00
|
|
|
/* Here we check if taps-gesture was completed successfuly */
|
|
|
|
/* Count how many taps were recieved on each device then */
|
|
|
|
/* determine if it matches n_taps_needed defined on START */
|
|
|
|
Taps_Type *st = gesture->data;
|
|
|
|
Eina_List *l;
|
|
|
|
Eina_List *pe_list;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2012-05-17 18:45:40 -07:00
|
|
|
if (!st->l) return EINA_FALSE;
|
2012-10-01 00:36:27 -07:00
|
|
|
EINA_LIST_FOREACH(st->l, l, pe_list)
|
2011-10-17 01:12:45 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
/* No match taps number on device, ABORT */
|
2011-10-17 01:12:45 -07:00
|
|
|
if (eina_list_count(pe_list) != st->n_taps_needed)
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
2012-05-16 01:44:17 -07:00
|
|
|
return EINA_FALSE;
|
2011-10-17 01:12:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-16 01:44:17 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function sets state a tap-gesture to END or ABORT
|
|
|
|
*
|
|
|
|
* @param data gesture info pointer
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
_tap_gesture_finish(void *data)
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
|
|
|
/* This function will test each tap gesture when timer expires */
|
2012-05-17 06:37:10 -07:00
|
|
|
Elm_Gesture_State s = ELM_GESTURE_STATE_ABORT;
|
2012-05-16 01:44:17 -07:00
|
|
|
Gesture_Info *gesture = data;
|
|
|
|
Taps_Type *st = gesture->data;
|
|
|
|
|
2012-05-17 06:37:10 -07:00
|
|
|
if (_tap_gesture_check_finish(gesture))
|
|
|
|
{
|
|
|
|
s = ELM_GESTURE_STATE_END;
|
|
|
|
}
|
2012-05-16 01:44:17 -07:00
|
|
|
|
2011-10-17 01:12:45 -07:00
|
|
|
st->info.n = eina_list_count(st->l);
|
2012-05-28 09:56:56 -07:00
|
|
|
_state_set(gesture, s, gesture->info, EINA_FALSE);
|
2011-10-17 01:12:45 -07:00
|
|
|
_tap_gestures_test_reset(gesture);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* when this timer expires we finish tap gestures.
|
2011-07-10 07:10:57 -07:00
|
|
|
*
|
|
|
|
* @param data The gesture-layer object.
|
|
|
|
* @return cancles callback for this timer.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Eina_Bool
|
2011-10-17 01:12:45 -07:00
|
|
|
_multi_tap_timeout(void *data)
|
2011-07-10 07:10:57 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_DATA_GET(data, sd);
|
2011-07-10 07:10:57 -07:00
|
|
|
|
2011-10-17 01:12:45 -07:00
|
|
|
if (IS_TESTED(ELM_GESTURE_N_TAPS))
|
2012-05-28 09:56:56 -07:00
|
|
|
_tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TAPS]);
|
2011-10-17 01:12:45 -07:00
|
|
|
|
|
|
|
if (IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS))
|
2012-05-28 09:56:56 -07:00
|
|
|
_tap_gesture_finish(sd->gesture[ELM_GESTURE_N_DOUBLE_TAPS]);
|
2011-07-10 07:10:57 -07:00
|
|
|
|
2011-10-17 01:12:45 -07:00
|
|
|
if (IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS))
|
2012-05-28 09:56:56 -07:00
|
|
|
_tap_gesture_finish(sd->gesture[ELM_GESTURE_N_TRIPLE_TAPS]);
|
2011-10-17 01:12:45 -07:00
|
|
|
|
|
|
|
_clear_if_finished(data);
|
2012-05-28 09:56:56 -07:00
|
|
|
sd->gest_taps_timeout = NULL;
|
|
|
|
|
2011-07-10 07:10:57 -07:00
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
|
2011-08-01 06:09:05 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* when this timer expires we START long tap gesture
|
|
|
|
*
|
|
|
|
* @param data The gesture-layer object.
|
|
|
|
* @return cancles callback for this timer.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Eina_Bool
|
|
|
|
_long_tap_timeout(void *data)
|
|
|
|
{
|
|
|
|
Gesture_Info *gesture = data;
|
|
|
|
|
2012-07-02 22:24:03 -07:00
|
|
|
_state_set(gesture, ELM_GESTURE_STATE_MOVE,
|
|
|
|
gesture->data, EINA_TRUE);
|
2011-08-01 06:09:05 -07:00
|
|
|
|
2012-07-02 22:24:03 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2011-08-01 06:09:05 -07:00
|
|
|
}
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
2012-05-17 06:37:10 -07:00
|
|
|
* This function checks the state of a tap gesture.
|
2011-07-07 07:41:03 -07:00
|
|
|
*
|
2012-05-28 09:56:56 -07:00
|
|
|
* @param sd Gesture Layer Widget Data.
|
2011-07-07 07:41:03 -07:00
|
|
|
* @param pe The recent input event as stored in pe struct.
|
|
|
|
* @param event_info Original input event pointer.
|
|
|
|
* @param event_type Type of original input event.
|
2011-10-17 01:12:45 -07:00
|
|
|
* @param gesture what gesture is tested
|
|
|
|
* @param how many taps for this gesture (1, 2 or 3)
|
|
|
|
*
|
2011-07-07 07:41:03 -07:00
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
2012-05-17 06:37:10 -07:00
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_tap_gesture_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type)
|
|
|
|
{
|
|
|
|
int taps = 0;
|
|
|
|
Taps_Type *st;
|
|
|
|
Gesture_Info *gesture;
|
|
|
|
Eina_List *pe_list = NULL;
|
|
|
|
Pointer_Event *pe_down = NULL;
|
|
|
|
Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
|
|
|
|
|
|
|
|
/* Here we fill Tap struct */
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
|
|
|
|
2012-05-17 06:37:10 -07:00
|
|
|
if (!pe)
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
2012-05-17 06:37:10 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
gesture = sd->gesture[g_type];
|
2012-05-17 08:31:31 -07:00
|
|
|
if (!gesture) return;
|
|
|
|
|
|
|
|
switch (g_type)
|
|
|
|
{
|
|
|
|
case ELM_GESTURE_N_TAPS:
|
2012-05-28 09:56:56 -07:00
|
|
|
taps = 1;
|
|
|
|
break;
|
|
|
|
|
2012-05-17 08:31:31 -07:00
|
|
|
case ELM_GESTURE_N_DOUBLE_TAPS:
|
2012-05-28 09:56:56 -07:00
|
|
|
taps = 2;
|
|
|
|
break;
|
|
|
|
|
2012-05-17 08:31:31 -07:00
|
|
|
case ELM_GESTURE_N_TRIPLE_TAPS:
|
2012-05-28 09:56:56 -07:00
|
|
|
taps = 3;
|
|
|
|
break;
|
|
|
|
|
2012-05-17 08:31:31 -07:00
|
|
|
default:
|
2012-05-28 09:56:56 -07:00
|
|
|
taps = 0;
|
|
|
|
break;
|
2012-05-17 08:31:31 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st = gesture->data;
|
|
|
|
if (!st) /* Allocated once on first time */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
st = calloc(1, sizeof(Taps_Type));
|
|
|
|
gesture->data = st;
|
2011-10-17 01:12:45 -07:00
|
|
|
_tap_gestures_test_reset(gesture);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (pe->event_type)
|
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Check if got tap on same cord was tapped before */
|
|
|
|
pe_list = eina_list_search_unsorted(st->l, _match_fingers_compare, pe);
|
2011-11-07 06:31:20 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if ((!pe_list) &&
|
|
|
|
/* This device was touched in other cord before completion */
|
|
|
|
eina_list_search_unsorted(st->l, _pe_device_compare, pe))
|
|
|
|
{
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-11-07 06:31:20 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
|
|
|
}
|
2011-11-07 06:31:20 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
pe_list = _pointer_event_record
|
|
|
|
(st, pe_list, pe, sd, event_info, event_type);
|
2012-07-14 02:17:04 -07:00
|
|
|
if ((!sd->gest_taps_timeout) &&
|
|
|
|
(_elm_config->glayer_double_tap_timeout > 0.0))
|
|
|
|
sd->gest_taps_timeout =
|
|
|
|
ecore_timer_add(_elm_config->glayer_double_tap_timeout,
|
|
|
|
_multi_tap_timeout, gesture->obj);
|
|
|
|
else if (sd->gest_taps_timeout)
|
|
|
|
ecore_timer_reset(sd->gest_taps_timeout);
|
2012-05-17 06:37:10 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* This is the first mouse down we got */
|
|
|
|
if ((pe->device == 0) && (eina_list_count(pe_list) == 1))
|
|
|
|
{
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_START,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st->n_taps_needed = taps * 2; /* count DOWN and UP */
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (eina_list_count(pe_list) > st->n_taps_needed)
|
2012-07-14 02:17:04 -07:00
|
|
|
/* If we arleady got too many touches for this gesture. */
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
|
|
|
&st->info, EINA_FALSE);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
break;
|
2011-10-17 01:12:45 -07:00
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
|
2012-07-14 02:17:04 -07:00
|
|
|
if (!pe_list) return;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
|
|
|
pe_list = _pointer_event_record
|
|
|
|
(st, pe_list, pe, sd, event_info, event_type);
|
|
|
|
|
|
|
|
if (((gesture->g_type == ELM_GESTURE_N_TAPS) &&
|
|
|
|
!IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS) &&
|
|
|
|
!IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)) ||
|
|
|
|
((gesture->g_type == ELM_GESTURE_N_DOUBLE_TAPS) &&
|
|
|
|
!IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS)))
|
|
|
|
{
|
|
|
|
if (_tap_gesture_check_finish(gesture))
|
|
|
|
{
|
|
|
|
_tap_gesture_finish(gesture);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2012-05-16 01:44:17 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
break;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
case EVAS_CALLBACK_MULTI_MOVE:
|
|
|
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Get first event in first list, this has to be a Mouse Down event */
|
|
|
|
/* and verify that user didn't move out of this area before next tap */
|
|
|
|
pe_list = eina_list_search_unsorted(st->l, _pe_device_compare, pe);
|
|
|
|
if (pe_list)
|
|
|
|
{
|
|
|
|
pe_down = eina_list_data_get(pe_list);
|
|
|
|
if (!_inside(pe_down->x, pe_down->y, pe->x, pe->y))
|
|
|
|
{
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
default:
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-01 06:09:05 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function computes center-point for long-tap gesture
|
|
|
|
*
|
|
|
|
* @param st Long Tap gesture info pointer
|
|
|
|
* @param pe The recent input event as stored in pe struct.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2011-10-25 02:51:30 -07:00
|
|
|
_compute_taps_center(Long_Tap_Type *st,
|
2012-05-28 09:56:56 -07:00
|
|
|
Evas_Coord *x_out,
|
|
|
|
Evas_Coord *y_out,
|
|
|
|
Pointer_Event *pe)
|
2011-08-01 06:09:05 -07:00
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
Pointer_Event *p;
|
|
|
|
Evas_Coord x = 0, y = 0;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
|
|
|
if (!eina_list_count(st->touched))
|
|
|
|
return;
|
|
|
|
|
2012-10-01 00:36:27 -07:00
|
|
|
EINA_LIST_FOREACH(st->touched, l, p)
|
2011-08-01 06:09:05 -07:00
|
|
|
{ /* Accumulate all then take avarage */
|
2012-05-28 09:56:56 -07:00
|
|
|
if (p->device == pe->device) /* This will take care of values
|
|
|
|
* coming from MOVE event */
|
|
|
|
{
|
|
|
|
x += pe->x;
|
|
|
|
y += pe->y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x += p->x;
|
|
|
|
y += p->y;
|
|
|
|
}
|
2011-08-01 06:09:05 -07:00
|
|
|
}
|
|
|
|
|
2011-10-25 02:51:30 -07:00
|
|
|
*x_out = x / eina_list_count(st->touched);
|
|
|
|
*y_out = y / eina_list_count(st->touched);
|
2011-08-01 06:09:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function checks N long-tap gesture.
|
|
|
|
*
|
|
|
|
* @param obj The gesture-layer object.
|
|
|
|
* @param pe The recent input event as stored in pe struct.
|
|
|
|
* @param event_info Original input event pointer.
|
|
|
|
* @param event_type Type of original input event.
|
|
|
|
* @param g_type what Gesture we are testing.
|
|
|
|
* @param taps How many click/taps we test for.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_n_long_tap_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
2012-01-27 08:51:23 -08:00
|
|
|
Elm_Gesture_Type g_type)
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
|
|
|
Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
|
|
|
|
Gesture_Info *gesture;
|
|
|
|
Long_Tap_Type *st;
|
2011-08-01 06:09:05 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Here we fill Recent_Taps struct and fire-up click/tap timers */
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
|
|
|
|
|
|
|
if (!pe) /* this happens when unhandled event arrived */
|
2011-10-25 02:51:30 -07:00
|
|
|
return; /* see _make_pointer_event function */
|
2012-05-28 09:56:56 -07:00
|
|
|
|
|
|
|
gesture = sd->gesture[g_type];
|
2011-10-25 02:51:30 -07:00
|
|
|
if (!gesture) return;
|
2011-08-01 06:09:05 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st = gesture->data;
|
|
|
|
if (!st) /* Allocated once on first time */
|
|
|
|
{
|
2011-08-01 06:09:05 -07:00
|
|
|
st = calloc(1, sizeof(Long_Tap_Type));
|
|
|
|
gesture->data = st;
|
|
|
|
_n_long_tap_test_reset(gesture);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (pe->event_type)
|
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
2012-05-28 09:56:56 -07:00
|
|
|
st->touched = _touched_device_add(st->touched, pe);
|
2011-10-27 08:57:14 -07:00
|
|
|
st->info.n = eina_list_count(st->touched);
|
2011-10-25 02:51:30 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* This is the first mouse down we got */
|
2012-07-02 22:24:03 -07:00
|
|
|
if (eina_list_count(st->touched) == 1)
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
2012-07-02 22:24:03 -07:00
|
|
|
_state_set(gesture, ELM_GESTURE_STATE_START,
|
|
|
|
gesture->data, EINA_FALSE);
|
2011-10-27 08:57:14 -07:00
|
|
|
st->info.timestamp = pe->timestamp;
|
2011-08-01 06:09:05 -07:00
|
|
|
|
2011-10-27 08:57:14 -07:00
|
|
|
/* To test long tap */
|
|
|
|
/* When this timer expires, gesture STARTED */
|
2012-07-14 02:17:04 -07:00
|
|
|
if ((!st->timeout) && (sd->long_tap_start_timeout > 0.0))
|
2012-05-28 09:56:56 -07:00
|
|
|
st->timeout = ecore_timer_add(sd->long_tap_start_timeout,
|
2011-10-27 08:57:14 -07:00
|
|
|
_long_tap_timeout, gesture);
|
|
|
|
}
|
2012-07-02 22:24:03 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (st->timeout)
|
|
|
|
ecore_timer_reset(st->timeout);
|
|
|
|
}
|
|
|
|
|
2011-08-01 06:09:05 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-10-27 08:57:14 -07:00
|
|
|
_compute_taps_center(st, &st->info.x, &st->info.y, pe);
|
|
|
|
st->center_x = st->info.x;
|
|
|
|
st->center_y = st->info.y;
|
|
|
|
break;
|
2011-08-01 06:09:05 -07:00
|
|
|
|
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
st->touched = _touched_device_remove(st->touched, pe);
|
2011-10-27 08:57:14 -07:00
|
|
|
_compute_taps_center(st, &st->center_x, &st->center_y, pe);
|
2012-07-02 22:24:03 -07:00
|
|
|
if (st->info.n)
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
2012-07-02 22:24:03 -07:00
|
|
|
if (gesture->state == ELM_GESTURE_STATE_MOVE)
|
2012-07-14 02:17:04 -07:00
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_END,
|
|
|
|
&st->info, EINA_FALSE);
|
2012-07-02 22:24:03 -07:00
|
|
|
else
|
2012-07-14 02:17:04 -07:00
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
|
|
|
&st->info, EINA_FALSE);
|
2012-07-02 22:24:03 -07:00
|
|
|
|
|
|
|
if (st->timeout)
|
|
|
|
{
|
|
|
|
ecore_timer_del(st->timeout);
|
|
|
|
st->timeout = NULL;
|
|
|
|
}
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-10-27 08:57:14 -07:00
|
|
|
}
|
2011-10-17 01:12:45 -07:00
|
|
|
|
2011-10-27 08:57:14 -07:00
|
|
|
break;
|
2011-08-01 06:09:05 -07:00
|
|
|
|
|
|
|
case EVAS_CALLBACK_MULTI_MOVE:
|
|
|
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
2012-03-29 04:09:45 -07:00
|
|
|
if (st->info.n &&
|
2012-05-28 09:56:56 -07:00
|
|
|
((gesture->state == ELM_GESTURE_STATE_START) ||
|
|
|
|
/* Report MOVE only if STARTED */
|
|
|
|
(gesture->state == ELM_GESTURE_STATE_MOVE)))
|
|
|
|
{
|
2011-10-27 08:57:14 -07:00
|
|
|
Evas_Coord x = 0;
|
|
|
|
Evas_Coord y = 0;
|
|
|
|
|
|
|
|
_compute_taps_center(st, &x, &y, pe);
|
|
|
|
/* ABORT if user moved fingers out of tap area */
|
|
|
|
if (!_inside(x, y, st->center_x, st->center_y))
|
2012-07-02 22:24:03 -07:00
|
|
|
{
|
|
|
|
if (st->timeout)
|
|
|
|
{
|
|
|
|
ecore_timer_del(st->timeout);
|
|
|
|
st->timeout = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Report MOVE if gesture started */
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
}
|
2011-10-25 02:51:30 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-10-27 08:57:14 -07:00
|
|
|
}
|
|
|
|
break;
|
2011-08-01 06:09:05 -07:00
|
|
|
|
|
|
|
default:
|
2011-10-27 08:57:14 -07:00
|
|
|
return;
|
2011-08-01 06:09:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function computes momentum for MOMENTUM, LINE and FLICK gestures
|
|
|
|
* This momentum value will be sent to widget when gesture is completed.
|
|
|
|
*
|
|
|
|
* @param momentum pointer to buffer where we record momentum value.
|
|
|
|
* @param x1 x coord where user started gesture.
|
|
|
|
* @param y1 y coord where user started gesture.
|
|
|
|
* @param x2 x coord where user completed gesture.
|
|
|
|
* @param y2 y coord where user completed gesture.
|
|
|
|
* @param t1x timestamp for X, when user started gesture.
|
|
|
|
* @param t1y timestamp for Y, when user started gesture.
|
|
|
|
* @param t2 timestamp when user completed gesture.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_momentum_set(Elm_Gesture_Momentum_Info *momentum,
|
|
|
|
Evas_Coord xx1,
|
|
|
|
Evas_Coord yy1,
|
|
|
|
Evas_Coord xx2,
|
|
|
|
Evas_Coord yy2,
|
|
|
|
unsigned int t1x,
|
|
|
|
unsigned int t1y,
|
|
|
|
unsigned int t2)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
Evas_Coord velx = 0, vely = 0, vel;
|
2012-03-07 00:13:06 -08:00
|
|
|
Evas_Coord dx = xx2 - xx1;
|
|
|
|
Evas_Coord dy = yy2 - yy1;
|
2011-07-07 07:41:03 -07:00
|
|
|
int dtx = t2 - t1x;
|
|
|
|
int dty = t2 - t1y;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
if (dtx > 0)
|
|
|
|
velx = (dx * 1000) / dtx;
|
|
|
|
|
|
|
|
if (dty > 0)
|
|
|
|
vely = (dy * 1000) / dty;
|
|
|
|
|
|
|
|
vel = sqrt((velx * velx) + (vely * vely));
|
|
|
|
|
|
|
|
if ((_elm_config->thumbscroll_friction > 0.0) &&
|
2012-05-28 09:56:56 -07:00
|
|
|
(vel > _elm_config->thumbscroll_momentum_threshold)) /* report
|
|
|
|
* momentum */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
momentum->mx = velx;
|
|
|
|
momentum->my = vely;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
momentum->mx = 0;
|
|
|
|
momentum->my = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function is used for computing rotation angle (DEG).
|
|
|
|
*
|
|
|
|
* @param x1 first finger x location.
|
|
|
|
* @param y1 first finger y location.
|
|
|
|
* @param x2 second finger x location.
|
|
|
|
* @param y2 second finger y location.
|
|
|
|
*
|
2011-12-21 00:48:12 -08:00
|
|
|
* @return angle of the line between (x1,y1), (x2,y2) in Deg.
|
|
|
|
* Angles now are given in DEG, not RAD.
|
|
|
|
* ZERO angle at 12-oclock, growing clockwise.
|
2011-07-07 07:41:03 -07:00
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static double
|
2012-05-28 09:56:56 -07:00
|
|
|
_angle_get(Evas_Coord xx1,
|
|
|
|
Evas_Coord yy1,
|
|
|
|
Evas_Coord xx2,
|
|
|
|
Evas_Coord yy2)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2011-12-21 00:48:08 -08:00
|
|
|
double a, xx, yy, rt = (-1);
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2012-03-07 00:19:55 -08:00
|
|
|
xx = fabs(xx2 - xx1);
|
|
|
|
yy = fabs(yy2 - yy1);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-03-07 00:19:55 -08:00
|
|
|
if (((int)xx) && ((int)yy))
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2011-12-21 00:48:08 -08:00
|
|
|
rt = a = RAD2DEG(atan(yy / xx));
|
2012-03-07 00:19:55 -08:00
|
|
|
if (xx1 < xx2)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-03-07 00:19:55 -08:00
|
|
|
if (yy1 < yy2) rt = 360 - a;
|
|
|
|
else rt = a;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-03-07 00:19:55 -08:00
|
|
|
if (yy1 < yy2) rt = 180 + a;
|
|
|
|
else rt = 180 - a;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (rt < 0) /* Do this only if rt is not set */
|
|
|
|
{
|
|
|
|
if (((int)xx)) /* Horizontal line */
|
|
|
|
{
|
2012-03-07 00:19:55 -08:00
|
|
|
if (xx2 < xx1) rt = 180;
|
|
|
|
else rt = 0.0;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
else
|
2011-12-21 00:48:08 -08:00
|
|
|
{ /* Vertical line */
|
2012-05-28 09:56:56 -07:00
|
|
|
if (yy2 < yy1) rt = 90;
|
|
|
|
else rt = 270;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-21 00:48:08 -08:00
|
|
|
/* Now we want to change from:
|
|
|
|
* 90 0
|
|
|
|
* original circle 180 0 We want: 270 90
|
|
|
|
* 270 180
|
|
|
|
*/
|
|
|
|
rt = 450 - rt;
|
2012-03-07 00:19:55 -08:00
|
|
|
if (rt >= 360) rt -= 360;
|
2011-12-21 00:48:08 -08:00
|
|
|
|
|
|
|
return rt;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function is used for computing the magnitude and direction
|
|
|
|
* of vector between two points.
|
|
|
|
*
|
|
|
|
* @param x1 first finger x location.
|
|
|
|
* @param y1 first finger y location.
|
|
|
|
* @param x2 second finger x location.
|
|
|
|
* @param y2 second finger y location.
|
|
|
|
* @param l length computed (output)
|
|
|
|
* @param a angle computed (output)
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_vector_get(Evas_Coord xx1,
|
|
|
|
Evas_Coord yy1,
|
|
|
|
Evas_Coord xx2,
|
|
|
|
Evas_Coord yy2,
|
|
|
|
Evas_Coord *l,
|
|
|
|
double *a)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
Evas_Coord xx, yy;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2012-03-07 00:19:55 -08:00
|
|
|
xx = xx2 - xx1;
|
|
|
|
yy = yy2 - yy1;
|
2012-05-28 09:56:56 -07:00
|
|
|
*l = (Evas_Coord)sqrt((xx * xx) + (yy * yy));
|
|
|
|
*a = _angle_get(xx1, yy1, xx2, yy2);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2012-05-28 09:56:56 -07:00
|
|
|
_direction_get(Evas_Coord xx1,
|
|
|
|
Evas_Coord xx2)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-03-07 00:19:55 -08:00
|
|
|
if (xx2 < xx1) return -1;
|
|
|
|
if (xx2 > xx1) return 1;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2011-12-21 00:47:53 -08:00
|
|
|
return 0;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
2012-05-28 09:56:56 -07:00
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function tests momentum gesture.
|
|
|
|
* @param obj The gesture-layer object.
|
|
|
|
* @param pe The recent input event as stored in pe struct.
|
|
|
|
* @param event_info recent input event.
|
|
|
|
* @param event_type recent event type.
|
|
|
|
* @param g_type what Gesture we are testing.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_momentum_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
2012-03-07 00:19:55 -08:00
|
|
|
Elm_Gesture_Type g_type)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
Eina_List *l;
|
|
|
|
Pointer_Event *p;
|
|
|
|
Momentum_Type *st;
|
|
|
|
Gesture_Info *gesture;
|
|
|
|
Pointer_Event pe_local;
|
|
|
|
Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
|
|
|
|
Elm_Gesture_State state_to_report = ELM_GESTURE_STATE_MOVE;
|
|
|
|
unsigned int cnt = 1; /* We start counter counting current pe event */
|
|
|
|
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
|
|
|
|
|
|
|
gesture = sd->gesture[g_type];
|
2012-05-17 08:31:31 -07:00
|
|
|
if (!gesture) return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2011-11-08 05:09:18 -08:00
|
|
|
/* When continues enable = TRUE a gesture may START on MOVE event */
|
|
|
|
/* We don't allow this to happen with the if-statement below. */
|
|
|
|
/* When continues enable = FALSE a gesture may START on DOWN only */
|
|
|
|
/* Therefor it would NOT start on MOVE event. */
|
|
|
|
/* NOTE that touched list is updated AFTER this function returns */
|
|
|
|
/* so (count == 0) when we get here on first touch on surface. */
|
2012-05-28 09:56:56 -07:00
|
|
|
if ((sd->glayer_continues_enable) && (!eina_list_count(sd->touched)))
|
|
|
|
return; /* Got move on mouse-over move */
|
2011-11-07 06:31:25 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st = gesture->data;
|
|
|
|
if (!st) /* Allocated once on first time */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
st = calloc(1, sizeof(Momentum_Type));
|
|
|
|
gesture->data = st;
|
|
|
|
_momentum_test_reset(gesture);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pe)
|
|
|
|
return;
|
|
|
|
|
2011-10-25 02:51:22 -07:00
|
|
|
/* First make avarage of all touched devices to determine center point */
|
2012-05-28 09:56:56 -07:00
|
|
|
pe_local = *pe; /* Copy pe event info to local */
|
2012-10-01 00:36:27 -07:00
|
|
|
EINA_LIST_FOREACH(sd->touched, l, p)
|
2012-05-28 09:56:56 -07:00
|
|
|
if (p->device != pe_local.device)
|
|
|
|
{
|
|
|
|
pe_local.x += p->x;
|
|
|
|
pe_local.y += p->y;
|
|
|
|
cnt++;
|
|
|
|
}
|
2011-10-25 02:51:22 -07:00
|
|
|
|
|
|
|
/* Compute avarage to get center point */
|
|
|
|
pe_local.x /= cnt;
|
|
|
|
pe_local.y /= cnt;
|
|
|
|
|
|
|
|
/* If user added finger - reset gesture */
|
2011-10-30 03:08:01 -07:00
|
|
|
if ((st->info.n) && (st->info.n < cnt))
|
2011-10-25 02:51:22 -07:00
|
|
|
state_to_report = ELM_GESTURE_STATE_ABORT;
|
|
|
|
|
2011-10-30 03:08:01 -07:00
|
|
|
if (st->info.n < cnt)
|
|
|
|
st->info.n = cnt;
|
2011-10-25 02:51:22 -07:00
|
|
|
|
2011-09-08 03:10:27 -07:00
|
|
|
switch (event_type)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
2011-10-25 02:51:22 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
2011-10-10 08:47:34 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
2011-10-25 02:51:22 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_MOVE:
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!st->t_st_x)
|
|
|
|
{
|
|
|
|
if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
|
|
|
|
(event_type == EVAS_CALLBACK_MULTI_DOWN) ||
|
|
|
|
(sd->glayer_continues_enable)) /* start also on MOVE */
|
|
|
|
{ /* We start on MOVE when cont-enabled only */
|
|
|
|
st->line_st.x = st->line_end.x = pe_local.x;
|
|
|
|
st->line_st.y = st->line_end.y = pe_local.y;
|
|
|
|
st->t_st_x = st->t_st_y = st->t_end = pe_local.timestamp;
|
|
|
|
st->xdir = st->ydir = 0;
|
|
|
|
st->info.x2 = st->info.x1 = pe_local.x;
|
|
|
|
st->info.y2 = st->info.y1 = pe_local.y;
|
|
|
|
st->info.tx = st->info.ty = pe_local.timestamp;
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_START,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (st->t_up)
|
|
|
|
{
|
|
|
|
Eina_Bool force = EINA_TRUE; /* for move state */
|
2011-10-25 02:51:22 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* ABORT if got DOWN or MOVE event after UP+timeout */
|
|
|
|
if ((st->t_up + ELM_GESTURE_MULTI_TIMEOUT) < pe_local.timestamp)
|
|
|
|
{
|
|
|
|
state_to_report = ELM_GESTURE_STATE_ABORT;
|
|
|
|
force = EINA_FALSE;
|
|
|
|
}
|
2012-01-01 04:30:49 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* We report state but don't compute momentum now */
|
|
|
|
ev_flag = _state_set(gesture, state_to_report, &st->info,
|
|
|
|
force);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
return; /* Stop computing when user remove finger */
|
|
|
|
}
|
2011-10-25 02:51:22 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Too long of a wait, reset all values */
|
|
|
|
if ((pe_local.timestamp - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->t_end)
|
|
|
|
{
|
|
|
|
st->line_st.x = pe_local.x;
|
|
|
|
st->line_st.y = pe_local.y;
|
|
|
|
st->t_st_y = st->t_st_x = pe_local.timestamp;
|
|
|
|
st->info.tx = st->t_st_x;
|
|
|
|
st->info.ty = st->t_st_y;
|
|
|
|
st->xdir = st->ydir = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int xdir, ydir;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
xdir = _direction_get(st->line_end.x, pe_local.x);
|
|
|
|
ydir = _direction_get(st->line_end.y, pe_local.y);
|
|
|
|
if (xdir && (xdir != st->xdir))
|
|
|
|
{
|
|
|
|
st->line_st.x = st->line_end.x;
|
|
|
|
st->info.tx = st->t_st_x = st->t_end;
|
|
|
|
st->xdir = xdir;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (ydir && (ydir != st->ydir))
|
|
|
|
{
|
|
|
|
st->line_st.y = st->line_end.y;
|
|
|
|
st->info.ty = st->t_st_y = st->t_end;
|
|
|
|
st->ydir = ydir;
|
|
|
|
}
|
|
|
|
}
|
2012-01-01 04:30:49 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st->info.x2 = st->line_end.x = pe_local.x;
|
|
|
|
st->info.y2 = st->line_end.y = pe_local.y;
|
|
|
|
st->t_end = pe_local.timestamp;
|
|
|
|
_momentum_set(&st->info, st->line_st.x, st->line_st.y,
|
|
|
|
pe_local.x, pe_local.y, st->t_st_x, st->t_st_y,
|
|
|
|
pe_local.timestamp);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
ev_flag = _state_set(gesture, state_to_report, &st->info,
|
|
|
|
EINA_TRUE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
break;
|
2011-10-10 08:47:34 -07:00
|
|
|
|
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
2011-10-25 02:51:22 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
st->t_up = pe_local.timestamp; /* Record recent up event time */
|
|
|
|
if ((cnt > 1) || /* Ignore if more fingers touch surface */
|
|
|
|
(!st->t_st_x)) /* IGNORE if info was cleared, long press,move */
|
|
|
|
return;
|
2011-10-10 08:47:34 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Too long of a wait, reset all values */
|
|
|
|
if ((pe_local.timestamp - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->t_end)
|
|
|
|
{
|
|
|
|
st->line_st.x = pe_local.x;
|
|
|
|
st->line_st.y = pe_local.y;
|
|
|
|
st->t_st_y = st->t_st_x = pe_local.timestamp;
|
|
|
|
st->xdir = st->ydir = 0;
|
|
|
|
}
|
2011-10-10 08:47:34 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st->info.x2 = pe_local.x;
|
|
|
|
st->info.y2 = pe_local.y;
|
|
|
|
st->line_end.x = pe_local.x;
|
|
|
|
st->line_end.y = pe_local.y;
|
|
|
|
st->t_end = pe_local.timestamp;
|
|
|
|
|
|
|
|
if ((fabs(st->info.mx) > ELM_GESTURE_MINIMUM_MOMENTUM) ||
|
|
|
|
(fabs(st->info.my) > ELM_GESTURE_MINIMUM_MOMENTUM))
|
|
|
|
state_to_report = ELM_GESTURE_STATE_END;
|
|
|
|
else
|
|
|
|
state_to_report = ELM_GESTURE_STATE_ABORT;
|
2011-11-10 08:06:09 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
ev_flag = _state_set(gesture, state_to_report, &st->info,
|
|
|
|
EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
default:
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2012-05-28 09:56:56 -07:00
|
|
|
_line_device_compare(const void *data1,
|
|
|
|
const void *data2)
|
|
|
|
{
|
|
|
|
/* Compare device component of line struct */
|
2011-07-07 07:41:03 -07:00
|
|
|
const Line_Data *ln1 = data1;
|
|
|
|
const int *device = data2;
|
|
|
|
|
|
|
|
if (ln1->t_st) /* Compare only with lines that started */
|
2012-05-28 09:56:56 -07:00
|
|
|
return ln1->device - (*device);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return -1;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function construct line struct from input.
|
|
|
|
* @param info pointer to store line momentum.
|
|
|
|
* @param st line info to store input data.
|
|
|
|
* @param pe The recent input event as stored in pe struct.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Eina_Bool
|
2012-05-28 09:56:56 -07:00
|
|
|
_single_line_process(Elm_Gesture_Line_Info *info,
|
|
|
|
Line_Data *st,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
Evas_Callback_Type event_type)
|
|
|
|
{
|
|
|
|
/* Record events and set momentum for line pointed by st */
|
2011-07-07 07:41:03 -07:00
|
|
|
if (!pe)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
2011-09-08 03:10:27 -07:00
|
|
|
switch (event_type)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
2011-10-10 08:47:34 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
2011-07-07 07:41:03 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
2011-10-10 08:47:34 -07:00
|
|
|
case EVAS_CALLBACK_MULTI_MOVE:
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!st->t_st) /* This happens only when line starts */
|
|
|
|
{
|
|
|
|
st->line_st.x = pe->x;
|
|
|
|
st->line_st.y = pe->y;
|
|
|
|
st->t_st = pe->timestamp;
|
|
|
|
st->device = pe->device;
|
|
|
|
info->momentum.x1 = pe->x;
|
|
|
|
info->momentum.y1 = pe->y;
|
|
|
|
info->momentum.tx = pe->timestamp;
|
|
|
|
info->momentum.ty = pe->timestamp;
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
2011-10-10 08:47:34 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
break;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
/* IGNORE if line info was cleared, like long press, move */
|
|
|
|
if (!st->t_st)
|
|
|
|
return EINA_FALSE;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st->line_end.x = pe->x;
|
|
|
|
st->line_end.y = pe->y;
|
|
|
|
st->t_end = pe->timestamp;
|
|
|
|
break;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
default:
|
2012-05-28 09:56:56 -07:00
|
|
|
return EINA_FALSE;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!st->t_st)
|
|
|
|
{
|
|
|
|
_line_data_reset(st);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
info->momentum.x2 = pe->x;
|
|
|
|
info->momentum.y2 = pe->y;
|
2012-05-28 09:56:56 -07:00
|
|
|
_momentum_set(&info->momentum, st->line_st.x, st->line_st.y, pe->x, pe->y,
|
|
|
|
st->t_st, st->t_st, pe->timestamp);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function test for (n) line gesture.
|
|
|
|
* @param obj The gesture-layer object.
|
|
|
|
* @param pe The recent input event as stored in pe struct.
|
|
|
|
* @param event_info Original input event pointer.
|
|
|
|
* @param event_type Type of original input event.
|
|
|
|
* @param g_type what Gesture we are testing.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_n_line_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type)
|
|
|
|
{
|
|
|
|
unsigned cnt;
|
|
|
|
Line_Type *st;
|
|
|
|
Eina_List *list;
|
|
|
|
Gesture_Info *gesture;
|
|
|
|
Line_Data *line = NULL;
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
if (!pe)
|
|
|
|
return;
|
2012-05-28 09:56:56 -07:00
|
|
|
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
|
|
|
|
|
|
|
gesture = sd->gesture[g_type];
|
2011-07-07 07:41:03 -07:00
|
|
|
if (!gesture ) return;
|
2011-10-10 08:47:34 -07:00
|
|
|
|
2011-11-08 05:09:18 -08:00
|
|
|
/* When continues enable = TRUE a gesture may START on MOVE event */
|
|
|
|
/* We don't allow this to happen with the if-statement below. */
|
|
|
|
/* When continues enable = FALSE a gesture may START on DOWN only */
|
|
|
|
/* Therefor it would NOT start on MOVE event. */
|
|
|
|
/* NOTE that touched list is updated AFTER this function returns */
|
|
|
|
/* so (count == 0) when we get here on first touch on surface. */
|
2012-05-28 09:56:56 -07:00
|
|
|
if ((sd->glayer_continues_enable) && (!eina_list_count(sd->touched)))
|
|
|
|
return; /* Got move on mouse-over move */
|
2011-11-07 06:31:25 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st = gesture->data;
|
2011-07-07 07:41:03 -07:00
|
|
|
if (!st)
|
|
|
|
{
|
|
|
|
st = calloc(1, sizeof(Line_Type));
|
|
|
|
gesture->data = st;
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
list = st->list;
|
|
|
|
cnt = eina_list_count(list);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (cnt) /* list is not empty, locate this device on list */
|
|
|
|
{
|
|
|
|
line = (Line_Data *)eina_list_search_unsorted
|
|
|
|
(st->list, _line_device_compare, &pe->device);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!line) /* List is empty or device not found, new line-struct on
|
|
|
|
* START only */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
|
2012-05-28 09:56:56 -07:00
|
|
|
(event_type == EVAS_CALLBACK_MULTI_DOWN) ||
|
|
|
|
((sd->glayer_continues_enable) && /* START on MOVE also */
|
|
|
|
((event_type == EVAS_CALLBACK_MOUSE_MOVE) ||
|
|
|
|
/* Allocate new item on START only */
|
|
|
|
(event_type == EVAS_CALLBACK_MULTI_MOVE))))
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
line = calloc(1, sizeof(Line_Data));
|
|
|
|
_line_data_reset(line);
|
|
|
|
list = eina_list_append(list, line);
|
|
|
|
st->list = list;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!line) /* This may happen on MOVE that comes before DOWN */
|
|
|
|
return; /* No line-struct to work with, can't continue testing */
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* update st with input */
|
|
|
|
if (_single_line_process(&st->info, line, pe, event_type))
|
|
|
|
_event_consume(sd, event_info, event_type, EVAS_EVENT_FLAG_NONE);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
/* Get direction and magnitude of the line */
|
|
|
|
double angle;
|
2012-05-28 09:56:56 -07:00
|
|
|
_vector_get(line->line_st.x, line->line_st.y, pe->x, pe->y,
|
|
|
|
&line->line_length, &angle);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
/* These are used later to compare lines length */
|
|
|
|
Evas_Coord shortest_line_len = line->line_length;
|
|
|
|
Evas_Coord longest_line_len = line->line_length;
|
|
|
|
Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
|
|
|
|
|
|
|
|
/* Now update line-state */
|
2012-05-28 09:56:56 -07:00
|
|
|
if (line->t_st) /* Analyze line only if line started */
|
|
|
|
{
|
|
|
|
if (line->line_angle >= 0.0) /* if line direction was set, we
|
|
|
|
* test if broke tolerance */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
double a = fabs(angle - line->line_angle);
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Distance from line */
|
|
|
|
double d = (tan(DEG2RAD(a))) * line->line_length;
|
|
|
|
/* Broke tolerance: abort line and start a new one */
|
|
|
|
if ((d > sd->line_distance_tolerance) ||
|
|
|
|
(a > sd->line_angular_tolerance))
|
|
|
|
{
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-07-07 07:41:03 -07:00
|
|
|
return;
|
|
|
|
}
|
2011-09-08 03:10:27 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* We may finish line if momentum is zero */
|
|
|
|
if (sd->glayer_continues_enable)
|
|
|
|
{
|
2011-09-08 03:10:34 -07:00
|
|
|
/* This is for continues-gesture */
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Finish line on zero momentum for continues gesture */
|
2011-09-08 03:10:34 -07:00
|
|
|
if ((!st->info.momentum.mx) && (!st->info.momentum.my))
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
2011-09-08 03:10:34 -07:00
|
|
|
line->line_end.x = pe->x;
|
|
|
|
line->line_end.y = pe->y;
|
|
|
|
line->t_end = pe->timestamp;
|
|
|
|
}
|
2011-09-08 03:10:27 -07:00
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* Record the line angle as it broke minimum length for line */
|
2012-05-28 09:56:56 -07:00
|
|
|
if (line->line_length >= sd->line_min_length)
|
|
|
|
st->info.angle = line->line_angle = angle;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (line->t_end)
|
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
if (line->line_angle < 0.0) /* it's not a line, too short
|
|
|
|
* more close to a tap */
|
|
|
|
{
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-07-07 07:41:03 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Count how many lines already started / ended */
|
|
|
|
int started = 0;
|
|
|
|
int ended = 0;
|
|
|
|
unsigned int tm_start = pe->timestamp;
|
|
|
|
unsigned int tm_end = pe->timestamp;
|
|
|
|
Eina_List *l;
|
|
|
|
Line_Data *t_line;
|
|
|
|
double base_angle = ELM_GESTURE_NEGATIVE_ANGLE;
|
|
|
|
Eina_Bool lines_parallel = EINA_TRUE;
|
2012-10-01 00:36:27 -07:00
|
|
|
EINA_LIST_FOREACH(list, l, t_line)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
if (base_angle < 0)
|
|
|
|
base_angle = t_line->line_angle;
|
|
|
|
else
|
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
if (t_line->line_angle >= 0) /* Compare angle only with
|
|
|
|
* lines with direction
|
|
|
|
* defined */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
if (fabs(base_angle - t_line->line_angle) >
|
2012-05-28 09:56:56 -07:00
|
|
|
sd->line_angular_tolerance)
|
2011-07-07 07:41:03 -07:00
|
|
|
lines_parallel = EINA_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (t_line->line_length) /* update only if this line is used */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
if (shortest_line_len > t_line->line_length)
|
|
|
|
shortest_line_len = t_line->line_length;
|
|
|
|
|
|
|
|
if (longest_line_len < t_line->line_length)
|
|
|
|
longest_line_len = t_line->line_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t_line->t_st)
|
|
|
|
{
|
|
|
|
started++;
|
|
|
|
if (t_line->t_st < tm_start)
|
|
|
|
tm_start = t_line->t_st;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (t_line->t_end)
|
|
|
|
{
|
|
|
|
ended++;
|
|
|
|
if (t_line->t_end < tm_end)
|
|
|
|
tm_end = t_line->t_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-30 03:08:05 -07:00
|
|
|
st->info.momentum.n = started;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
if (ended &&
|
2012-05-28 09:56:56 -07:00
|
|
|
((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
|
|
|
|
/* user lift one finger then starts again without line-end - ABORT */
|
|
|
|
(event_type == EVAS_CALLBACK_MULTI_DOWN)))
|
|
|
|
{
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
|
|
|
|
EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-07-07 07:41:03 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!lines_parallel) /* Lines are NOT at same direction, abort this
|
|
|
|
* gesture */
|
|
|
|
{
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
|
|
|
|
EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-07-07 07:41:03 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We report ABORT if lines length are NOT matching when fingers are up */
|
2012-05-28 09:56:56 -07:00
|
|
|
if ((longest_line_len - shortest_line_len) >
|
|
|
|
(elm_config_finger_size_get() * 2))
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
|
|
|
|
EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-07-07 07:41:03 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* We consider FLICK as a fast line.ABORT if take too long to finish */
|
|
|
|
if ((g_type == ELM_GESTURE_N_FLICKS) && ((tm_end - tm_start) >
|
|
|
|
sd->flick_time_limit_ms))
|
|
|
|
{
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
|
|
|
|
EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-07-07 07:41:03 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (event_type)
|
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
if ((started) && (started == ended))
|
|
|
|
{
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_END,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
|
|
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
|
|
|
case EVAS_CALLBACK_MULTI_MOVE:
|
2012-05-28 09:56:56 -07:00
|
|
|
if (started)
|
|
|
|
{
|
|
|
|
/* For continues gesture */
|
|
|
|
if (sd->glayer_continues_enable && (started == ended))
|
|
|
|
{
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_END,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* When continues, may START on MOVE event too */
|
|
|
|
Elm_Gesture_State s = ELM_GESTURE_STATE_MOVE;
|
|
|
|
|
|
|
|
/* This happens when: on n > 1 lines then one finger up */
|
|
|
|
/* caused abort, then put finger down. */
|
|
|
|
/* This will stop line from starting again. */
|
|
|
|
/* Number of lines, MUST match touched-device in list */
|
|
|
|
if ((!sd->glayer_continues_enable) &&
|
|
|
|
(eina_list_count(st->list) <
|
|
|
|
eina_list_count(sd->touched)))
|
|
|
|
s = ELM_GESTURE_STATE_ABORT;
|
|
|
|
|
|
|
|
if (gesture->state == ELM_GESTURE_STATE_UNDEFINED)
|
|
|
|
s = ELM_GESTURE_STATE_START;
|
|
|
|
|
|
|
|
ev_flag = _state_set(gesture, s, &st->info, EINA_TRUE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
default:
|
2012-05-28 09:56:56 -07:00
|
|
|
return; /* Unhandeld event type */
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function is used to check if rotation gesture started.
|
|
|
|
* @param st Contains current rotation values from user input.
|
|
|
|
* @return TRUE/FALSE if we need to set rotation START.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Eina_Bool
|
2012-05-28 09:56:56 -07:00
|
|
|
_on_rotation_broke_tolerance(Rotate_Type *st)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
if (st->info.base_angle < 0)
|
2012-05-28 09:56:56 -07:00
|
|
|
return EINA_FALSE; /* Angle has to be computed first */
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2011-07-17 23:24:34 -07:00
|
|
|
if (st->rotate_angular_tolerance < 0)
|
2011-07-07 07:41:03 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
double low = st->info.base_angle - st->rotate_angular_tolerance;
|
2011-07-17 23:24:34 -07:00
|
|
|
double high = st->info.base_angle + st->rotate_angular_tolerance;
|
2011-07-07 07:41:03 -07:00
|
|
|
double t = st->info.angle;
|
|
|
|
|
|
|
|
if (low < 0)
|
|
|
|
{
|
2011-12-21 00:48:08 -08:00
|
|
|
low += 180;
|
|
|
|
high += 180;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2011-12-21 00:48:08 -08:00
|
|
|
if (t < 180)
|
|
|
|
t += 180;
|
2011-07-07 07:41:03 -07:00
|
|
|
else
|
2011-12-21 00:48:08 -08:00
|
|
|
t -= 180;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2011-12-21 00:48:08 -08:00
|
|
|
if (high > 360)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2011-12-21 00:48:08 -08:00
|
|
|
low -= 180;
|
|
|
|
high -= 180;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2011-12-21 00:48:08 -08:00
|
|
|
if (t < 180)
|
|
|
|
t += 180;
|
2011-07-07 07:41:03 -07:00
|
|
|
else
|
2011-12-21 00:48:08 -08:00
|
|
|
t -= 180;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if ((t < low) || (t > high)) /* This marks that roation action has
|
|
|
|
* started */
|
|
|
|
{
|
2011-07-17 23:24:34 -07:00
|
|
|
st->rotate_angular_tolerance = ELM_GESTURE_NEGATIVE_ANGLE;
|
2011-07-07 07:41:03 -07:00
|
|
|
st->info.base_angle = st->info.angle; /* Avoid jump in angle value */
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function is used for computing the gap between fingers.
|
|
|
|
* It returns the length and center point between fingers.
|
|
|
|
*
|
|
|
|
* @param x1 first finger x location.
|
|
|
|
* @param y1 first finger y location.
|
|
|
|
* @param x2 second finger x location.
|
|
|
|
* @param y2 second finger y location.
|
|
|
|
* @param x Gets center point x cord (output)
|
|
|
|
* @param y Gets center point y cord (output)
|
|
|
|
*
|
|
|
|
* @return length of the line between (x1,y1), (x2,y2) in pixels.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static Evas_Coord
|
2012-05-28 09:56:56 -07:00
|
|
|
_finger_gap_length_get(Evas_Coord xx1,
|
|
|
|
Evas_Coord yy1,
|
|
|
|
Evas_Coord xx2,
|
|
|
|
Evas_Coord yy2,
|
|
|
|
Evas_Coord *x,
|
|
|
|
Evas_Coord *y)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
double a, b, xx, yy, gap;
|
2012-03-07 00:19:55 -08:00
|
|
|
xx = fabs(xx2 - xx1);
|
|
|
|
yy = fabs(yy2 - yy1);
|
|
|
|
gap = sqrt((xx * xx) + (yy * yy));
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
/* START - Compute zoom center point */
|
|
|
|
/* The triangle defined as follows:
|
|
|
|
* B
|
|
|
|
* / |
|
|
|
|
* / |
|
|
|
|
* gap / | a
|
|
|
|
* / |
|
|
|
|
* A-----C
|
|
|
|
* b
|
|
|
|
* http://en.wikipedia.org/wiki/Trigonometric_functions
|
|
|
|
*************************************/
|
2012-03-07 00:19:55 -08:00
|
|
|
if (((int)xx) && ((int)yy))
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
|
|
|
double A = atan((yy / xx));
|
2012-05-28 09:56:56 -07:00
|
|
|
a = (Evas_Coord)((gap / 2) * sin(A));
|
|
|
|
b = (Evas_Coord)((gap / 2) * cos(A));
|
|
|
|
*x = (Evas_Coord)((xx2 > xx1) ? (xx1 + b) : (xx2 + b));
|
|
|
|
*y = (Evas_Coord)((yy2 > yy1) ? (yy1 + a) : (yy2 + a));
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
if ((int)xx) /* horiz line, take half width */
|
|
|
|
{
|
|
|
|
*x = (Evas_Coord)((xx1 + xx2) / 2);
|
|
|
|
*y = (Evas_Coord)(yy1);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if ((int)yy) /* vert line, take half width */
|
|
|
|
{
|
|
|
|
*x = (Evas_Coord)(xx1);
|
|
|
|
*y = (Evas_Coord)((yy1 + yy2) / 2);
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* END - Compute zoom center point */
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return (Evas_Coord)gap;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2011-12-21 00:47:44 -08:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function is used for computing zoom value.
|
|
|
|
*
|
|
|
|
* @param st Pointer to zoom data based on user input.
|
|
|
|
* @param tm_end Recent input event timestamp.
|
|
|
|
* @param zoom_val Current computed zoom value.
|
|
|
|
*
|
|
|
|
* @return zoom momentum
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static double
|
2012-05-28 09:56:56 -07:00
|
|
|
_zoom_momentum_get(Zoom_Type *st,
|
|
|
|
unsigned int tm_end,
|
|
|
|
double zoom_val)
|
2011-12-21 00:47:44 -08:00
|
|
|
{
|
|
|
|
unsigned int tm_total;
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!st->m_st_tm) /* Init, and we don't start computing momentum yet */
|
|
|
|
{
|
2011-12-21 00:48:16 -08:00
|
|
|
st->m_st_tm = st->m_prev_tm = tm_end;
|
|
|
|
st->m_base = zoom_val;
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
2011-12-21 00:48:25 -08:00
|
|
|
if ((tm_end - ELM_GESTURE_MOMENTUM_DELAY) < st->m_st_tm)
|
2012-05-28 09:56:56 -07:00
|
|
|
return 0.0; /* we don't start to compute momentum yet */
|
2011-12-21 00:47:44 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (st->dir) /* if direction was already defined, check if changed */
|
|
|
|
{
|
2011-12-21 00:47:44 -08:00
|
|
|
if (((st->dir < 0) && (zoom_val > st->info.zoom)) ||
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Direction changed, reset momentum */
|
|
|
|
((st->dir > 0) && (zoom_val < st->info.zoom)))
|
|
|
|
{
|
2011-12-21 00:47:44 -08:00
|
|
|
st->m_st_tm = 0;
|
|
|
|
st->dir = (-st->dir);
|
2011-12-21 00:48:16 -08:00
|
|
|
return 0.0;
|
2011-12-21 00:47:44 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
st->dir = (zoom_val > st->info.zoom) ? 1 : -1; /* init */
|
|
|
|
|
2011-12-21 00:48:16 -08:00
|
|
|
if ((tm_end - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->m_prev_tm)
|
2011-12-21 00:47:44 -08:00
|
|
|
{
|
2011-12-21 00:48:16 -08:00
|
|
|
st->m_st_tm = 0; /* Rest momentum when waiting too long */
|
|
|
|
return 0.0;
|
2011-12-21 00:47:44 -08:00
|
|
|
}
|
|
|
|
|
2011-12-21 00:48:16 -08:00
|
|
|
st->m_prev_tm = tm_end;
|
2011-12-21 00:47:44 -08:00
|
|
|
tm_total = tm_end - st->m_st_tm;
|
|
|
|
|
|
|
|
if (tm_total)
|
2012-05-28 09:56:56 -07:00
|
|
|
return ((zoom_val - st->m_base) * 1000) / tm_total;
|
2011-12-21 00:47:44 -08:00
|
|
|
else
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function is used for computing zoom value.
|
|
|
|
*
|
|
|
|
* @param st Pointer to zoom data based on user input.
|
|
|
|
* @param x1 first finger x location.
|
|
|
|
* @param y1 first finger y location.
|
|
|
|
* @param x2 second finger x location.
|
|
|
|
* @param y2 second finger y location.
|
|
|
|
* @param factor zoom-factor, used to determine how fast zoom works.
|
|
|
|
*
|
|
|
|
* @return zoom value, when 1.0 means no zoom, 0.5 half size...
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
2011-07-17 23:24:29 -07:00
|
|
|
static double
|
2012-05-28 09:56:56 -07:00
|
|
|
_zoom_compute(Zoom_Type *st,
|
|
|
|
Evas_Coord xx1,
|
|
|
|
Evas_Coord yy1,
|
|
|
|
Evas_Coord xx2,
|
|
|
|
Evas_Coord yy2,
|
|
|
|
double zoom_finger_factor)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2011-07-17 23:24:29 -07:00
|
|
|
double rt = 1.0;
|
2011-12-21 00:47:44 -08:00
|
|
|
unsigned int tm_end = (st->zoom_mv.timestamp > st->zoom_mv1.timestamp) ?
|
2012-03-07 00:21:20 -08:00
|
|
|
st->zoom_mv.timestamp : st->zoom_mv1.timestamp;
|
2011-12-21 00:47:44 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
Evas_Coord diam = _finger_gap_length_get(xx1, yy1, xx2, yy2,
|
|
|
|
&st->info.x, &st->info.y);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
st->info.radius = diam / 2;
|
|
|
|
|
|
|
|
if (!st->zoom_base)
|
|
|
|
{
|
|
|
|
st->zoom_base = diam;
|
|
|
|
return st->info.zoom;
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (st->zoom_distance_tolerance) /* zoom tolerance <> ZERO, means
|
|
|
|
* zoom action NOT started yet */
|
|
|
|
{
|
|
|
|
/* avoid jump with zoom value when break tolerance */
|
2011-07-17 23:24:34 -07:00
|
|
|
if (diam < (st->zoom_base - st->zoom_distance_tolerance))
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
2011-07-17 23:24:34 -07:00
|
|
|
st->zoom_base -= st->zoom_distance_tolerance;
|
|
|
|
st->zoom_distance_tolerance = 0;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* avoid jump with zoom value when break tolerance */
|
2011-07-17 23:24:34 -07:00
|
|
|
if (diam > (st->zoom_base + st->zoom_distance_tolerance))
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
2011-07-17 23:24:34 -07:00
|
|
|
st->zoom_base += st->zoom_distance_tolerance;
|
|
|
|
st->zoom_distance_tolerance = 0;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return rt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We use factor only on the difference between gap-base */
|
|
|
|
/* if gap=120, base=100, we get ((120-100)/100)=0.2*factor */
|
2012-05-28 09:56:56 -07:00
|
|
|
rt = ((1.0) + ((((float)diam - (float)st->zoom_base) /
|
|
|
|
(float)st->zoom_base) * zoom_finger_factor));
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2011-12-21 00:47:44 -08:00
|
|
|
/* Momentum: zoom per second: */
|
|
|
|
st->info.momentum = _zoom_momentum_get(st, tm_end, rt);
|
|
|
|
|
2011-07-07 07:41:03 -07:00
|
|
|
return rt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function handles zoom with mouse wheel.
|
|
|
|
* thats a combination of wheel + CTRL key.
|
|
|
|
* @param obj The gesture-layer object.
|
|
|
|
* @param event_info Original input event pointer.
|
|
|
|
* @param event_type Type of original input event.
|
|
|
|
* @param g_type what Gesture we are testing.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_zoom_with_wheel_test(Evas_Object *obj,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
|
|
|
|
|
|
|
if (!sd->gesture[g_type]) return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
Gesture_Info *gesture_zoom = sd->gesture[g_type];
|
2011-07-07 07:41:03 -07:00
|
|
|
Zoom_Type *st = gesture_zoom->data;
|
|
|
|
Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!st) /* Allocated once on first time, used for zoom intermediate data */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
st = calloc(1, sizeof(Zoom_Type));
|
|
|
|
gesture_zoom->data = st;
|
|
|
|
_zoom_test_reset(gesture_zoom);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (event_type)
|
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_KEY_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
|
|
|
Evas_Event_Key_Up *p = event_info;
|
|
|
|
if ((!strcmp(p->keyname, "Control_L")) ||
|
|
|
|
/* Test if we ended a zoom gesture when releasing CTRL */
|
|
|
|
(!strcmp(p->keyname, "Control_R")))
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
if ((st->zoom_wheel) &&
|
|
|
|
((gesture_zoom->state == ELM_GESTURE_STATE_START) ||
|
|
|
|
/* User released CTRL after zooming */
|
|
|
|
(gesture_zoom->state == ELM_GESTURE_STATE_MOVE)))
|
|
|
|
{
|
|
|
|
st->info.momentum = _zoom_momentum_get
|
|
|
|
(st, p->timestamp, st->info.zoom);
|
|
|
|
|
|
|
|
ev_flag = _state_set
|
|
|
|
(gesture_zoom, ELM_GESTURE_STATE_END, &st->info,
|
|
|
|
EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
|
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
}
|
2012-05-28 09:56:56 -07:00
|
|
|
break;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
case EVAS_CALLBACK_MOUSE_WHEEL:
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
|
|
|
Eina_Bool force;
|
|
|
|
Elm_Gesture_State s;
|
|
|
|
if (!evas_key_modifier_is_set(
|
|
|
|
((Evas_Event_Mouse_Wheel *)event_info)->modifiers,
|
|
|
|
"Control")) /* if using wheel witout CTRL after starting zoom */
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
if ((st->zoom_wheel) &&
|
|
|
|
((gesture_zoom->state == ELM_GESTURE_STATE_START) ||
|
|
|
|
(gesture_zoom->state == ELM_GESTURE_STATE_MOVE)))
|
|
|
|
{
|
|
|
|
ev_flag = _state_set
|
|
|
|
(gesture_zoom, ELM_GESTURE_STATE_END, &st->info,
|
|
|
|
EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
else
|
2012-05-28 09:56:56 -07:00
|
|
|
return; /* Ignore mouse-wheel without control */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Using mouse wheel with CTRL for zoom */
|
|
|
|
/* (zoom_wheel == NULL) and (zoom_distance_tolerance == 0) we
|
|
|
|
* continue a zoom gesture */
|
|
|
|
if (st->zoom_wheel || (st->zoom_distance_tolerance == 0))
|
|
|
|
{
|
|
|
|
force = EINA_TRUE;
|
|
|
|
s = ELM_GESTURE_STATE_MOVE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ /* On first wheel event, report START */
|
|
|
|
Evas_Modifier_Mask mask = evas_key_modifier_mask_get(
|
|
|
|
evas_object_evas_get(sd->target), "Control");
|
|
|
|
force = EINA_FALSE;
|
|
|
|
s = ELM_GESTURE_STATE_START;
|
|
|
|
if (!evas_object_key_grab
|
|
|
|
(sd->target, "Control_L", mask, 0, EINA_FALSE))
|
|
|
|
ERR("Failed to Grabbed CTRL_L");
|
|
|
|
if (!evas_object_key_grab
|
|
|
|
(sd->target, "Control_R", mask, 0, EINA_FALSE))
|
|
|
|
ERR("Failed to Grabbed CTRL_R");
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st->zoom_distance_tolerance = 0; /* Cancel tolerance */
|
|
|
|
st->zoom_wheel = (Evas_Event_Mouse_Wheel *)event_info;
|
|
|
|
st->info.x = st->zoom_wheel->canvas.x;
|
|
|
|
st->info.y = st->zoom_wheel->canvas.y;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (st->zoom_wheel->z < 0) /* zoom in */
|
|
|
|
st->info.zoom += (sd->zoom_finger_factor * sd->zoom_wheel_factor);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (st->zoom_wheel->z > 0) /* zoom out */
|
|
|
|
st->info.zoom -= (sd->zoom_finger_factor * sd->zoom_wheel_factor);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (st->info.zoom < 0.0)
|
|
|
|
st->info.zoom = 0.0;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st->info.momentum = _zoom_momentum_get
|
|
|
|
(st, st->zoom_wheel->timestamp, st->info.zoom);
|
2011-12-21 00:47:44 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
ev_flag = _state_set(gesture_zoom, s, &st->info, force);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
break;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
default:
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function is used to test zoom gesture.
|
|
|
|
* user may combine zoom, rotation together.
|
|
|
|
* so its possible that both will be detected from input.
|
|
|
|
* (both are two-finger movement-oriented gestures)
|
|
|
|
*
|
|
|
|
* @param obj The gesture-layer object.
|
|
|
|
* @param event_info Pointer to recent input event.
|
|
|
|
* @param event_type Recent input event type.
|
|
|
|
* @param g_type what Gesture we are testing.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_zoom_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-17 08:31:34 -07:00
|
|
|
/* Test for wheel zoom. */
|
|
|
|
_zoom_with_wheel_test(obj, event_info, event_type, ELM_GESTURE_ZOOM);
|
|
|
|
|
|
|
|
if (!_elm_config->glayer_zoom_finger_enable)
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
2012-05-17 08:31:34 -07:00
|
|
|
|
2011-07-10 04:51:44 -07:00
|
|
|
if (!pe)
|
2011-07-07 07:41:03 -07:00
|
|
|
return;
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!sd->gesture[g_type]) return;
|
|
|
|
|
|
|
|
Gesture_Info *gesture_zoom = sd->gesture[g_type];
|
2011-07-07 07:41:03 -07:00
|
|
|
Zoom_Type *st = gesture_zoom->data;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!st) /* Allocated once on first time, used for zoom data */
|
|
|
|
{
|
2011-07-07 07:41:03 -07:00
|
|
|
st = calloc(1, sizeof(Zoom_Type));
|
|
|
|
gesture_zoom->data = st;
|
|
|
|
_zoom_test_reset(gesture_zoom);
|
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Start - new zoom testing, letting all fingers start */
|
|
|
|
Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
|
|
|
|
switch (event_type)
|
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
|
|
|
case EVAS_CALLBACK_MULTI_MOVE:
|
|
|
|
/* if non-continues mode and gesture NOT started, ignore MOVE */
|
|
|
|
if ((!sd->glayer_continues_enable) &&
|
|
|
|
(!st->zoom_st.timestamp))
|
|
|
|
return;
|
|
|
|
|
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
|
|
|
{ /* Here we take care of zoom-start and zoom move */
|
|
|
|
Eina_List *l;
|
|
|
|
Pointer_Event *p;
|
|
|
|
|
|
|
|
if (eina_list_count(sd->touched) > 2) /* Process zoom only
|
|
|
|
* when 2 fingers on
|
|
|
|
* surface */
|
|
|
|
{
|
|
|
|
ev_flag = _state_set
|
|
|
|
(gesture_zoom, ELM_GESTURE_STATE_ABORT, &st->info,
|
|
|
|
EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!st->zoom_st.timestamp) /* Now scan touched-devices list
|
|
|
|
* and find other finger */
|
|
|
|
{
|
2012-10-01 00:36:27 -07:00
|
|
|
EINA_LIST_FOREACH(sd->touched, l, p)
|
2012-05-28 09:56:56 -07:00
|
|
|
{ /* Device of other finger <> pe device */
|
|
|
|
if (p->device != pe->device)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!p) /* Single finger on touch */
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Record down fingers */
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
memcpy(&st->zoom_st, pe, sizeof(Pointer_Event));
|
|
|
|
memcpy(&st->zoom_st1, p, sizeof(Pointer_Event));
|
|
|
|
|
|
|
|
/* Set mv field as well to be ready for MOVE events */
|
|
|
|
memcpy(&st->zoom_mv, pe, sizeof(Pointer_Event));
|
|
|
|
memcpy(&st->zoom_mv1, p, sizeof(Pointer_Event));
|
|
|
|
|
|
|
|
/* Here we have zoom_st, zoom_st1 set, report START */
|
|
|
|
/* Set zoom-base after BOTH down events recorded */
|
|
|
|
/* Compute length of line between fingers zoom start */
|
|
|
|
st->info.zoom = 1.0;
|
|
|
|
st->zoom_base = _finger_gap_length_get
|
|
|
|
(st->zoom_st1.x, st->zoom_st1.y, st->zoom_st.x, st->zoom_st.y,
|
|
|
|
&st->info.x, &st->info.y);
|
|
|
|
|
|
|
|
st->info.radius = st->zoom_base / 2;
|
2011-10-10 08:47:34 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if ((gesture_zoom->state != ELM_GESTURE_STATE_START) &&
|
|
|
|
/* zoom started with mouse-wheel, don't report twice */
|
|
|
|
(gesture_zoom->state != ELM_GESTURE_STATE_MOVE))
|
|
|
|
{
|
|
|
|
ev_flag = _state_set
|
|
|
|
(gesture_zoom, ELM_GESTURE_STATE_START, &st->info,
|
|
|
|
EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return; /* Zoom started */
|
|
|
|
} /* End of ZOOM_START handling */
|
|
|
|
|
|
|
|
/* if we got here, we have (exacally) two fingers on surfce */
|
|
|
|
/* we also after START, report MOVE */
|
|
|
|
/* First detect which finger moved */
|
|
|
|
if (pe->device == st->zoom_mv.device)
|
|
|
|
memcpy(&st->zoom_mv, pe, sizeof(Pointer_Event));
|
|
|
|
else if (pe->device == st->zoom_mv1.device)
|
|
|
|
memcpy(&st->zoom_mv1, pe, sizeof(Pointer_Event));
|
|
|
|
|
|
|
|
/* Compute change in zoom as fingers move */
|
|
|
|
st->info.zoom = _zoom_compute(st,
|
|
|
|
st->zoom_mv.x, st->zoom_mv.y,
|
|
|
|
st->zoom_mv1.x, st->zoom_mv1.y,
|
|
|
|
sd->zoom_finger_factor);
|
|
|
|
|
|
|
|
if (!st->zoom_distance_tolerance) /* Zoom broke tolerance,
|
|
|
|
* report move */
|
|
|
|
{
|
|
|
|
double d = st->info.zoom - st->next_step;
|
|
|
|
if (d < 0.0)
|
|
|
|
d = (-d);
|
2011-10-10 08:47:34 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (d >= sd->zoom_step) /* Report move in steps */
|
|
|
|
{
|
|
|
|
st->next_step = st->info.zoom;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
ev_flag = _state_set(gesture_zoom,
|
|
|
|
ELM_GESTURE_STATE_MOVE,
|
|
|
|
&st->info, EINA_TRUE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
}
|
|
|
|
} /* End of ZOOM_MOVE handling */
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Reset timestamp of finger-up.This is used later
|
|
|
|
by _zoom_test_reset() to retain finger-down data */
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
if (((st->zoom_wheel) || (st->zoom_base)) &&
|
|
|
|
(st->zoom_distance_tolerance == 0))
|
|
|
|
{
|
|
|
|
ev_flag = _state_set(gesture_zoom, ELM_GESTURE_STATE_END,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* if we got here not a ZOOM */
|
|
|
|
/* Must be != undefined, if gesture started */
|
|
|
|
if (gesture_zoom->state != ELM_GESTURE_STATE_UNDEFINED)
|
|
|
|
{
|
|
|
|
ev_flag = _state_set
|
|
|
|
(gesture_zoom, ELM_GESTURE_STATE_ABORT, &st->info,
|
|
|
|
EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_zoom_test_reset(gesture_zoom);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
default:
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_rotate_properties_get(Rotate_Type *st,
|
|
|
|
Evas_Coord xx1,
|
|
|
|
Evas_Coord yy1,
|
|
|
|
Evas_Coord xx2,
|
|
|
|
Evas_Coord yy2,
|
2012-03-07 00:21:20 -08:00
|
|
|
double *angle)
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
|
|
|
/* FIXME: Fix momentum computation, it's wrong */
|
2011-12-21 00:47:47 -08:00
|
|
|
double prev_angle = *angle;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st->info.radius = _finger_gap_length_get(xx1, yy1, xx2, yy2,
|
|
|
|
&st->info.x, &st->info.y) / 2;
|
2012-03-28 02:02:22 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
*angle = _angle_get(xx1, yy1, xx2, yy2);
|
|
|
|
|
|
|
|
if (angle == &st->info.angle) /* Fingers are moving, compute momentum */
|
|
|
|
{
|
2011-12-21 00:47:47 -08:00
|
|
|
unsigned int tm_start =
|
2012-05-28 09:56:56 -07:00
|
|
|
(st->rotate_st.timestamp > st->rotate_st1.timestamp)
|
|
|
|
? st->rotate_st.timestamp : st->rotate_st1.timestamp;
|
2011-12-21 00:47:47 -08:00
|
|
|
unsigned int tm_end =
|
2012-05-28 09:56:56 -07:00
|
|
|
(st->rotate_mv.timestamp > st->rotate_mv1.timestamp)
|
|
|
|
? st->rotate_mv.timestamp : st->rotate_mv1.timestamp;
|
2011-12-21 00:47:47 -08:00
|
|
|
|
|
|
|
unsigned int tm_total = tm_end - tm_start;
|
2012-05-28 09:56:56 -07:00
|
|
|
if (tm_total) /* Momentum computed as:
|
|
|
|
accumulated roation angle (deg) divided by time */
|
|
|
|
{
|
|
|
|
double m = 0;
|
2011-12-21 00:48:08 -08:00
|
|
|
if (((prev_angle < 90) && ((*angle) > 270)) ||
|
2012-05-28 09:56:56 -07:00
|
|
|
/* We circle passing ZERO point */
|
|
|
|
((prev_angle > 270) && ((*angle) < 90)))
|
|
|
|
{
|
2011-12-21 00:47:50 -08:00
|
|
|
prev_angle = (*angle);
|
2011-12-21 00:47:47 -08:00
|
|
|
}
|
2011-12-21 00:48:16 -08:00
|
|
|
else m = prev_angle - (*angle);
|
2011-12-21 00:47:47 -08:00
|
|
|
|
|
|
|
st->accum_momentum += m;
|
|
|
|
|
|
|
|
if ((tm_end - st->prev_momentum_tm) < 100)
|
|
|
|
st->prev_momentum += m;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (fabs(st->prev_momentum) < 0.002)
|
|
|
|
st->accum_momentum = 0.0; /* reset momentum */
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
st->prev_momentum = 0.0; /* Start again */
|
2011-12-21 00:47:47 -08:00
|
|
|
}
|
|
|
|
|
2011-12-21 00:47:50 -08:00
|
|
|
st->prev_momentum_tm = tm_end;
|
2011-12-21 00:47:47 -08:00
|
|
|
st->info.momentum = (st->accum_momentum * 1000) / tm_total;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
st->info.momentum = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @internal
|
|
|
|
*
|
|
|
|
* This function is used to test rotation gesture.
|
|
|
|
* user may combine zoom, rotation together.
|
|
|
|
* so its possible that both will be detected from input.
|
|
|
|
* (both are two-finger movement-oriented gestures)
|
|
|
|
*
|
|
|
|
* @param obj The gesture-layer object.
|
|
|
|
* @param event_info Pointer to recent input event.
|
|
|
|
* @param event_type Recent input event type.
|
|
|
|
* @param g_type what Gesture we are testing.
|
|
|
|
*
|
|
|
|
* @ingroup Elm_Gesture_Layer
|
|
|
|
*/
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_rotate_test(Evas_Object *obj,
|
|
|
|
Pointer_Event *pe,
|
|
|
|
void *event_info,
|
|
|
|
Evas_Callback_Type event_type,
|
|
|
|
Elm_Gesture_Type g_type)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-17 08:31:34 -07:00
|
|
|
if (!_elm_config->glayer_rotate_finger_enable)
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
2012-05-17 08:31:34 -07:00
|
|
|
|
2011-07-10 04:51:44 -07:00
|
|
|
if (!pe)
|
2011-07-07 07:41:03 -07:00
|
|
|
return;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
|
|
|
|
|
|
|
if (!sd->gesture[g_type]) return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
Gesture_Info *gesture = sd->gesture[g_type];
|
2011-11-29 01:20:31 -08:00
|
|
|
Rotate_Type *st;
|
2011-07-07 07:41:03 -07:00
|
|
|
if (gesture)
|
2012-05-28 09:56:56 -07:00
|
|
|
{
|
|
|
|
st = gesture->data;
|
|
|
|
if (!st) /* Allocated once on first time */
|
|
|
|
{
|
|
|
|
st = calloc(1, sizeof(Rotate_Type));
|
|
|
|
gesture->data = st;
|
|
|
|
_rotate_test_reset(gesture);
|
|
|
|
}
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
|
|
|
|
switch (event_type)
|
|
|
|
{
|
|
|
|
case EVAS_CALLBACK_MOUSE_MOVE:
|
|
|
|
case EVAS_CALLBACK_MULTI_MOVE:
|
2012-05-28 09:56:56 -07:00
|
|
|
/* if non-continues mode and gesture NOT started, ignore MOVE */
|
|
|
|
if ((!sd->glayer_continues_enable) &&
|
|
|
|
(!st->rotate_st.timestamp))
|
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2011-10-10 08:47:34 -07:00
|
|
|
case EVAS_CALLBACK_MOUSE_DOWN:
|
|
|
|
case EVAS_CALLBACK_MULTI_DOWN:
|
2012-05-28 09:56:56 -07:00
|
|
|
{ /* Here we take care of rotate-start and rotate move */
|
|
|
|
Eina_List *l;
|
|
|
|
Pointer_Event *p;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (eina_list_count(sd->touched) > 2) /* Process rotate only
|
|
|
|
* when 2 fingers on
|
|
|
|
* surface */
|
|
|
|
{
|
|
|
|
ev_flag = _state_set
|
|
|
|
(gesture, ELM_GESTURE_STATE_ABORT, &st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!st->rotate_st.timestamp) /* Now scan touched-devices list
|
|
|
|
* and find other finger */
|
|
|
|
{
|
2012-10-01 00:36:27 -07:00
|
|
|
EINA_LIST_FOREACH(sd->touched, l, p)
|
2012-05-28 09:56:56 -07:00
|
|
|
{ /* Device of other finger <> pe device */
|
|
|
|
if (p->device != pe->device)
|
|
|
|
break;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!p)
|
|
|
|
return; /* Single finger on touch */
|
|
|
|
|
|
|
|
/* Record down fingers */
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
memcpy(&st->rotate_st, pe, sizeof(Pointer_Event));
|
|
|
|
memcpy(&st->rotate_st1, p, sizeof(Pointer_Event));
|
|
|
|
|
|
|
|
/* Set mv field as well to be ready for MOVE events */
|
|
|
|
memcpy(&st->rotate_mv, pe, sizeof(Pointer_Event));
|
|
|
|
memcpy(&st->rotate_mv1, p, sizeof(Pointer_Event));
|
|
|
|
|
|
|
|
/* Here we have rotate_st, rotate_st1 set, report START */
|
|
|
|
/* Set rotate-base after BOTH down events recorded */
|
|
|
|
/* Compute length of line between fingers rotate start */
|
|
|
|
_rotate_properties_get(st,
|
|
|
|
st->rotate_st.x, st->rotate_st.y,
|
|
|
|
st->rotate_st1.x, st->rotate_st1.y,
|
|
|
|
&st->info.base_angle);
|
|
|
|
|
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_START,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
|
|
|
|
return; /* Rotate started */
|
|
|
|
} /* End of ROTATE_START handling */
|
|
|
|
|
|
|
|
/* if we got here, we have (exacally) two fingers on surfce */
|
|
|
|
/* we also after START, report MOVE */
|
|
|
|
/* First detect which finger moved */
|
|
|
|
if (pe->device == st->rotate_mv.device)
|
|
|
|
memcpy(&st->rotate_mv, pe, sizeof(Pointer_Event));
|
|
|
|
else if (pe->device == st->rotate_mv1.device)
|
|
|
|
memcpy(&st->rotate_mv1, pe, sizeof(Pointer_Event));
|
|
|
|
|
|
|
|
/* Compute change in rotate as fingers move */
|
|
|
|
_rotate_properties_get(st,
|
|
|
|
st->rotate_mv.x, st->rotate_mv.y,
|
|
|
|
st->rotate_mv1.x, st->rotate_mv1.y,
|
|
|
|
&st->info.angle);
|
|
|
|
|
|
|
|
if (_on_rotation_broke_tolerance(st)) /* Rotation broke
|
|
|
|
* tolerance, report
|
|
|
|
* move */
|
|
|
|
{
|
|
|
|
double d = st->info.angle - st->next_step;
|
|
|
|
if (d < 0)
|
|
|
|
d = (-d);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (d >= sd->rotate_step) /* Report move in steps */
|
|
|
|
{
|
|
|
|
st->next_step = st->info.angle;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
ev_flag = _state_set
|
|
|
|
(gesture, ELM_GESTURE_STATE_MOVE, &st->info, EINA_TRUE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
}
|
|
|
|
} /* End of ROTATE_MOVE handling */
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
case EVAS_CALLBACK_MOUSE_UP:
|
|
|
|
case EVAS_CALLBACK_MULTI_UP:
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
|
|
|
/* Reset timestamp of finger-up.This is used later
|
|
|
|
by rotate_test_reset() to retain finger-down data */
|
|
|
|
if (st->rotate_angular_tolerance < 0)
|
2012-05-20 07:56:26 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_END,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2011-09-08 03:10:30 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return;
|
2012-05-20 07:56:26 -07:00
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* Must be != undefined, if gesture started */
|
|
|
|
if (gesture->state != ELM_GESTURE_STATE_UNDEFINED)
|
2012-05-17 08:31:34 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ev_flag = _state_set(gesture, ELM_GESTURE_STATE_ABORT,
|
|
|
|
&st->info, EINA_FALSE);
|
|
|
|
_event_consume(sd, event_info, event_type, ev_flag);
|
2012-05-17 08:31:34 -07:00
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_rotate_test_reset(gesture);
|
|
|
|
return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
default:
|
|
|
|
return;
|
2011-07-10 04:51:40 -07:00
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_elm_gesture_layer_smart_disable(Evas_Object *obj)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
if (elm_widget_disabled_get(obj))
|
|
|
|
_callbacks_unregister(obj);
|
|
|
|
else
|
|
|
|
_callbacks_register(obj);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return EINA_TRUE;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_elm_gesture_layer_smart_add(Evas_Object *obj)
|
|
|
|
{
|
|
|
|
EVAS_SMART_DATA_ALLOC(obj, Elm_Gesture_Layer_Smart_Data);
|
|
|
|
|
|
|
|
_elm_gesture_layer_parent_sc->base.add(obj);
|
|
|
|
|
|
|
|
priv->target = NULL;
|
|
|
|
priv->line_min_length =
|
|
|
|
_elm_config->glayer_line_min_length * elm_config_finger_size_get();
|
|
|
|
priv->zoom_distance_tolerance = _elm_config->glayer_zoom_distance_tolerance
|
|
|
|
* elm_config_finger_size_get();
|
|
|
|
priv->line_distance_tolerance = _elm_config->glayer_line_distance_tolerance
|
|
|
|
* elm_config_finger_size_get();
|
|
|
|
priv->zoom_finger_factor = _elm_config->glayer_zoom_finger_factor;
|
|
|
|
/* mouse wheel zoom steps */
|
|
|
|
priv->zoom_wheel_factor = _elm_config->glayer_zoom_wheel_factor;
|
|
|
|
priv->rotate_angular_tolerance =
|
|
|
|
_elm_config->glayer_rotate_angular_tolerance;
|
|
|
|
priv->line_angular_tolerance = _elm_config->glayer_line_angular_tolerance;
|
|
|
|
priv->flick_time_limit_ms = _elm_config->glayer_flick_time_limit_ms;
|
|
|
|
priv->long_tap_start_timeout = _elm_config->glayer_long_tap_start_timeout;
|
|
|
|
priv->repeat_events = EINA_TRUE;
|
|
|
|
priv->glayer_continues_enable = _elm_config->glayer_continues_enable;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
/* FIXME: Hack to get around old configs - if too small, enlarge. */
|
|
|
|
if (_elm_config->glayer_double_tap_timeout < 0.00001)
|
|
|
|
_elm_config->glayer_double_tap_timeout = 0.25;
|
|
|
|
|
|
|
|
memset(priv->gesture, 0, sizeof(priv->gesture));
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_elm_gesture_layer_smart_del(Evas_Object *obj)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
Pointer_Event *data;
|
|
|
|
int i;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_event_history_clear(obj);
|
|
|
|
eina_list_free(sd->pending);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
EINA_LIST_FREE (sd->touched, data)
|
|
|
|
free(data);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!elm_widget_disabled_get(obj))
|
|
|
|
_callbacks_unregister(obj);
|
|
|
|
|
|
|
|
/* Free all gestures internal data structures */
|
|
|
|
for (i = 0; i < ELM_GESTURE_LAST; i++)
|
|
|
|
if (sd->gesture[i])
|
|
|
|
{
|
|
|
|
if (sd->gesture[i]->data)
|
|
|
|
free(sd->gesture[i]->data);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
free(sd->gesture[i]);
|
|
|
|
}
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_elm_gesture_layer_parent_sc->base.del(obj); /* handles freeing sd */
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-05-28 09:56:56 -07:00
|
|
|
_elm_gesture_layer_smart_set_user(Elm_Widget_Smart_Class *sc)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
sc->base.add = _elm_gesture_layer_smart_add;
|
|
|
|
sc->base.del = _elm_gesture_layer_smart_del;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
sc->disable = _elm_gesture_layer_smart_disable;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
EAPI Evas_Object *
|
|
|
|
elm_gesture_layer_add(Evas_Object *parent)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
Evas_Object *obj;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-07-18 14:03:39 -07:00
|
|
|
obj = elm_widget_add(_elm_gesture_layer_smart_class_new(), parent);
|
|
|
|
if (!obj) return NULL;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!elm_widget_sub_object_add(parent, obj))
|
|
|
|
ERR("could not add %p as sub object of %p", obj, parent);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return obj;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
2012-02-24 04:21:22 -08:00
|
|
|
elm_gesture_layer_hold_events_get(const Evas_Object *obj)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_CHECK(obj) EINA_FALSE;
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2012-02-24 02:42:53 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return !sd->repeat_events;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-05-28 09:56:56 -07:00
|
|
|
elm_gesture_layer_hold_events_set(Evas_Object *obj,
|
|
|
|
Eina_Bool hold_events)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_CHECK(obj);
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
sd->repeat_events = !(!!hold_events);
|
2012-02-24 04:21:22 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
elm_gesture_layer_zoom_step_get(const Evas_Object *obj)
|
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_CHECK(obj) 0;
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2012-02-24 04:21:22 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return sd->zoom_step;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-05-28 09:56:56 -07:00
|
|
|
elm_gesture_layer_zoom_step_set(Evas_Object *obj,
|
|
|
|
double step)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_CHECK(obj);
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-02-24 04:21:22 -08:00
|
|
|
if (step < 0) return;
|
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
sd->zoom_step = step;
|
2012-02-24 04:21:22 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
|
|
|
elm_gesture_layer_rotate_step_get(const Evas_Object *obj)
|
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_CHECK(obj) 0;
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2012-02-24 04:21:22 -08:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
return sd->rotate_step;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-05-28 09:56:56 -07:00
|
|
|
elm_gesture_layer_rotate_step_set(Evas_Object *obj,
|
|
|
|
double step)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_CHECK(obj);
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-02-24 04:21:22 -08:00
|
|
|
if (step < 0) return;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
sd->rotate_step = step;
|
2011-07-07 07:41:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
2012-05-28 09:56:56 -07:00
|
|
|
elm_gesture_layer_attach(Evas_Object *obj,
|
|
|
|
Evas_Object *target)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_CHECK(obj) EINA_FALSE;
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-02-24 04:21:22 -08:00
|
|
|
if (!target) return EINA_FALSE;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
|
|
|
/* if was attached before, unregister callbacks first */
|
2012-05-28 09:56:56 -07:00
|
|
|
if (sd->target)
|
|
|
|
_callbacks_unregister(obj);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
sd->target = target;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
_callbacks_register(obj);
|
2011-07-07 07:41:03 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-05-28 09:56:56 -07:00
|
|
|
elm_gesture_layer_cb_set(Evas_Object *obj,
|
|
|
|
Elm_Gesture_Type idx,
|
|
|
|
Elm_Gesture_State cb_type,
|
|
|
|
Elm_Gesture_Event_Cb cb,
|
|
|
|
void *data)
|
2011-07-07 07:41:03 -07:00
|
|
|
{
|
2011-08-05 16:13:16 -07:00
|
|
|
Gesture_Info *p;
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
ELM_GESTURE_LAYER_CHECK(obj);
|
|
|
|
ELM_GESTURE_LAYER_DATA_GET(obj, sd);
|
2011-07-07 07:41:03 -07:00
|
|
|
|
2012-05-28 09:56:56 -07:00
|
|
|
if (!sd->gesture[idx])
|
|
|
|
sd->gesture[idx] = calloc(1, sizeof(Gesture_Info));
|
|
|
|
if (!sd->gesture[idx]) return;
|
|
|
|
|
|
|
|
p = sd->gesture[idx];
|
2011-07-07 07:41:03 -07:00
|
|
|
p->obj = obj;
|
|
|
|
p->g_type = idx;
|
|
|
|
p->fn[cb_type].cb = cb;
|
|
|
|
p->fn[cb_type].user_data = data;
|
|
|
|
p->state = ELM_GESTURE_STATE_UNDEFINED;
|
|
|
|
SET_TEST_BIT(p);
|
|
|
|
}
|