Compare commits

...

34 Commits

Author SHA1 Message Date
Mike Blumenkrantz 9d03062ce4 efl/gesture: remove 'gesture' member from recognizer data struct
Summary:
this was never used

ref T8503

Depends on D11177

Reviewers: CHAN, bu5hm4n, segfaultxavi

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Maniphest Tasks: T8503

Differential Revision: https://phab.enlightenment.org/D11178
2020-01-27 11:22:33 +01:00
Mike Blumenkrantz bf36c03a7a efl/gesture: remove 'manager' member from recognizer data struct
this can be fetched using efl_provider_find from the recognizer

ref T8503

Differential Revision: https://phab.enlightenment.org/D11177
2020-01-24 14:22:29 -05:00
Mike Blumenkrantz 37d48f4870 efl/gesture: remove 'config' property from recognizers
this is a manager functionality, and recognizers are always child objects of
managers

ref T8503

Differential Revision: https://phab.enlightenment.org/D11176
2020-01-24 14:22:21 -05:00
Mike Blumenkrantz 30668b44a2 efl/gesture: expose 'continues' as a public property for recognizers
we still access this using private data in the in-tree recognizers, but
now it's also accessible normally to custom recognizers

ref T8503

Differential Revision: https://phab.enlightenment.org/D11175
2020-01-24 14:22:14 -05:00
Mike Blumenkrantz ed228d2495 efl/gesture: add an event to notify when a config value has been changed
recognizers should be storing config values internally to avoid overhead
of multiple eo/hash lookups on every event

Differential Revision: https://phab.enlightenment.org/D11174
2020-01-24 14:22:08 -05:00
Mike Blumenkrantz cf7c1b22f9 efl/gesture: move finger_size into private structs of recognizers
we must write these recognizers using publicly available apis to ensure
that we don't accidentally start using private struct data

this requires a lot of changes to properly manage the config value for finger
size and update the recognizer data when changed (which external recognizers
will need to monitor an event to achieve) and then also to change some
recognizers so they don't use memset and unset the finger_size value

ref TT8503

Differential Revision: https://phab.enlightenment.org/D11173
2020-01-24 14:17:53 -05:00
Mike Blumenkrantz 08fad93ffe tests/gesture: add zoom and pinch tests
basic tests verifying completion of the gestures

Differential Revision: https://phab.enlightenment.org/D11170
2020-01-23 15:26:34 -05:00
Mike Blumenkrantz a77b635327 efl/gesture: discard non-press events for all touch points if unseen previously
not sure why this was restricted to first touch point previously, but the logic
applies to all points as we don't want to be tracking input for a touch we
haven't gotten a down for

Differential Revision: https://phab.enlightenment.org/D11169
2020-01-23 15:26:25 -05:00
Mike Blumenkrantz 0ac5244176 efl/gesture: add 'pressed' state info for touch data
since we retain touch info for the duration of a touch sequence, including
after a touch point has been unpressed, it's necessary to track the current
state of each point and then use that to accurately determine the number of
touches active

Differential Revision: https://phab.enlightenment.org/D11168
2020-01-23 15:26:17 -05:00
Mike Blumenkrantz 941a12487c efl/gesture: correctly reset zoom gesture recognizer data on >2 finger touch
canceling without a proper reset breaks the recognizer for successive events

Differential Revision: https://phab.enlightenment.org/D11167
2020-01-23 15:26:10 -05:00
Mike Blumenkrantz 2aa110a191 tests/elm: add util function for doing pinch motions
simple function which takes start points and vectors for 2 touches

Differential Revision: https://phab.enlightenment.org/D11166
2020-01-23 15:26:01 -05:00
Mike Blumenkrantz 981c3fbad0 efl/gesture: more accurately handle flick/momentum recognition with multi-touch
if we have one of these gestures where we are flicking/momentuming with multiple
touch points, we want to permit this so long as the touch points are moving vaguely
in the same direction, e.g., press -> swipe with 2 fingers

with this, we now cancel these gestures with multi-touch active if we detect motion
with subsequent touch events that doesn't match the vector of the "active" press
for which we are monitoring events

Differential Revision: https://phab.enlightenment.org/D11165
2020-01-23 15:25:53 -05:00
Mike Blumenkrantz 9915b34c46 efl/gesture: break out _direction_get() into helper function
this is useful in multiple places, no functional changes

Differential Revision: https://phab.enlightenment.org/D11164
2020-01-23 15:25:45 -05:00
Mike Blumenkrantz 6efbd83536 evas/events: fix multi-touch object targeting on touch down events
a touch press is both a touch and a move event, which means the canvas must
update its list of target objects on the first touch press to avoid using the
wrong objects when processing events

@fix

Differential Revision: https://phab.enlightenment.org/D11163
2020-01-23 15:25:36 -05:00
Mike Blumenkrantz 1671b4573d efl/gesture: correct config value name for glayer_double_tap_timeout
typo--

Differential Revision: https://phab.enlightenment.org/D11155
2020-01-23 15:25:27 -05:00
Mike Blumenkrantz dd62a0d0d1 tests/gesture: add extra event callback to verify event multiplication is fixed
Differential Revision: https://phab.enlightenment.org/D11145
2020-01-23 15:25:20 -05:00
Mike Blumenkrantz fefeeaf227 efl/gesture: redo (and make stupider) hash usage in gesture manager
this rewrites the gesture event dispatcher to use a hash of hashes for
tracking which events are being watched on a given object to avoid:
* dispatching n gesture events per object to each callback, where n is the
  number of gesture callbacks for any given type
* removing all gesture callbacks when only one callback is removed

this is not smart code. it should be improved at some time, but that time
is not now.

Differential Revision: https://phab.enlightenment.org/D11144
2020-01-23 15:25:14 -05:00
Mike Blumenkrantz b884e76c7f efl/gesture: add touch_count property for gesture event info
this allows us to provide the number of touch points active in any gesture
so we can detect e.g., double-tap with two fingers

Differential Revision: https://phab.enlightenment.org/D11126
2020-01-23 15:25:08 -05:00
Mike Blumenkrantz 41b4373755 tests/gesture: add gesture tests for basic multi-touch tap events
Differential Revision: https://phab.enlightenment.org/D11090
2020-01-23 15:25:01 -05:00
Mike Blumenkrantz 50379c00ff tests/elm: add util functions for doing multi-touch events
Differential Revision: https://phab.enlightenment.org/D11089
2020-01-23 15:24:54 -05:00
Mike Blumenkrantz 59f4944df5 efl/gesture: fix zoom to ignore single press events and not crash
zoom requires two fingers for a pinch, so skip the first press

Differential Revision: https://phab.enlightenment.org/D11088
2020-01-23 15:24:48 -05:00
Mike Blumenkrantz 8870ca45e2 efl/gesture: restrict flick and momentum gestures to original touch point
if multiple fingers are pressed down, filter and use only the first finger
to make gesture recognizing more accurate

this may change later once tests develop

Differential Revision: https://phab.enlightenment.org/D11087
2020-01-23 15:24:42 -05:00
Mike Blumenkrantz 5741ed6d0a efl/gesture: handle multi-touch press for tap gestures
any time multiple fingers are pressed down at the same time, we should
treat this as a single gesture like if only one finger was pressed

Differential Revision: https://phab.enlightenment.org/D11086
2020-01-23 15:24:36 -05:00
Mike Blumenkrantz 07b1e4c201 efl/gesture: move Point_Data to eo and add methods to fetch it for recognizers
this lets gesture framework track two touch points in order to distinguish between
successive presses and e.g., treat a simultaneous two finger tap as a single tap
gesture rather than two

it also simplifies some internal code and removes most hash lookups

Differential Revision: https://phab.enlightenment.org/D11085
2020-01-23 15:24:30 -05:00
Mike Blumenkrantz be3a0f0364 tests/gesture: add longpress tests
Differential Revision: https://phab.enlightenment.org/D11084
2020-01-23 15:24:24 -05:00
Mike Blumenkrantz c00b1b9dcc tests/elm: add util functions for pressing mouse button without releasing
Differential Revision: https://phab.enlightenment.org/D11083
2020-01-23 15:24:18 -05:00
Mike Blumenkrantz 590e392976 tests/elm: add util function to automatically delay loop by given time
Differential Revision: https://phab.enlightenment.org/D11082
2020-01-23 15:24:12 -05:00
Mike Blumenkrantz 35ca4e0988 efl/gesture: unset timer pointers for tap recognizers
avoid having stale timer pointers around once timers have triggered

Differential Revision: https://phab.enlightenment.org/D11081
2020-01-23 15:24:06 -05:00
Mike Blumenkrantz 19156e9a5c tests/gesture: beef up gesture flick/momentum tests significantly
this adds test cases for flicks in different directions, flicks which
leave the canvas, and gestures which are momentums but not flicks

Differential Revision: https://phab.enlightenment.org/D11055
2020-01-23 15:23:59 -05:00
Mike Blumenkrantz 2bc5e87af2 tests/elm: add util function for dragging the pointer in an arc
useful for throwing in non-linear drags

Differential Revision: https://phab.enlightenment.org/D11054
2020-01-23 15:23:53 -05:00
Mike Blumenkrantz c357bcc6dd efl/gesture: formatting
some parts of this were entirely unreadable due to mixed tabs/spaces and other
bizarre formatting issues which somehow made it into the tree

Differential Revision: https://phab.enlightenment.org/D11053
2020-01-23 15:23:47 -05:00
Mike Blumenkrantz f849c9637e tests/efl_ui: begin some gesture unit tests
adds basic testing for taps and flick

Differential Revision: https://phab.enlightenment.org/D11029
2020-01-23 15:23:41 -05:00
Mike Blumenkrantz 01f33eac6f tests/elm: add basic timestamping for event helpers
this enables various internal components which use timestamps to have timestamps
that can be used

Differential Revision: https://phab.enlightenment.org/D11028
2020-01-23 15:23:35 -05:00
Mike Blumenkrantz 892b843d35 efl/gesture: do not emit events for canceled gestures with no state
for non-continuing gestures which have been canceled at this point, we must
not emit events in order to avoid sending useless events which serve no
purpose other than to waste cpu cycles

Differential Revision: https://phab.enlightenment.org/D11027
2020-01-23 15:23:28 -05:00
24 changed files with 1828 additions and 781 deletions

View File

@ -1037,7 +1037,35 @@ _evas_event_source_multi_down_events(Evas_Object_Protected_Data *obj, Evas_Publi
if (pdata->seat->mouse_grabbed == 0)
{
if (pdata->seat->downs > 1) addgrab = pdata->seat->downs - 1;
if (pdata->seat->downs > 1)
addgrab = pdata->seat->downs - 1;
else /* this is the first touch, which means it's also a move event, which means we need to redo this */
{
Eina_List *ins = NULL;
if (src->is_smart)
{
int no_rep = 0;
ins = _evas_event_object_list_raw_in_get
(e->evas, ins, evas_object_smart_members_get_direct(eo_src), NULL, NULL,
ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE, EINA_FALSE);
}
if (src->is_event_parent)
{
int no_rep = 0;
ins = _evas_event_object_list_raw_in_get
(e->evas, ins, NULL, evas_object_event_grabber_members_list(eo_src), NULL,
ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE, EINA_FALSE);
}
else
ins = eina_list_append(ins, eo_src);
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, src->proxy, Evas_Object_Proxy_Data, proxy_write)
{
eina_list_free(proxy_write->src_event_in);
proxy_write->src_event_in = ins;
}
EINA_COW_WRITE_END(evas_object_proxy_cow, src->proxy, proxy_write);
}
}
EINA_LIST_FOREACH(src->proxy->src_event_in, l, eo_child)
@ -3006,7 +3034,17 @@ _canvas_event_feed_multi_down_internal(Evas_Public_Data *e, Efl_Input_Pointer_Da
_evas_touch_point_append(eo_e, ev->touch_id, ev->cur.x, ev->cur.y);
if (pdata->seat->mouse_grabbed == 0)
{
if (pdata->seat->downs > 1) addgrab = pdata->seat->downs - 1;
if (pdata->seat->downs > 1)
addgrab = pdata->seat->downs - 1;
else /* this is the first touch, which means it's also a move event, which means we need to redo this */
{
/* get all new in objects */
Eina_List *ins = evas_event_objects_event_list(eo_e, NULL, ev->cur.x, ev->cur.y);
/* free our old list of ins */
eina_list_free(pdata->seat->object.in);
/* and set up the new one */
pdata->seat->object.in = ins;
}
}
copy = evas_event_list_copy(pdata->seat->object.in);
EINA_LIST_FOREACH(copy, l, eo_obj)

View File

@ -1,3 +1,4 @@
#define EFL_CANVAS_GESTURE_PROTECTED
#include "efl_canvas_gesture_private.h"
#define MY_CLASS EFL_CANVAS_GESTURE_CLASS
@ -28,7 +29,6 @@ _efl_canvas_gesture_hotspot_set(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Data *pd
pd->hotspot = hotspot;
}
EOLIAN static Eina_Position2D
_efl_canvas_gesture_hotspot_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Data *pd)
{
@ -41,12 +41,23 @@ _efl_canvas_gesture_timestamp_set(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Data *
pd->timestamp = timestamp;
}
EOLIAN static unsigned int
_efl_canvas_gesture_timestamp_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Data *pd)
{
return pd->timestamp;
}
EOLIAN static void
_efl_canvas_gesture_touch_count_set(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Data *pd, unsigned int touch_count)
{
pd->touch_count = touch_count;
}
EOLIAN static unsigned int
_efl_canvas_gesture_touch_count_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Data *pd)
{
return pd->touch_count;
}
#include "efl_canvas_gesture.eo.c"
#include "efl_canvas_gesture_events.eo.c"

View File

@ -46,5 +46,15 @@ abstract @beta Efl.Canvas.Gesture extends Efl.Object
timestamp: uint;[[The time-stamp.]]
}
}
@property touch_count {
[[The current number of touch points recorded in the gesture.]]
get {
}
set @protected {
}
values {
touch_count: uint;[[The count of the touch points.]]
}
}
}
}

View File

@ -1,36 +1,38 @@
#define EFL_CANVAS_GESTURE_PROTECTED
#include "efl_canvas_gesture_private.h"
#define MY_CLASS EFL_CANVAS_GESTURE_MANAGER_CLASS
#define EFL_GESTURE_RECOGNIZER_TYPE_TAP_FINGER_SIZE 10
typedef struct _Object_Gesture
{
Eo *object;
const Efl_Event_Description *type;
Efl_Canvas_Gesture *gesture;
Efl_Canvas_Gesture_Recognizer *recognizer;
Eo *object;
const Efl_Event_Description *type;
Efl_Canvas_Gesture *gesture;
Efl_Canvas_Gesture_Recognizer *recognizer;
} Object_Gesture;
typedef struct _Efl_Canvas_Gesture_Manager_Data
{
//Keeps track of all the gesture request for a particular target
Eina_Hash *m_gesture_contex; // (*target, *event_desc)
Eina_Hash *m_gesture_contex; // (*target, Eina_Hash(type, int))
//Keeps all the event directed to this particular object from touch_begin till touch_end
Eina_Hash *m_object_events; // (*target, *efl_gesture_touch)
Eina_Hash *m_object_events; // (*target, *efl_gesture_touch)
//Keeps all the recognizer registered to gesture manager
Eina_Hash *m_recognizers; // (*gesture_type, *recognizer)
Eina_Hash *m_recognizers; // (*gesture_type, *recognizer)
//Keeps track of all current object gestures.
Eina_List *m_object_gestures; //(List of *object_gesture)
Eina_List *m_object_gestures; //(List of *object_gesture)
//Lazy deletion of gestures
Eina_List *m_gestures_to_delete;
Eina_List *m_gestures_to_delete;
//Kepps config values for gesture recognize
Eina_Hash *m_config;
Eina_Hash *m_config;
} Efl_Canvas_Gesture_Manager_Data;
static void _cleanup_cached_gestures(Efl_Canvas_Gesture_Manager_Data *pd,
Eo *target, const Efl_Event_Description *type);
static Efl_Canvas_Gesture*
_get_state(Efl_Canvas_Gesture_Manager_Data *pd, Eo *target,
Efl_Canvas_Gesture_Recognizer *recognizer, const Efl_Event_Description *type);
Eo *target, const Efl_Event_Description *type);
static Efl_Canvas_Gesture *
_get_state(Efl_Canvas_Gesture_Manager_Data *pd, Eo *target,
Efl_Canvas_Gesture_Recognizer *recognizer, const Efl_Event_Description *type);
static void
_cleanup_object(Eina_List *list)
@ -52,18 +54,64 @@ _hash_unref_cb(Eo *obj)
efl_unref(obj);
}
/* updates the data for in-tree recognizers without needing to watch events */
static void
_update_finger_sizes(Efl_Canvas_Gesture_Manager_Data *pd, int finger_size)
{
Efl_Canvas_Gesture_Recognizer *r;
Efl_Canvas_Gesture_Recognizer_Tap_Data *td;
Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *dtd;
Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data *ttd;
Efl_Canvas_Gesture_Recognizer_Long_Tap_Data *ltd;
Efl_Canvas_Gesture_Recognizer_Flick_Data *fd;
Efl_Canvas_Gesture_Recognizer_Zoom_Data *zd;
const Efl_Event_Description *type;
type = EFL_EVENT_GESTURE_TAP;
r = eina_hash_find(pd->m_recognizers, &type);
td = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_TAP_CLASS);
td->finger_size = finger_size;
type = EFL_EVENT_GESTURE_DOUBLE_TAP;
r = eina_hash_find(pd->m_recognizers, &type);
dtd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_DOUBLE_TAP_CLASS);
dtd->finger_size = finger_size;
type = EFL_EVENT_GESTURE_TRIPLE_TAP;
r = eina_hash_find(pd->m_recognizers, &type);
ttd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_TRIPLE_TAP_CLASS);
ttd->finger_size = finger_size;
type = EFL_EVENT_GESTURE_LONG_TAP;
r = eina_hash_find(pd->m_recognizers, &type);
ltd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_LONG_TAP_CLASS);
ltd->finger_size = finger_size;
type = EFL_EVENT_GESTURE_FLICK;
r = eina_hash_find(pd->m_recognizers, &type);
fd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_FLICK_CLASS);
fd->finger_size = finger_size;
type = EFL_EVENT_GESTURE_ZOOM;
r = eina_hash_find(pd->m_recognizers, &type);
zd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_ZOOM_CLASS);
zd->finger_size = finger_size;
}
EOLIAN static Efl_Object *
_efl_canvas_gesture_manager_efl_object_constructor(Eo *obj, Efl_Canvas_Gesture_Manager_Data *pd EINA_UNUSED)
_efl_canvas_gesture_manager_efl_object_constructor(Eo *obj, Efl_Canvas_Gesture_Manager_Data *pd)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->m_recognizers = eina_hash_pointer_new(EINA_FREE_CB(_hash_unref_cb));
pd->m_gesture_contex = eina_hash_pointer_new(NULL);
pd->m_gesture_contex = eina_hash_pointer_new(EINA_FREE_CB(eina_hash_free));
pd->m_object_events = eina_hash_pointer_new(EINA_FREE_CB(_hash_unref_cb));
pd->m_object_gestures = NULL;
pd->m_gestures_to_delete = NULL;
pd->m_config = eina_hash_string_superfast_new(EINA_FREE_CB(eina_value_free));
/* this needs to always be present */
eina_hash_add(pd->m_config, "glayer_tap_finger_size", eina_value_int_new(EFL_GESTURE_RECOGNIZER_TYPE_TAP_FINGER_SIZE));
//Register all types of recognizers at very first time.
efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_TAP_CLASS, obj));
@ -73,6 +121,7 @@ _efl_canvas_gesture_manager_efl_object_constructor(Eo *obj, Efl_Canvas_Gesture_M
efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_MOMENTUM_CLASS, obj));
efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_FLICK_CLASS, obj));
efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_ZOOM_CLASS, obj));
_update_finger_sizes(pd, EFL_GESTURE_RECOGNIZER_TYPE_TAP_FINGER_SIZE);
return obj;
}
@ -84,27 +133,19 @@ _efl_canvas_gesture_manager_config_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Ges
}
EOLIAN static void
_efl_canvas_gesture_manager_config_set(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Manager_Data *pd, const char *name, Eina_Value *value)
_efl_canvas_gesture_manager_config_set(Eo *obj, Efl_Canvas_Gesture_Manager_Data *pd, const char *name, Eina_Value *value)
{
Eina_Value *v = eina_value_new(eina_value_type_get(value));
Eina_Value *v;
int finger_size;
EINA_SAFETY_ON_NULL_RETURN(name);
v = eina_value_new(eina_value_type_get(value));
eina_value_copy(value, v);
eina_hash_add(pd->m_config, name, v);
//Sets recognizer class property.
if (!strcmp(name, "glayer_tap_finger_size"))
{
int finger_size;
Efl_Canvas_Gesture_Recognizer *r;
Efl_Canvas_Gesture_Recognizer_Data *rd;
eina_value_get(value, &finger_size);
const Efl_Event_Description *type = EFL_EVENT_GESTURE_TAP;
r = eina_hash_find(pd->m_recognizers, &type);
rd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
rd->finger_size = finger_size;
}
efl_event_callback_call(obj, EFL_GESTURE_MANAGER_EVENT_CONFIG_CHANGED, (void*)name);
if (!eina_streq(name, "glayer_tap_finger_size")) return;
eina_value_get(value, &finger_size);
_update_finger_sizes(pd, finger_size);
}
EOLIAN static void
@ -131,11 +172,22 @@ _efl_canvas_gesture_manager_callback_add_hook(void *data, Eo *target, const Efl_
{
Efl_Canvas_Gesture_Manager_Data *pd = data;
//If there is a recognizer registered for that event then add it to the gesture context
Efl_Canvas_Gesture_Recognizer *recognizer = eina_hash_find (pd->m_recognizers, &type);
Efl_Canvas_Gesture_Recognizer *recognizer = eina_hash_find(pd->m_recognizers, &type);
if (recognizer)
{
//Add it to the gesture context.
eina_hash_list_append(pd->m_gesture_contex, &target, type);
Eina_Hash *thisisreallystupid = eina_hash_find(pd->m_gesture_contex, &target);
int count = 0;
/* already present */
if (thisisreallystupid)
count = (intptr_t)eina_hash_find(thisisreallystupid, &type);
else
{
thisisreallystupid = eina_hash_pointer_new(NULL);
eina_hash_set(pd->m_gesture_contex, &target, thisisreallystupid);
}
count++;
eina_hash_set(thisisreallystupid, &type, (intptr_t*)(long)count);
}
}
@ -144,10 +196,20 @@ _efl_canvas_gesture_manager_callback_del_hook(void *data, Eo *target, const Efl_
{
Efl_Canvas_Gesture_Manager_Data *pd = data;
//If there is a recognizer registered for that event then add it to the gesture context
Efl_Canvas_Gesture_Recognizer *recognizer = eina_hash_find (pd->m_recognizers, &type);
Efl_Canvas_Gesture_Recognizer *recognizer = eina_hash_find(pd->m_recognizers, &type);
if (recognizer)
{
eina_hash_list_remove(pd->m_gesture_contex, &target, type);
Eina_Hash *thisisreallystupid = eina_hash_find(pd->m_gesture_contex, &target);
int count;
if (!thisisreallystupid) return;
count = (intptr_t)eina_hash_find(thisisreallystupid, &type);
if (!count) return;
count--;
if (count) return;
eina_hash_del_by_key(thisisreallystupid, &type);
if (eina_hash_population(thisisreallystupid)) return;
eina_hash_del_by_key(pd->m_gesture_contex, &target);
_cleanup_cached_gestures(pd, target, type);
}
}
@ -156,104 +218,106 @@ void
_efl_canvas_gesture_manager_filter_event(void *data, Eo *target, void *event)
{
Efl_Canvas_Gesture_Manager_Data *pd = data;
Eina_List *l, *gesture_context;
const Efl_Event_Description *gesture_type;
Eina_Hash *thisisreallystupid;
Eina_Iterator *it;
const Efl_Event_Description **gtype;
Efl_Canvas_Gesture_Recognizer *recognizer;
Efl_Canvas_Gesture *gesture;
Efl_Canvas_Gesture_Recognizer_Result recog_result;
Efl_Canvas_Gesture_Recognizer_Result recog_state;
Efl_Canvas_Gesture_Touch *touch_event;
gesture_context = eina_hash_find(pd->m_gesture_contex, &target);
if (gesture_context)
thisisreallystupid = eina_hash_find(pd->m_gesture_contex, &target);
if (!thisisreallystupid) return;
it = eina_hash_iterator_key_new(thisisreallystupid);
EINA_ITERATOR_FOREACH(it, gtype)
{
EINA_LIST_FOREACH(gesture_context, l, gesture_type)
const Efl_Event_Description *gesture_type = *gtype;
//Check there is already created event exist or not.
touch_event = eina_hash_find(pd->m_object_events, &gesture_type);
if (!touch_event)
{
//Check there is already created event exist or not.
touch_event = eina_hash_find(pd->m_object_events, &gesture_type);
touch_event = efl_add_ref(EFL_CANVAS_GESTURE_TOUCH_CLASS, NULL);
eina_hash_add(pd->m_object_events, &gesture_type, touch_event);
}
if (!touch_event)
efl_gesture_touch_point_record(touch_event, event);
//This is for handling the case that mouse event pairs dont match.
//Such as the case of canceling gesture recognition after a mouse down.
if (efl_gesture_touch_state_get(touch_event) == EFL_GESTURE_TOUCH_STATE_UNKNOWN)
continue;
recognizer = eina_hash_find(pd->m_recognizers, &gesture_type);
//If the gesture canceled or already finished by recognizer.
gesture = _get_state(pd, target, recognizer, gesture_type);
if (!gesture)
continue;
/* this is the "default" value for the event, recognizers may modify it if necessary */
efl_gesture_touch_count_set(gesture, efl_gesture_touch_points_count_get(touch_event));
//Gesture detecting.
recog_result = efl_gesture_recognizer_recognize(recognizer, gesture, target, touch_event);
recog_state = recog_result & EFL_GESTURE_RECOGNIZER_RESULT_RESULT_MASK;
Efl_Canvas_Gesture_Recognizer_Data *rd =
efl_data_scope_get(recognizer, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER)
{
if (efl_gesture_state_get(gesture) == EFL_GESTURE_STATE_NONE)
efl_gesture_state_set(gesture, EFL_GESTURE_STATE_STARTED);
else
efl_gesture_state_set(gesture, EFL_GESTURE_STATE_UPDATED);
}
else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_FINISH)
{
efl_gesture_state_set(gesture, EFL_GESTURE_STATE_FINISHED);
}
else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_MAYBE)
{
continue;
}
else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_CANCEL)
{
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE)
efl_gesture_state_set(gesture, EFL_GESTURE_STATE_CANCELED);
else
{
touch_event = efl_add_ref(EFL_CANVAS_GESTURE_TOUCH_CLASS, NULL);
eina_hash_add(pd->m_object_events, &gesture_type, touch_event);
}
efl_gesture_touch_point_record(touch_event, event);
//This is for handling the case that mouse event pairs dont match.
//Such as the case of canceling gesture recognition after a mouse down.
if (efl_gesture_touch_state_get(touch_event) == EFL_GESTURE_TOUCH_STATE_UNKNOWN)
continue;
recognizer = eina_hash_find(pd->m_recognizers, &gesture_type);
//If the gesture canceled or already finished by recognizer.
gesture = _get_state(pd, target, recognizer, gesture_type);
if (!gesture)
continue;
//Gesture detecting.
recog_result = efl_gesture_recognizer_recognize(recognizer, gesture, target, touch_event);
recog_state = recog_result & EFL_GESTURE_RECOGNIZER_RESULT_RESULT_MASK;
Efl_Canvas_Gesture_Recognizer_Data *rd =
efl_data_scope_get(recognizer, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER)
{
if (efl_gesture_state_get(gesture) == EFL_GESTURE_STATE_NONE)
efl_gesture_state_set(gesture, EFL_GESTURE_STATE_STARTED);
else
efl_gesture_state_set(gesture, EFL_GESTURE_STATE_UPDATED);
}
else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_FINISH)
{
efl_gesture_state_set(gesture, EFL_GESTURE_STATE_FINISHED);
}
else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_MAYBE)
{
continue;
}
else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_CANCEL)
{
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE)
efl_gesture_state_set(gesture, EFL_GESTURE_STATE_CANCELED);
else
{
//Need to recognize events that occur consecutively
//in a mouse-down state.
if (rd->continues)
continue;
}
}
else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_IGNORE)
{
continue;
}
efl_gesture_timestamp_set(gesture, efl_gesture_touch_cur_timestamp_get(touch_event));
efl_event_callback_call(target, gesture_type, gesture);
//If the current event recognizes the gesture continuously, dont delete gesture.
if (((recog_state == EFL_GESTURE_RECOGNIZER_RESULT_FINISH) || (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_CANCEL)) &&
!rd->continues)
{
_cleanup_cached_gestures(pd, target, gesture_type);
eina_hash_del(pd->m_object_events, &gesture_type, NULL);
//FIXME: delete it by object not list.
_cleanup_object(pd->m_gestures_to_delete);
pd->m_gestures_to_delete = NULL;
if (rd->continues)
continue;
goto post_event;
}
}
else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_IGNORE)
{
continue;
}
efl_gesture_timestamp_set(gesture, efl_gesture_touch_cur_timestamp_get(touch_event));
efl_event_callback_call(target, gesture_type, gesture);
post_event:
//If the current event recognizes the gesture continuously, dont delete gesture.
if (((recog_state == EFL_GESTURE_RECOGNIZER_RESULT_FINISH) || (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_CANCEL)) &&
!rd->continues)
{
_cleanup_cached_gestures(pd, target, gesture_type);
eina_hash_del(pd->m_object_events, &gesture_type, NULL);
//FIXME: delete it by object not list.
_cleanup_object(pd->m_gestures_to_delete);
pd->m_gestures_to_delete = NULL;
}
}
eina_iterator_free(it);
}
EOLIAN static void
_efl_canvas_gesture_manager_recognizer_register(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Manager_Data *pd,
Efl_Canvas_Gesture_Recognizer *recognizer)
{
Efl_Canvas_Gesture_Recognizer_Data *rpd;
Efl_Canvas_Gesture *dummy = efl_gesture_recognizer_add(recognizer, NULL);
if (!dummy)
@ -263,16 +327,13 @@ _efl_canvas_gesture_manager_recognizer_register(Eo *obj EINA_UNUSED, Efl_Canvas_
//Add the recognizer to the m_recognizers
eina_hash_add(pd->m_recognizers, &type, efl_ref(recognizer));
//Update the manager
rpd = efl_data_scope_get(recognizer, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
rpd->manager = obj;
efl_del(dummy);
}
EOLIAN static void
_efl_canvas_gesture_manager_recognizer_unregister(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Manager_Data *pd,
Efl_Canvas_Gesture_Recognizer *recognizer)
Efl_Canvas_Gesture_Recognizer *recognizer)
{
Eina_List *l, *l_next;
Object_Gesture *object_gesture;
@ -283,7 +344,7 @@ _efl_canvas_gesture_manager_recognizer_unregister(Eo *obj EINA_UNUSED, Efl_Canva
//Find the type of the recognizer
dummy = efl_gesture_recognizer_add(recognizer, 0);
if (!dummy)return;
if (!dummy) return;
type = _efl_gesture_type_get(dummy);
efl_del(dummy);
@ -314,43 +375,50 @@ _find_match_recognizer(Efl_Canvas_Gesture_Manager_Data *pd, Efl_Canvas_Gesture_R
switch (type)
{
case EFL_GESTURE_RECOGNIZER_TYPE_TAP:
{
event_type = EFL_EVENT_GESTURE_TAP;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_DOUBLETAP:
{
event_type = EFL_EVENT_GESTURE_DOUBLE_TAP;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_TRIPLETAP:
{
event_type = EFL_EVENT_GESTURE_TRIPLE_TAP;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_LONGTAP:
{
event_type = EFL_EVENT_GESTURE_LONG_TAP;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_MOMENTUM:
{
event_type = EFL_EVENT_GESTURE_MOMENTUM;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_FLICK:
{
event_type = EFL_EVENT_GESTURE_FLICK;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_ZOOM:
{
event_type = EFL_EVENT_GESTURE_ZOOM;
break;
}
default:
return NULL;
case EFL_GESTURE_RECOGNIZER_TYPE_TAP:
{
event_type = EFL_EVENT_GESTURE_TAP;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_DOUBLETAP:
{
event_type = EFL_EVENT_GESTURE_DOUBLE_TAP;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_TRIPLETAP:
{
event_type = EFL_EVENT_GESTURE_TRIPLE_TAP;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_LONGTAP:
{
event_type = EFL_EVENT_GESTURE_LONG_TAP;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_MOMENTUM:
{
event_type = EFL_EVENT_GESTURE_MOMENTUM;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_FLICK:
{
event_type = EFL_EVENT_GESTURE_FLICK;
break;
}
case EFL_GESTURE_RECOGNIZER_TYPE_ZOOM:
{
event_type = EFL_EVENT_GESTURE_ZOOM;
break;
}
default:
return NULL;
}
return eina_hash_find(pd->m_recognizers, &event_type);
@ -387,7 +455,7 @@ _efl_canvas_gesture_manager_recognizer_get(Eo *obj EINA_UNUSED, Efl_Canvas_Gestu
// }
//Get or create a gesture object that will represent the state for a given object, used by the recognizer
Efl_Canvas_Gesture*
Efl_Canvas_Gesture *
_get_state(Efl_Canvas_Gesture_Manager_Data *pd,
Eo *target, Efl_Canvas_Gesture_Recognizer *recognizer, const Efl_Event_Description *type)
{
@ -408,20 +476,20 @@ _get_state(Efl_Canvas_Gesture_Manager_Data *pd,
if (object_gesture->object == target &&
object_gesture->recognizer == recognizer &&
object_gesture->type == type)
{
//The gesture is already processed waiting for cleanup
if (((efl_gesture_state_get(object_gesture->gesture) == EFL_GESTURE_STATE_FINISHED) ||
(efl_gesture_state_get(object_gesture->gesture) == EFL_GESTURE_STATE_CANCELED)) &&
(!rd->continues))
{
_cleanup_cached_gestures(pd, target, type);
eina_hash_del(pd->m_object_events, &type, NULL);
_cleanup_object(pd->m_gestures_to_delete);
pd->m_gestures_to_delete = NULL;
return NULL;
}
return object_gesture->gesture;
}
{
//The gesture is already processed waiting for cleanup
if (((efl_gesture_state_get(object_gesture->gesture) == EFL_GESTURE_STATE_FINISHED) ||
(efl_gesture_state_get(object_gesture->gesture) == EFL_GESTURE_STATE_CANCELED)) &&
(!rd->continues))
{
_cleanup_cached_gestures(pd, target, type);
eina_hash_del(pd->m_object_events, &type, NULL);
_cleanup_object(pd->m_gestures_to_delete);
pd->m_gestures_to_delete = NULL;
return NULL;
}
return object_gesture->gesture;
}
}
gesture = efl_gesture_recognizer_add(recognizer, target);

View File

@ -43,6 +43,9 @@ class @beta Efl.Canvas.Gesture_Manager extends Efl.Object
}
}
}
events {
config,changed: string; [[Called when a config value has been changed for the manager object. Passed string is the name of the value.]]
}
implements {
Efl.Object.constructor;
Efl.Object.destructor;

View File

@ -8,8 +8,13 @@
#include <Ecore.h>
/* milliseconds */
#define TAP_TOUCH_TIME_THRESHOLD (0.1 * 1000)
const Efl_Event_Description * _efl_gesture_type_get(const Eo *obj);
void efl_gesture_manager_gesture_clean_up(Eo *obj, Eo *target, const Efl_Event_Description *type);
int _direction_get(Evas_Coord xx1, Evas_Coord xx2);
Eina_Value *_recognizer_config_get(const Eo *obj, const char *name);
typedef struct _Efl_Canvas_Gesture_Manager_Data Efl_Canvas_Gesture_Manager_Data;
typedef struct _Efl_Canvas_Gesture_Recognizer_Data Efl_Canvas_Gesture_Recognizer_Data;
@ -25,31 +30,19 @@ typedef struct _Efl_Canvas_Gesture_Momentum_Data Efl_Canvas_Gestur
typedef struct _Efl_Canvas_Gesture_Flick_Data Efl_Canvas_Gesture_Flick_Data;
typedef struct _Efl_Canvas_Gesture_Zoom_Data Efl_Canvas_Gesture_Zoom_Data;
typedef struct _Pointer_Data
{
struct
{
Eina_Position2D pos;
unsigned int timestamp;
} start, prev, cur;
int id;
Efl_Pointer_Action action;
} Pointer_Data;
typedef struct _Efl_Canvas_Gesture_Touch_Data
{
Efl_Canvas_Gesture_Touch_State state;
Eina_Hash *touch_points;
Eina_Array *touch_points;
int touch_down;
Efl_Gesture_Touch_Point_Data *cur_touch;
Efl_Gesture_Touch_Point_Data *prev_touch;
Eina_Bool multi_touch;
Eo *target;
} Efl_Canvas_Gesture_Touch_Data;
struct _Efl_Canvas_Gesture_Recognizer_Data
{
Eo *manager; // keeps a reference of the manager
Eo *gesture;
int finger_size;
Eina_Bool continues;
};
@ -58,6 +51,7 @@ struct _Efl_Canvas_Gesture_Recognizer_Tap_Data
Eo *target;
Eo *gesture;
Ecore_Timer *timeout;
int finger_size;
};
struct _Efl_Canvas_Gesture_Recognizer_Long_Tap_Data
@ -68,6 +62,7 @@ struct _Efl_Canvas_Gesture_Recognizer_Long_Tap_Data
Ecore_Timer *timeout;
double start_timeout;
Eina_Bool is_timeout;
int finger_size;
};
struct _Efl_Canvas_Gesture_Recognizer_Double_Tap_Data
@ -79,6 +74,7 @@ struct _Efl_Canvas_Gesture_Recognizer_Double_Tap_Data
double start_timeout;
Eina_Bool is_timeout;
int tap_count;
int finger_size;
};
struct _Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data
@ -90,6 +86,7 @@ struct _Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data
double start_timeout;
Eina_Bool is_timeout;
int tap_count;
int finger_size;
};
struct _Efl_Canvas_Gesture_Recognizer_Momentum_Data
@ -110,16 +107,17 @@ struct _Efl_Canvas_Gesture_Recognizer_Flick_Data
unsigned int t_end;
int line_length;
double line_angle;
int finger_size;
Eina_Bool touched;
};
struct _Efl_Canvas_Gesture_Recognizer_Zoom_Data
{
Pointer_Data zoom_st;
Pointer_Data zoom_st1;
Efl_Gesture_Touch_Point_Data zoom_st;
Efl_Gesture_Touch_Point_Data zoom_st1;
Pointer_Data zoom_mv;
Pointer_Data zoom_mv1;
Efl_Gesture_Touch_Point_Data zoom_mv;
Efl_Gesture_Touch_Point_Data zoom_mv1;
Evas_Coord zoom_base; /* Holds gap between fingers on
* zoom-start */
@ -128,6 +126,7 @@ struct _Efl_Canvas_Gesture_Recognizer_Zoom_Data
double zoom_step;
double next_step;
Eina_Bool calc_temp;
int finger_size;
};
struct _Efl_Canvas_Gesture_Data
@ -136,15 +135,18 @@ struct _Efl_Canvas_Gesture_Data
Efl_Canvas_Gesture_State state;
Eina_Position2D hotspot;
unsigned int timestamp;
unsigned int touch_count;
};
struct _Efl_Canvas_Gesture_Momentum_Data
{
int id;
Eina_Vector2 momentum;
};
struct _Efl_Canvas_Gesture_Flick_Data
{
int id;
Eina_Vector2 momentum;
double angle;
};

View File

@ -1,28 +1,43 @@
#define EFL_CANVAS_GESTURE_RECOGNIZER_PROTECTED
#include "efl_canvas_gesture_private.h"
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_CLASS
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_CLASS
#include "efl_canvas_gesture_recognizer.eo.h"
#define EFL_GESTURE_RECOGNIZER_TYPE_TAP_FINGER_SIZE 10
EOLIAN static Eina_Value *
_efl_canvas_gesture_recognizer_config_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Recognizer_Data *pd, const char *name)
Eina_Value *
_recognizer_config_get(const Eo *obj, const char *name)
{
return efl_gesture_manager_config_get(pd->manager, name);
Eo *manager = efl_provider_find(obj, EFL_CANVAS_GESTURE_MANAGER_CLASS);
EINA_SAFETY_ON_NULL_RETURN_VAL(manager, NULL);
return efl_gesture_manager_config_get(manager, name);
}
EOLIAN static void
_efl_canvas_gesture_recognizer_reset(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Recognizer_Data *pd EINA_UNUSED,
Efl_Canvas_Gesture *gesture EINA_UNUSED)
Efl_Canvas_Gesture *gesture EINA_UNUSED)
{
}
EOLIAN static Efl_Object *
_efl_canvas_gesture_recognizer_efl_object_constructor(Eo *obj, Efl_Canvas_Gesture_Recognizer_Data *pd)
EOLIAN static Eina_Bool
_efl_canvas_gesture_recognizer_continues_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Recognizer_Data *pd)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->finger_size = EFL_GESTURE_RECOGNIZER_TYPE_TAP_FINGER_SIZE;
return obj;
return pd->continues;
}
EOLIAN static void
_efl_canvas_gesture_recognizer_continues_set(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Recognizer_Data *pd, Eina_Bool value)
{
pd->continues = !!value;
}
int
_direction_get(Evas_Coord xx1, Evas_Coord xx2)
{
if (xx2 < xx1) return -1;
if (xx2 > xx1) return 1;
return 0;
}
#include "efl_canvas_gesture_recognizer.eo.c"

View File

@ -7,7 +7,8 @@ abstract @beta Efl.Canvas.Gesture_Recognizer extends Efl.Object
Gesture recognizers listen to events that occur on a target object
to see if a particular gesture has occurred.
Recognizer-specific configuration values can be modified through @.config.
Recognizer-specific configuration values can be modified through @Efl.Canvas.Gesture_Manager.config,
and the recognizer's manager can be found using efl_provider_find.
Default configuration values are taken from the system's configuration.
]]
c_prefix: efl_gesture_recognizer;
@ -40,19 +41,17 @@ abstract @beta Efl.Canvas.Gesture_Recognizer extends Efl.Object
@in gesture: Efl.Canvas.Gesture; [[The gesture object.]]
}
}
@property config {
[[This property holds configuration values for the recognizer.]]
get {
@property continues {
[[This property determines whether a gesture recognizer should continue
to try processing events after returning #Efl.Canvas.Gesture_Recognizer_Result.finish
or #Efl.Canvas.Gesture_Recognizer_Result.cancel.]]
get @protected {
}
keys {
name: string; [[Property name.]]
set @protected {
}
values {
value: any_value_ref; [[Value of the property.]]
value: bool; [[Value of the property.]]
}
}
}
implements {
Efl.Object.constructor;
}
}

View File

@ -1,6 +1,6 @@
#include "efl_canvas_gesture_private.h"
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_DOUBLE_TAP_CLASS
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_DOUBLE_TAP_CLASS
#define TAP_TIME_OUT 0.33
@ -23,16 +23,15 @@ _efl_canvas_gesture_recognizer_double_tap_efl_object_destructor(Eo *obj,
static Eina_Bool
_tap_timeout_cb(void *data)
{
Efl_Canvas_Gesture_Recognizer_Data *rd;
Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *pd;
rd = efl_data_scope_get(data, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
pd = efl_data_scope_get(data, EFL_CANVAS_GESTURE_RECOGNIZER_DOUBLE_TAP_CLASS);
efl_gesture_state_set(pd->gesture, EFL_GESTURE_STATE_CANCELED);
efl_event_callback_call(pd->target, EFL_EVENT_GESTURE_DOUBLE_TAP, pd->gesture);
efl_gesture_manager_gesture_clean_up(rd->manager, pd->target, EFL_EVENT_GESTURE_DOUBLE_TAP);
efl_gesture_manager_gesture_clean_up(efl_provider_find(data, EFL_CANVAS_GESTURE_MANAGER_CLASS),
pd->target, EFL_EVENT_GESTURE_DOUBLE_TAP);
pd->timeout = NULL;
pd->tap_count = 0;
@ -51,7 +50,6 @@ _efl_canvas_gesture_recognizer_double_tap_efl_canvas_gesture_recognizer_recogniz
Eina_Position2D pos;
Eina_Vector2 dist;
Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(obj, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
pd->target = watched;
pd->gesture = gesture;
@ -59,7 +57,7 @@ _efl_canvas_gesture_recognizer_double_tap_efl_canvas_gesture_recognizer_recogniz
if (!pd->start_timeout)
{
double time;
Eina_Value *val = efl_gesture_recognizer_config_get(obj, "glayer_doublee_tap_timeout");
Eina_Value *val = _recognizer_config_get(obj, "glayer_double_tap_timeout");
if (val)
{
@ -73,80 +71,88 @@ _efl_canvas_gesture_recognizer_double_tap_efl_canvas_gesture_recognizer_recogniz
switch (efl_gesture_touch_state_get(event))
{
case EFL_GESTURE_TOUCH_STATE_BEGIN:
{
pos = efl_gesture_touch_start_point_get(event);
efl_gesture_hotspot_set(gesture, pos);
{
pos = efl_gesture_touch_start_point_get(event);
efl_gesture_hotspot_set(gesture, pos);
if (pd->timeout)
ecore_timer_reset(pd->timeout);
else
pd->timeout = ecore_timer_add(timeout, _tap_timeout_cb, obj);
if (pd->timeout)
ecore_timer_reset(pd->timeout);
else
pd->timeout = ecore_timer_add(timeout, _tap_timeout_cb, obj);
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
break;
}
break;
}
case EFL_GESTURE_TOUCH_STATE_UPDATE:
{
/* multi-touch */
if (efl_gesture_touch_cur_data_get(event)->action == EFL_POINTER_ACTION_DOWN)
{
/* a second finger was pressed at the same time-ish as the first: combine into same event */
if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
{
result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
break;
}
}
result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
{
result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
if (length > pd->finger_size)
{
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
if (length > rd->finger_size)
if (pd->timeout)
{
if (pd->timeout)
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
pd->tap_count = 0;
}
}
break;
}
case EFL_GESTURE_TOUCH_STATE_END:
{
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
{
if (efl_gesture_touch_prev_data_get(event))
{
Efl_Pointer_Action prev_act = efl_gesture_touch_prev_data_get(event)->action;
/* multi-touch */
if ((prev_act == EFL_POINTER_ACTION_UP) || (prev_act == EFL_POINTER_ACTION_CANCEL))
{
/* a second finger was pressed at the same time-ish as the first: combine into same event */
if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
break;
}
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
pd->tap_count = 0;
}
}
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
break;
}
case EFL_GESTURE_TOUCH_STATE_END:
{
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
if (length <= pd->finger_size)
{
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
if (length <= rd->finger_size)
pd->tap_count++;
if (pd->tap_count == 1)
{
pd->tap_count++;
if (pd->tap_count == 1)
{
if (pd->timeout)
ecore_timer_reset(pd->timeout);
if (pd->timeout)
ecore_timer_reset(pd->timeout);
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
else
{
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_END)
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
else
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
pd->tap_count = 0;
}
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
else
{
@ -156,15 +162,31 @@ _efl_canvas_gesture_recognizer_double_tap_efl_canvas_gesture_recognizer_recogniz
pd->timeout = NULL;
}
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_END)
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
else
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
pd->tap_count = 0;
}
}
else
{
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
break;
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
pd->tap_count = 0;
}
}
break;
}
default:
break;

View File

@ -1,15 +1,27 @@
#include "efl_canvas_gesture_private.h"
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_FLICK_CLASS
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_FLICK_CLASS
#define MOMENTUM_TIMEOUT 50
#define THUMBSCROLL_FRICTION 0.95
#define MOMENTUM_TIMEOUT 50
#define THUMBSCROLL_FRICTION 0.95
#define THUMBSCROLL_MOMENTUM_THRESHOLD 100.0
#define EFL_GESTURE_MINIMUM_MOMENTUM 0.001
#define EFL_GESTURE_MINIMUM_MOMENTUM 0.001
#define RAD2DEG(x) ((x) * 57.295779513)
#define DEG2RAD(x) ((x) / 57.295779513)
#define memset do not use memset to reset flick data, use _reset_recognizer
static void
_reset_recognizer(Efl_Canvas_Gesture_Recognizer_Flick_Data *pd)
{
pd->st_line = EINA_POSITION2D(0, 0);
pd->t_st = pd->t_end = 0;
pd->line_length = 0;
pd->line_angle = -1;
pd->touched = EINA_FALSE;
}
EOLIAN static Efl_Canvas_Gesture *
_efl_canvas_gesture_recognizer_flick_efl_canvas_gesture_recognizer_add(Eo *obj, Efl_Canvas_Gesture_Recognizer_Flick_Data *pd EINA_UNUSED, Efl_Object *target EINA_UNUSED)
{
@ -39,11 +51,11 @@ _momentum_set(Eo *obj,
vel = sqrt((velx * velx) + (vely * vely));
tf = efl_gesture_recognizer_config_get(obj, "thumbscroll_friction");
tf = _recognizer_config_get(obj, "thumbscroll_friction");
if (tf) eina_value_get(tf, &thumbscroll_friction);
else thumbscroll_friction = THUMBSCROLL_FRICTION;
tmt = efl_gesture_recognizer_config_get(obj, "thumbscroll_momentum_threshold");
tmt = _recognizer_config_get(obj, "thumbscroll_momentum_threshold");
if (tmt) eina_value_get(tmt, &thumbscroll_momentum_threshold);
else thumbscroll_momentum_threshold = THUMBSCROLL_MOMENTUM_THRESHOLD;
@ -70,32 +82,32 @@ _single_line_process(Eo *obj,
{
switch (efl_gesture_touch_state_get(event))
{
case EFL_GESTURE_TOUCH_STATE_BEGIN:
case EFL_GESTURE_TOUCH_STATE_UPDATE:
if (!pd->t_st)
{
pd->st_line = efl_gesture_touch_cur_point_get(event);
pd->t_st = efl_gesture_touch_cur_timestamp_get(event);
case EFL_GESTURE_TOUCH_STATE_BEGIN:
case EFL_GESTURE_TOUCH_STATE_UPDATE:
if (!pd->t_st)
{
pd->st_line = efl_gesture_touch_cur_point_get(event);
pd->t_st = efl_gesture_touch_cur_timestamp_get(event);
efl_gesture_hotspot_set(gesture, pd->st_line);
efl_gesture_hotspot_set(gesture, pd->st_line);
return;
}
return;
}
break;
case EFL_GESTURE_TOUCH_STATE_END:
{
if (!pd->t_st) return;
pd->t_end = efl_gesture_touch_cur_timestamp_get(event);
break;
}
case EFL_GESTURE_TOUCH_STATE_END:
{
if (!pd->t_st) return;
default:
pd->t_end = efl_gesture_touch_cur_timestamp_get(event);
break;
}
default:
return;
return;
}
_momentum_set(obj, fd, pd->st_line, efl_gesture_touch_cur_point_get(event),
@ -135,8 +147,8 @@ _angle_get(Evas_Coord xx1,
if (xx2 < xx1) rt = 180;
else rt = 0.0;
}
else
{ /* Vertical line */
else /* Vertical line */
{
if (yy2 < yy1) rt = 90;
else rt = 270;
}
@ -153,7 +165,6 @@ _angle_get(Evas_Coord xx1,
return rt;
}
static void
_vector_get(Eina_Position2D v1,
Eina_Position2D v2,
@ -179,10 +190,11 @@ _efl_canvas_gesture_recognizer_flick_efl_canvas_gesture_recognizer_recognize(Eo
unsigned char glayer_continues_enable;
Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
Eina_Bool touch_up = EINA_FALSE;
int points = efl_gesture_touch_points_count_get(event);
Efl_Canvas_Gesture_Flick_Data *fd = efl_data_scope_get(gesture, EFL_CANVAS_GESTURE_FLICK_CLASS);
Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(obj, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
val = efl_gesture_recognizer_config_get(obj, "glayer_continues_enable");
val = _recognizer_config_get(obj, "glayer_continues_enable");
if (val) eina_value_get(val, &glayer_continues_enable);
else glayer_continues_enable = 1;
@ -198,15 +210,42 @@ _efl_canvas_gesture_recognizer_flick_efl_canvas_gesture_recognizer_recognize(Eo
//This is to handle a case with a mouse click on the target object.
if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_END && !pd->touched)
efl_gesture_manager_gesture_clean_up(rd->manager, watched, EFL_EVENT_GESTURE_FLICK);
efl_gesture_manager_gesture_clean_up(efl_provider_find(obj, EFL_CANVAS_GESTURE_MANAGER_CLASS), watched, EFL_EVENT_GESTURE_FLICK);
if (glayer_continues_enable && !pd->touched)
{
pd->touched = EINA_TRUE;
pd->line_angle = -1.0;
rd->continues = EINA_TRUE;
pd->touched = EINA_TRUE;
pd->line_angle = -1.0;
rd->continues = EINA_TRUE;
fd->id = -1;
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
if (pd->touched && (efl_gesture_touch_cur_data_get(event)->action == EFL_POINTER_ACTION_DOWN))
{
/* a second finger was pressed at the same time-ish as the first: combine into same event */
if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
if (pd->t_st && (points > 1) && (fd->id != efl_gesture_touch_cur_data_get(event)->id))
{
int xdir[2], ydir[2];
const Efl_Gesture_Touch_Point_Data *data = efl_gesture_touch_cur_data_get(event);
const Efl_Gesture_Touch_Point_Data *data2;
if (fd->id == -1) return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
data2 = efl_gesture_touch_data_get(event, fd->id);
xdir[0] = _direction_get(data->prev.pos.x, data->cur.pos.x);
ydir[0] = _direction_get(data->prev.pos.y, data->cur.pos.y);
xdir[1] = _direction_get(data2->prev.pos.x, data2->cur.pos.x);
ydir[1] = _direction_get(data2->prev.pos.y, data2->cur.pos.y);
if ((xdir[0] != xdir[1]) || (ydir[0] != ydir[1]))
{
rd->continues = EINA_FALSE;
_reset_recognizer(pd);
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
_single_line_process(obj, pd, gesture, fd, event);
@ -221,20 +260,20 @@ _efl_canvas_gesture_recognizer_flick_efl_canvas_gesture_recognizer_recognize(Eo
double a = fabs(angle - pd->line_angle);
double d = (tan(DEG2RAD(a))) * pd->line_length;
val = efl_gesture_recognizer_config_get(obj, "glayer_line_distance_tolerance");
val = _recognizer_config_get(obj, "glayer_line_distance_tolerance");
if (val) eina_value_get(val, &line_distance_tolerance);
else line_distance_tolerance = 3.0;
line_distance_tolerance *= rd->finger_size;
line_distance_tolerance *= pd->finger_size;
val = efl_gesture_recognizer_config_get(obj, "glayer_line_angular_tolerance");
val = _recognizer_config_get(obj, "glayer_line_angular_tolerance");
if (val) eina_value_get(val, &line_angular_tolerance);
else line_angular_tolerance = 20.0;
if ((d > line_distance_tolerance) ||
(a > line_angular_tolerance))
{
memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Flick_Data));
_reset_recognizer(pd);
if (touch_up) rd->continues = EINA_FALSE;
@ -254,22 +293,21 @@ _efl_canvas_gesture_recognizer_flick_efl_canvas_gesture_recognizer_recognize(Eo
{
double line_min_length;
val = efl_gesture_recognizer_config_get(obj, "glayer_line_min_length");
val = _recognizer_config_get(obj, "glayer_line_min_length");
if (val) eina_value_get(val, &line_min_length);
else line_min_length = 1.0;
line_min_length *= rd->finger_size;
line_min_length *= pd->finger_size;
if (pd->line_length >= line_min_length)
fd->angle = pd->line_angle = angle;
}
if (pd->t_end)
{
if (pd->line_angle < 0.0)
{
memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Flick_Data));
_reset_recognizer(pd);
if (touch_up) rd->continues = EINA_FALSE;
@ -286,62 +324,65 @@ _efl_canvas_gesture_recognizer_flick_efl_canvas_gesture_recognizer_recognize(Eo
}
unsigned int time_limit_ms;
val = efl_gesture_recognizer_config_get(obj, "glayer_flick_time_limit_ms");
val = _recognizer_config_get(obj, "glayer_flick_time_limit_ms");
if (val) eina_value_get(val, &time_limit_ms);
else time_limit_ms = 120;
if ((tm_end - pd->t_st) > time_limit_ms)
{
memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Flick_Data));
{
_reset_recognizer(pd);
if (touch_up) rd->continues = EINA_FALSE;
if (touch_up) rd->continues = EINA_FALSE;
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
switch (efl_gesture_touch_state_get(event))
{
case EFL_GESTURE_TOUCH_STATE_BEGIN:
if (!glayer_continues_enable)
fd->id = efl_gesture_touch_cur_data_get(event)->id;
EINA_FALLTHROUGH;
case EFL_GESTURE_TOUCH_STATE_UPDATE:
{
if (pd->t_st)
{
if (glayer_continues_enable && pd->t_end)
{
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
}
else
{
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
}
break;
}
{
if (pd->t_st)
{
if (glayer_continues_enable && pd->t_end)
{
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
}
else
{
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
}
break;
}
case EFL_GESTURE_TOUCH_STATE_END:
{
if (!pd->t_st)
{
pd->touched = EINA_FALSE;
rd->continues = EINA_FALSE;
{
if (!pd->t_st)
{
pd->touched = EINA_FALSE;
rd->continues = EINA_FALSE;
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
if (pd->t_st && pd->t_end)
{
rd->continues = EINA_FALSE;
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
if (pd->t_st && pd->t_end)
{
rd->continues = EINA_FALSE;
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
}
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
}
efl_gesture_hotspot_set(gesture, efl_gesture_touch_cur_point_get(event));
efl_gesture_hotspot_set(gesture, efl_gesture_touch_cur_point_get(event));
memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Flick_Data));
_reset_recognizer(pd);
rd->continues = EINA_FALSE;
rd->continues = EINA_FALSE;
break;
}
break;
}
default:

View File

@ -1,6 +1,6 @@
#include "efl_canvas_gesture_private.h"
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_LONG_TAP_CLASS
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_LONG_TAP_CLASS
#define EFL_GESTURE_LONG_TAP_TIME_OUT 1.2
@ -29,6 +29,7 @@ _long_tap_timeout_cb(void *data)
/* FIXME: Needs to propagate this event back to evas! */
pd->is_timeout = EINA_TRUE;
pd->timeout = NULL;
efl_gesture_state_set(pd->gesture, EFL_GESTURE_STATE_UPDATED);
efl_event_callback_call(pd->target, EFL_EVENT_GESTURE_LONG_TAP, pd->gesture);
@ -48,7 +49,6 @@ _efl_canvas_gesture_recognizer_long_tap_efl_canvas_gesture_recognizer_recognize(
Eina_Position2D pos;
Eina_Vector2 dist;
Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(obj, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
pd->target = watched;
pd->gesture = gesture;
@ -56,7 +56,7 @@ _efl_canvas_gesture_recognizer_long_tap_efl_canvas_gesture_recognizer_recognize(
if (!pd->start_timeout)
{
double time;
Eina_Value *val = efl_gesture_recognizer_config_get(obj, "glayer_long_tap_start_timeout");
Eina_Value *val = _recognizer_config_get(obj, "glayer_long_tap_start_timeout");
if (val)
{
@ -67,74 +67,73 @@ _efl_canvas_gesture_recognizer_long_tap_efl_canvas_gesture_recognizer_recognize(
else
timeout = pd->start_timeout;
switch (efl_gesture_touch_state_get(event))
{
case EFL_GESTURE_TOUCH_STATE_BEGIN:
{
pos = efl_gesture_touch_start_point_get(event);
efl_gesture_hotspot_set(gesture, pos);
{
pos = efl_gesture_touch_start_point_get(event);
efl_gesture_hotspot_set(gesture, pos);
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
}
pd->timeout = ecore_timer_add(timeout,
_long_tap_timeout_cb, pd);
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
}
pd->timeout = ecore_timer_add(timeout,
_long_tap_timeout_cb, pd);
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
break;
}
break;
}
case EFL_GESTURE_TOUCH_STATE_UPDATE:
{
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
{
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
if ((efl_gesture_touch_multi_touch_get(event)) || (length > rd->finger_size))
{
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
if ((efl_gesture_touch_multi_touch_get(event)) || (length > pd->finger_size))
{
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
else
{
result = EFL_GESTURE_RECOGNIZER_RESULT_MAYBE;
}
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
else
{
result = EFL_GESTURE_RECOGNIZER_RESULT_MAYBE;
}
break;
}
break;
}
case EFL_GESTURE_TOUCH_STATE_END:
{
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
{
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
{
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
if (length <= rd->finger_size && pd->is_timeout)
{
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
}
else
{
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
}
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
{
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
if (length <= pd->finger_size && pd->is_timeout)
{
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
}
else
{
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
}
break;
}
break;
}
default:

View File

@ -1,11 +1,11 @@
#include "efl_canvas_gesture_private.h"
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_MOMENTUM_CLASS
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_MOMENTUM_CLASS
#define MOMENTUM_TIMEOUT 50
#define THUMBSCROLL_FRICTION 0.95
#define MOMENTUM_TIMEOUT 50
#define THUMBSCROLL_FRICTION 0.95
#define THUMBSCROLL_MOMENTUM_THRESHOLD 100.0
#define EFL_GESTURE_MINIMUM_MOMENTUM 0.001
#define EFL_GESTURE_MINIMUM_MOMENTUM 0.001
EOLIAN static Efl_Canvas_Gesture *
_efl_canvas_gesture_recognizer_momentum_efl_canvas_gesture_recognizer_add(Eo *obj, Efl_Canvas_Gesture_Recognizer_Momentum_Data *pd EINA_UNUSED, Efl_Object *target EINA_UNUSED)
@ -32,15 +32,15 @@ _momentum_set(Eo *obj,
{
velx = (dx * 1000) / dt;
vely = (dy * 1000) / dt;
}
}
vel = sqrt((velx * velx) + (vely * vely));
tf = efl_gesture_recognizer_config_get(obj, "thumbscroll_friction");
tf = _recognizer_config_get(obj, "thumbscroll_friction");
if (tf) eina_value_get(tf, &thumbscroll_friction);
else thumbscroll_friction = THUMBSCROLL_FRICTION;
tmt = efl_gesture_recognizer_config_get(obj, "thumbscroll_momentum_threshold");
tmt = _recognizer_config_get(obj, "thumbscroll_momentum_threshold");
if (tmt) eina_value_get(tmt, &thumbscroll_momentum_threshold);
else thumbscroll_momentum_threshold = THUMBSCROLL_MOMENTUM_THRESHOLD;
@ -58,28 +58,18 @@ _momentum_set(Eo *obj,
}
}
static int
_direction_get(Evas_Coord xx1,
Evas_Coord xx2)
{
if (xx2 < xx1) return -1;
if (xx2 > xx1) return 1;
return 0;
}
EOLIAN static Efl_Canvas_Gesture_Recognizer_Result
_efl_canvas_gesture_recognizer_momentum_efl_canvas_gesture_recognizer_recognize(Eo *obj,
Efl_Canvas_Gesture_Recognizer_Momentum_Data *pd,
Efl_Canvas_Gesture *gesture, Efl_Object *watched EINA_UNUSED,
Efl_Canvas_Gesture_Touch *event)
Efl_Canvas_Gesture_Recognizer_Momentum_Data *pd,
Efl_Canvas_Gesture *gesture, Efl_Object *watched EINA_UNUSED,
Efl_Canvas_Gesture_Touch *event)
{
Eina_Value *val;
unsigned char glayer_continues_enable;
Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
Efl_Canvas_Gesture_Momentum_Data *md = efl_data_scope_get(gesture, EFL_CANVAS_GESTURE_MOMENTUM_CLASS);
val = efl_gesture_recognizer_config_get(obj, "glayer_continues_enable");
val = _recognizer_config_get(obj, "glayer_continues_enable");
if (val) eina_value_get(val, &glayer_continues_enable);
else glayer_continues_enable = 1;
@ -87,104 +77,143 @@ _efl_canvas_gesture_recognizer_momentum_efl_canvas_gesture_recognizer_recognize(
//It does not have any meanging of this gesture.
if (glayer_continues_enable && !pd->touched)
{
pd->touched = EINA_TRUE;
if (efl_gesture_touch_state_get(event) != EFL_GESTURE_TOUCH_STATE_END)
{
/* guard against successive multi-touch cancels */
if (efl_gesture_touch_points_count_get(event) == 1)
{
pd->touched = EINA_TRUE;
md->id = -1;
}
}
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
if (pd->touched && (efl_gesture_touch_cur_data_get(event)->action == EFL_POINTER_ACTION_DOWN))
{
/* a second finger was pressed at the same time-ish as the first: combine into same event */
if (efl_gesture_touch_points_count_get(event) > 1)
{
if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_touch_prev_data_get(event)->cur.timestamp < TAP_TOUCH_TIME_THRESHOLD)
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
else if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
if (pd->t_st && (md->id != -1) && (md->id != efl_gesture_touch_cur_data_get(event)->id))
{
int xdir, ydir;
const Efl_Gesture_Touch_Point_Data *data = efl_gesture_touch_cur_data_get(event);
xdir = _direction_get(data->prev.pos.x, data->cur.pos.x);
ydir = _direction_get(data->prev.pos.y, data->cur.pos.y);
if ((xdir != pd->xdir) || (ydir != pd->ydir))
{
memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Momentum_Data));
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
switch (efl_gesture_touch_state_get(event))
{
case EFL_GESTURE_TOUCH_STATE_BEGIN:
case EFL_GESTURE_TOUCH_STATE_UPDATE:
{
if (!pd->t_st)
{
if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_BEGIN ||
glayer_continues_enable)
{
pd->t_st = pd->t_end = efl_gesture_touch_cur_timestamp_get(event);
{
if (!pd->t_st)
{
if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_BEGIN ||
glayer_continues_enable)
{
if (efl_gesture_touch_prev_data_get(event))
{
if (efl_gesture_touch_prev_data_get(event)->action == efl_gesture_touch_cur_data_get(event)->action)
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
pd->t_st = pd->t_end = efl_gesture_touch_cur_timestamp_get(event);
pd->st_line = pd->end_line =
efl_gesture_touch_start_point_get(event);
pd->st_line = pd->end_line =
efl_gesture_touch_start_point_get(event);
efl_gesture_hotspot_set(gesture, pd->st_line);
efl_gesture_hotspot_set(gesture, pd->st_line);
if (!glayer_continues_enable)
md->id = efl_gesture_touch_cur_data_get(event)->id;
return EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
}
return EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
}
if ((efl_gesture_touch_cur_timestamp_get(event) - MOMENTUM_TIMEOUT) >
pd->t_end)
{
pd->st_line = efl_gesture_touch_cur_point_get(event);
pd->t_st = efl_gesture_touch_cur_timestamp_get(event);
pd->xdir = pd->ydir = 0;
}
else
{
int xdir, ydir;
Eina_Position2D cur_p = efl_gesture_touch_cur_point_get(event);
if ((efl_gesture_touch_cur_timestamp_get(event) - MOMENTUM_TIMEOUT) >
pd->t_end)
{
pd->st_line = efl_gesture_touch_cur_point_get(event);
pd->t_st = efl_gesture_touch_cur_timestamp_get(event);
pd->xdir = pd->ydir = 0;
}
else
{
int xdir, ydir;
Eina_Position2D cur_p = efl_gesture_touch_cur_point_get(event);
xdir = _direction_get(pd->end_line.x, cur_p.x);
ydir = _direction_get(pd->end_line.y, cur_p.y);
xdir = _direction_get(pd->end_line.x, cur_p.x);
ydir = _direction_get(pd->end_line.y, cur_p.y);
if (xdir && (xdir != pd->xdir))
{
pd->st_line.x = pd->end_line.x;
pd->t_st = pd->t_end;
pd->xdir = xdir;
}
if (xdir && (xdir != pd->xdir))
{
pd->st_line.x = pd->end_line.x;
pd->t_st = pd->t_end;
pd->xdir = xdir;
}
if (ydir && (ydir != pd->ydir))
{
pd->st_line.y = pd->end_line.y;
pd->t_st = pd->t_end;
pd->ydir = ydir;
}
}
if (ydir && (ydir != pd->ydir))
{
pd->st_line.y = pd->end_line.y;
pd->t_st = pd->t_end;
pd->ydir = ydir;
}
}
pd->end_line = efl_gesture_touch_cur_point_get(event);
pd->t_end = efl_gesture_touch_cur_timestamp_get(event);
efl_gesture_hotspot_set(gesture, pd->end_line);
pd->end_line = efl_gesture_touch_cur_point_get(event);
pd->t_end = efl_gesture_touch_cur_timestamp_get(event);
efl_gesture_hotspot_set(gesture, pd->end_line);
_momentum_set(obj, md, pd->st_line, efl_gesture_touch_cur_point_get(event),
pd->t_st, efl_gesture_touch_cur_timestamp_get(event));
_momentum_set(obj, md, pd->st_line, efl_gesture_touch_cur_point_get(event),
pd->t_st, efl_gesture_touch_cur_timestamp_get(event));
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
break;
}
break;
}
case EFL_GESTURE_TOUCH_STATE_END:
{
if (!pd->t_st)
{
pd->touched = EINA_FALSE;
{
if (!pd->t_st)
{
pd->touched = EINA_FALSE;
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
if ((efl_gesture_touch_cur_timestamp_get(event) - MOMENTUM_TIMEOUT) > pd->t_end)
{
pd->st_line = efl_gesture_touch_cur_point_get(event);
pd->t_st = efl_gesture_touch_cur_timestamp_get(event);
pd->xdir = pd->ydir = 0;
}
if ((efl_gesture_touch_cur_timestamp_get(event) - MOMENTUM_TIMEOUT) > pd->t_end)
{
pd->st_line = efl_gesture_touch_cur_point_get(event);
pd->t_st = efl_gesture_touch_cur_timestamp_get(event);
pd->xdir = pd->ydir = 0;
}
pd->end_line = efl_gesture_touch_cur_point_get(event);
pd->t_end = efl_gesture_touch_cur_timestamp_get(event);
efl_gesture_hotspot_set(gesture, pd->end_line);
pd->end_line = efl_gesture_touch_cur_point_get(event);
pd->t_end = efl_gesture_touch_cur_timestamp_get(event);
efl_gesture_hotspot_set(gesture, pd->end_line);
if ((fabs(md->momentum.x) > EFL_GESTURE_MINIMUM_MOMENTUM) ||
(fabs(md->momentum.y) > EFL_GESTURE_MINIMUM_MOMENTUM))
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
else
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
if ((fabs(md->momentum.x) > EFL_GESTURE_MINIMUM_MOMENTUM) ||
(fabs(md->momentum.y) > EFL_GESTURE_MINIMUM_MOMENTUM))
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
else
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Momentum_Data));
memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Momentum_Data));
break;
}
break;
}
default:

View File

@ -1,6 +1,6 @@
#include "efl_canvas_gesture_private.h"
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_TAP_CLASS
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_TAP_CLASS
//FIXME: It doesnt have matched config value.
// may using dobule tap timeout value?
@ -18,6 +18,7 @@ static Eina_Bool
_tap_timeout_cb(void *data)
{
Efl_Canvas_Gesture_Recognizer_Tap_Data *pd = data;
pd->timeout = NULL;
efl_gesture_state_set(pd->gesture, EFL_GESTURE_STATE_CANCELED);
efl_event_callback_call(pd->target, EFL_EVENT_GESTURE_TAP, pd->gesture);
@ -25,9 +26,8 @@ _tap_timeout_cb(void *data)
return ECORE_CALLBACK_CANCEL;
}
EOLIAN static Efl_Canvas_Gesture_Recognizer_Result
_efl_canvas_gesture_recognizer_tap_efl_canvas_gesture_recognizer_recognize(Eo *obj,
_efl_canvas_gesture_recognizer_tap_efl_canvas_gesture_recognizer_recognize(Eo *obj EINA_UNUSED,
Efl_Canvas_Gesture_Recognizer_Tap_Data *pd,
Efl_Canvas_Gesture *gesture,
Efl_Object *watched,
@ -37,7 +37,6 @@ _efl_canvas_gesture_recognizer_tap_efl_canvas_gesture_recognizer_recognize(Eo *o
Eina_Position2D pos;
Eina_Vector2 dist;
Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(obj, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
pd->target = watched;
pd->gesture = gesture;
@ -45,44 +44,58 @@ _efl_canvas_gesture_recognizer_tap_efl_canvas_gesture_recognizer_recognize(Eo *o
switch (efl_gesture_touch_state_get(event))
{
case EFL_GESTURE_TOUCH_STATE_BEGIN:
{
pos = efl_gesture_touch_start_point_get(event);
efl_gesture_hotspot_set(gesture, pos);
{
new_tap:
pos = efl_gesture_touch_start_point_get(event);
efl_gesture_hotspot_set(gesture, pos);
if (pd->timeout)
ecore_timer_del(pd->timeout);
pd->timeout = ecore_timer_add(EFL_GESTURE_RECOGNIZER_TYPE_TAP_TIME_OUT, _tap_timeout_cb, pd);
if (pd->timeout)
ecore_timer_del(pd->timeout);
pd->timeout = ecore_timer_add(EFL_GESTURE_RECOGNIZER_TYPE_TAP_TIME_OUT, _tap_timeout_cb, pd);
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
break;
}
break;
}
case EFL_GESTURE_TOUCH_STATE_UPDATE:
/* multi-touch */
if (efl_gesture_touch_cur_data_get(event)->action == EFL_POINTER_ACTION_DOWN)
{
/* a second finger was pressed at the same time-ish as the first: combine into same event */
if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
{
result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
break;
}
/* another distinct touch occurred, treat this as a new touch */
goto new_tap;
}
EINA_FALLTHROUGH;
case EFL_GESTURE_TOUCH_STATE_END:
{
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
{
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
{
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
if (length <= rd->finger_size)
{
if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_END)
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
else
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
}
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
{
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
if (length <= pd->finger_size)
{
if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_END)
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
else
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
}
break;
}
break;
}
default:

View File

@ -1,6 +1,6 @@
#include "efl_canvas_gesture_private.h"
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_TRIPLE_TAP_CLASS
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_TRIPLE_TAP_CLASS
#define TAP_TIME_OUT 0.33
@ -23,16 +23,14 @@ _efl_canvas_gesture_recognizer_triple_tap_efl_object_destructor(Eo *obj,
static Eina_Bool
_tap_timeout_cb(void *data)
{
Efl_Canvas_Gesture_Recognizer_Data *rd;
Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data *pd;
rd = efl_data_scope_get(data, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
pd = efl_data_scope_get(data, EFL_CANVAS_GESTURE_RECOGNIZER_TRIPLE_TAP_CLASS);
efl_gesture_state_set(pd->gesture, EFL_GESTURE_STATE_CANCELED);
efl_event_callback_call(pd->target, EFL_EVENT_GESTURE_TRIPLE_TAP, pd->gesture);
efl_gesture_manager_gesture_clean_up(rd->manager, pd->target, EFL_EVENT_GESTURE_TRIPLE_TAP);
efl_gesture_manager_gesture_clean_up(efl_provider_find(data, EFL_CANVAS_GESTURE_MANAGER_CLASS), pd->target, EFL_EVENT_GESTURE_TRIPLE_TAP);
pd->timeout = NULL;
pd->tap_count = 0;
@ -51,7 +49,6 @@ _efl_canvas_gesture_recognizer_triple_tap_efl_canvas_gesture_recognizer_recogniz
Eina_Position2D pos;
Eina_Vector2 dist;
Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(obj, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
pd->target = watched;
pd->gesture = gesture;
@ -59,7 +56,7 @@ _efl_canvas_gesture_recognizer_triple_tap_efl_canvas_gesture_recognizer_recogniz
if (!pd->start_timeout)
{
double time;
Eina_Value *val = efl_gesture_recognizer_config_get(obj, "glayer_doublee_tap_timeout");
Eina_Value *val = _recognizer_config_get(obj, "glayer_double_tap_timeout");
if (val)
{
@ -73,80 +70,88 @@ _efl_canvas_gesture_recognizer_triple_tap_efl_canvas_gesture_recognizer_recogniz
switch (efl_gesture_touch_state_get(event))
{
case EFL_GESTURE_TOUCH_STATE_BEGIN:
{
pos = efl_gesture_touch_start_point_get(event);
efl_gesture_hotspot_set(gesture, pos);
{
pos = efl_gesture_touch_start_point_get(event);
efl_gesture_hotspot_set(gesture, pos);
if (pd->timeout)
ecore_timer_reset(pd->timeout);
else
pd->timeout = ecore_timer_add(timeout, _tap_timeout_cb, obj);
if (pd->timeout)
ecore_timer_reset(pd->timeout);
else
pd->timeout = ecore_timer_add(timeout, _tap_timeout_cb, obj);
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
break;
}
break;
}
case EFL_GESTURE_TOUCH_STATE_UPDATE:
{
/* multi-touch */
if (efl_gesture_touch_cur_data_get(event)->action == EFL_POINTER_ACTION_DOWN)
{
/* a second finger was pressed at the same time-ish as the first: combine into same event */
if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
{
result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
break;
}
}
result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
{
result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
if (length > pd->finger_size)
{
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
if (length > rd->finger_size)
if (pd->timeout)
{
if (pd->timeout)
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
pd->tap_count = 0;
}
}
break;
}
case EFL_GESTURE_TOUCH_STATE_END:
{
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
{
if (efl_gesture_touch_prev_data_get(event))
{
Efl_Pointer_Action prev_act = efl_gesture_touch_prev_data_get(event)->action;
/* multi-touch */
if ((prev_act == EFL_POINTER_ACTION_UP) || (prev_act == EFL_POINTER_ACTION_CANCEL))
{
/* a second finger was pressed at the same time-ish as the first: combine into same event */
if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
break;
}
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
pd->tap_count = 0;
}
}
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
break;
}
case EFL_GESTURE_TOUCH_STATE_END:
{
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
!efl_gesture_touch_multi_touch_get(event))
if (length <= pd->finger_size)
{
dist = efl_gesture_touch_distance(event, 0);
length = fabs(dist.x) + fabs(dist.y);
if (length <= rd->finger_size)
pd->tap_count++;
if (pd->tap_count < 3)
{
pd->tap_count++;
if (pd->tap_count < 3)
{
if (pd->timeout)
ecore_timer_reset(pd->timeout);
if (pd->timeout)
ecore_timer_reset(pd->timeout);
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
else
{
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_END)
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
else
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
pd->tap_count = 0;
}
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
else
{
@ -156,15 +161,31 @@ _efl_canvas_gesture_recognizer_triple_tap_efl_canvas_gesture_recognizer_recogniz
pd->timeout = NULL;
}
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_END)
result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
else
result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
pd->tap_count = 0;
}
}
else
{
if (pd->timeout)
{
ecore_timer_del(pd->timeout);
pd->timeout = NULL;
}
break;
result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
pd->tap_count = 0;
}
}
break;
}
default:
break;

View File

@ -2,13 +2,27 @@
#define MY_CLASS EFL_CANVAS_GESTURE_RECOGNIZER_ZOOM_CLASS
static void
_reset_recognizer(Efl_Canvas_Gesture_Recognizer_Zoom_Data *pd)
{
memset(&pd->zoom_st, 0, sizeof(Efl_Gesture_Touch_Point_Data));
memset(&pd->zoom_st1, 0, sizeof(Efl_Gesture_Touch_Point_Data));
memset(&pd->zoom_mv, 0, sizeof(Efl_Gesture_Touch_Point_Data));
memset(&pd->zoom_mv1, 0, sizeof(Efl_Gesture_Touch_Point_Data));
pd->zoom_base = 0;
pd->zoom_step = pd->next_step = pd->zoom_finger_factor = pd->zoom_distance_tolerance = 0;
pd->calc_temp = EINA_FALSE;
}
#define memset do not use memset to reset zoom data, use _reset_recognizer
static Evas_Coord
_finger_gap_length_get(Evas_Coord xx1,
Evas_Coord yy1,
Evas_Coord xx2,
Evas_Coord yy2,
Evas_Coord *x,
Evas_Coord *y)
Evas_Coord yy1,
Evas_Coord xx2,
Evas_Coord yy2,
Evas_Coord *x,
Evas_Coord *y)
{
double a, b, xx, yy, gap;
xx = abs(xx2 - xx1);
@ -67,7 +81,7 @@ _zoom_compute(Efl_Canvas_Gesture_Recognizer_Zoom_Data *pd,
//unsigned int tm_end = (pd->zoom_mv.cur.timestamp > pd->zoom_mv1.cur.timestamp) ?
// pd->zoom_mv.cur.timestamp : pd->zoom_mv1.cur.timestamp;
int x,y; //Hot spot
int x, y; //Hot spot
Evas_Coord diam = _finger_gap_length_get(xx1, yy1, xx2, yy2,
&x, &y);
@ -80,7 +94,7 @@ _zoom_compute(Efl_Canvas_Gesture_Recognizer_Zoom_Data *pd,
}
if (pd->zoom_distance_tolerance) /* zoom tolerance <> ZERO, means
* zoom action NOT started yet */
* zoom action NOT started yet */
{
/* avoid jump with zoom value when break tolerance */
if (diam < (pd->zoom_base - pd->zoom_distance_tolerance))
@ -126,8 +140,6 @@ _efl_canvas_gesture_recognizer_zoom_efl_canvas_gesture_recognizer_recognize(Eo *
Efl_Object *watched,
Efl_Canvas_Gesture_Touch *event)
{
int id1 = 0;
int id2 = 1;
Eina_Value *val;
unsigned char zoom_finger_enable;
unsigned char glayer_continues_enable;
@ -138,16 +150,16 @@ _efl_canvas_gesture_recognizer_zoom_efl_canvas_gesture_recognizer_recognize(Eo *
//FIXME: Wheel zoom test first here.
val = efl_gesture_recognizer_config_get(obj, "glayer_continues_enable");
val = _recognizer_config_get(obj, "glayer_continues_enable");
if (val) eina_value_get(val, &glayer_continues_enable);
else glayer_continues_enable = 1;
val = efl_gesture_recognizer_config_get(obj, "glayer_zoom_finger_enable");
val = _recognizer_config_get(obj, "glayer_zoom_finger_enable");
if (val) eina_value_get(val, &zoom_finger_enable);
else zoom_finger_enable = 1;
val = efl_gesture_recognizer_config_get(obj, "glayer_zoom_finger_factor");
if (val) eina_value_get(val, &pd->zoom_finger_factor);
val = _recognizer_config_get(obj, "glayer_zoom_finger_factor");
if (val) eina_value_get(val, &pd->zoom_finger_factor);
else pd->zoom_finger_factor = 1.0;
rd->continues = EINA_TRUE;
@ -155,118 +167,124 @@ _efl_canvas_gesture_recognizer_zoom_efl_canvas_gesture_recognizer_recognize(Eo *
if (!pd->zoom_distance_tolerance && !pd->calc_temp)
{
pd->calc_temp = EINA_TRUE;
val = efl_gesture_recognizer_config_get(obj, "glayer_zoom_distance_tolerance");
if (val) eina_value_get(val, &pd->zoom_distance_tolerance);
val = _recognizer_config_get(obj, "glayer_zoom_distance_tolerance");
if (val) eina_value_get(val, &pd->zoom_distance_tolerance);
else pd->zoom_distance_tolerance = 1.0;
pd->zoom_distance_tolerance *= rd->finger_size;
pd->zoom_distance_tolerance *= pd->finger_size;
}
switch (efl_gesture_touch_state_get(event))
{
case EFL_GESTURE_TOUCH_STATE_UPDATE:
{
if ((!glayer_continues_enable) && (!pd->zoom_st.cur.timestamp))
{
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
EINA_FALLTHROUGH;
}
{
if ((!glayer_continues_enable) && (!pd->zoom_st.cur.timestamp))
{
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
EINA_FALLTHROUGH;
}
case EFL_GESTURE_TOUCH_STATE_BEGIN:
{
if (td->touch_down > 2)
{
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
{
if (td->touch_down > 2)
{
_reset_recognizer(pd);
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
if (td->touch_down == 1)
{
return EFL_GESTURE_RECOGNIZER_RESULT_MAYBE;
}
if (!pd->zoom_st.cur.timestamp) /* Now scan touched-devices list
if (!pd->zoom_st.cur.timestamp) /* Now scan touched-devices list
* and find other finger */
{
if (!efl_gesture_touch_multi_touch_get(event))
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
Pointer_Data *p1 = eina_hash_find(td->touch_points, &id1);
Pointer_Data *p2 = eina_hash_find(td->touch_points, &id2);
memcpy(&pd->zoom_st, p2, sizeof(Pointer_Data));
memcpy(&pd->zoom_st1, p1, sizeof(Pointer_Data));
memcpy(&pd->zoom_mv, p2, sizeof(Pointer_Data));
memcpy(&pd->zoom_mv1, p1, sizeof(Pointer_Data));
int x,y; //Hot spot
zd->zoom = 1.0;
pd->zoom_base = _finger_gap_length_get(pd->zoom_st1.cur.pos.x,
pd->zoom_st1.cur.pos.y,
pd->zoom_st.cur.pos.x,
pd->zoom_st.cur.pos.y,
&x, &y);
zd->radius = pd->zoom_base / 2.0;
if ((efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_STARTED) &&
(efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_UPDATED))
return EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
Pointer_Data *p2 = eina_hash_find(td->touch_points, &id2);
if (p2->id == pd->zoom_mv.id)
memcpy(&pd->zoom_mv, p2, sizeof(Pointer_Data));
else if (p2->id == pd->zoom_mv1.id)
memcpy(&pd->zoom_mv1, p2, sizeof(Pointer_Data));
zd->zoom = _zoom_compute(pd, zd, pd->zoom_mv.cur.pos.x,
pd->zoom_mv.cur.pos.y, pd->zoom_mv1.cur.pos.x,
pd->zoom_mv1.cur.pos.y, pd->zoom_finger_factor);
if (!pd->zoom_distance_tolerance)
{
double d = zd->zoom - pd->next_step;
if (d < 0.0) d = (-d);
if (d >= pd->zoom_step)
{
pd->next_step = zd->zoom;
return EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
}
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
case EFL_GESTURE_TOUCH_STATE_END:
{
if (td->touch_down == 0)
{
rd->continues = EINA_FALSE;
memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Zoom_Data));
efl_gesture_manager_gesture_clean_up(rd->manager, watched, EFL_EVENT_GESTURE_ZOOM);
{
if (!efl_gesture_touch_multi_touch_get(event))
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
if ((pd->zoom_base) && (pd->zoom_distance_tolerance == 0))
{
memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Zoom_Data));
return EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
}
const Efl_Gesture_Touch_Point_Data *p1 = efl_gesture_touch_data_get(event, 0);
const Efl_Gesture_Touch_Point_Data *p2 = efl_gesture_touch_data_get(event, 1);
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE)
{
memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Zoom_Data));
memcpy(&pd->zoom_st, p2, sizeof(Efl_Gesture_Touch_Point_Data));
memcpy(&pd->zoom_st1, p1, sizeof(Efl_Gesture_Touch_Point_Data));
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
}
memcpy(&pd->zoom_mv, p2, sizeof(Efl_Gesture_Touch_Point_Data));
memcpy(&pd->zoom_mv1, p1, sizeof(Efl_Gesture_Touch_Point_Data));
int x, y; //Hot spot
zd->zoom = 1.0;
pd->zoom_base = _finger_gap_length_get(pd->zoom_st1.cur.pos.x,
pd->zoom_st1.cur.pos.y,
pd->zoom_st.cur.pos.x,
pd->zoom_st.cur.pos.y,
&x, &y);
zd->radius = pd->zoom_base / 2.0;
if ((efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_STARTED) &&
(efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_UPDATED))
return EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
const Efl_Gesture_Touch_Point_Data *p2 = efl_gesture_touch_data_get(event, 1);
if (p2->id == pd->zoom_mv.id)
memcpy(&pd->zoom_mv, p2, sizeof(Efl_Gesture_Touch_Point_Data));
else if (p2->id == pd->zoom_mv1.id)
memcpy(&pd->zoom_mv1, p2, sizeof(Efl_Gesture_Touch_Point_Data));
zd->zoom = _zoom_compute(pd, zd, pd->zoom_mv.cur.pos.x,
pd->zoom_mv.cur.pos.y, pd->zoom_mv1.cur.pos.x,
pd->zoom_mv1.cur.pos.y, pd->zoom_finger_factor);
if (!pd->zoom_distance_tolerance)
{
double d = zd->zoom - pd->next_step;
if (d < 0.0) d = (-d);
if (d >= pd->zoom_step)
{
pd->next_step = zd->zoom;
return EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
}
}
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
case EFL_GESTURE_TOUCH_STATE_END:
{
if (td->touch_down == 0)
{
rd->continues = EINA_FALSE;
_reset_recognizer(pd);
efl_gesture_manager_gesture_clean_up(efl_provider_find(obj, EFL_CANVAS_GESTURE_MANAGER_CLASS), watched, EFL_EVENT_GESTURE_ZOOM);
return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
}
if ((pd->zoom_base) && (pd->zoom_distance_tolerance == 0))
{
_reset_recognizer(pd);
return EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
}
if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE)
{
_reset_recognizer(pd);
return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
}
}
default:
break;
break;
}
return result;

View File

@ -6,32 +6,30 @@
//that are directed to a particular object from the
//first finger down to the last finger up
static void _hash_free_cb(Pointer_Data *point)
{
free(point);
}
static inline void
_touch_points_reset(Efl_Canvas_Gesture_Touch_Data *pd)
{
eina_hash_free(pd->touch_points);
pd->touch_points = eina_hash_int32_new(EINA_FREE_CB(_hash_free_cb));
while (eina_array_count(pd->touch_points))
free(eina_array_pop(pd->touch_points));
pd->touch_down = 0;
pd->prev_touch = pd->cur_touch = NULL;
pd->state = EFL_GESTURE_TOUCH_STATE_UNKNOWN;
}
EOLIAN static Efl_Object *
_efl_canvas_gesture_touch_efl_object_constructor(Eo *obj, Efl_Canvas_Gesture_Touch_Data *pd)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
_touch_points_reset(pd);
return obj;
pd->touch_points = eina_array_new(2);
EINA_SAFETY_ON_NULL_RETURN_VAL(pd->touch_points, NULL);
return efl_constructor(efl_super(obj, MY_CLASS));
}
EOLIAN static void
_efl_canvas_gesture_touch_efl_object_destructor(Eo *obj, Efl_Canvas_Gesture_Touch_Data *pd)
{
eina_hash_free(pd->touch_points);
while (eina_array_count(pd->touch_points))
free(eina_array_pop(pd->touch_points));
eina_array_free(pd->touch_points);
efl_destructor(efl_super(obj, MY_CLASS));
}
@ -50,20 +48,24 @@ _efl_canvas_gesture_touch_point_record(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_T
Efl_Pointer_Action action = pointer_data->action;
Eina_Vector2 pos = pointer_data->cur;
Pointer_Data *point = eina_hash_find(pd->touch_points, &id);
Eina_Position2D _pos = { pos.x, pos.y };
Efl_Gesture_Touch_Point_Data *point = NULL;
if (eina_array_count(pd->touch_points))
point = eina_array_data_get(pd->touch_points, id);
if (action == EFL_POINTER_ACTION_DOWN)
{
pd->touch_down++;
//TODO: Need to handle 2 or more case.
if (pd->touch_down == 2)
if ((!point) || (!point->cur.pressed))
pd->touch_down++;
if (pd->touch_down >= 2)
pd->multi_touch = EINA_TRUE;
}
else if ((action == EFL_POINTER_ACTION_UP) ||
(action == EFL_POINTER_ACTION_CANCEL))
{
pd->touch_down--;
if (point && point->cur.pressed)
pd->touch_down--;
if (pd->multi_touch && pd->touch_down == 1)
pd->multi_touch = EINA_FALSE;
}
@ -80,37 +82,40 @@ _efl_canvas_gesture_touch_point_record(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_T
else
{
//New finger
if (!id && (action != EFL_POINTER_ACTION_DOWN))
if (action != EFL_POINTER_ACTION_DOWN)
{
//Discard any other event
return;
}
point = calloc(1, sizeof(Pointer_Data));
point = calloc(1, sizeof(Efl_Gesture_Touch_Point_Data));
if (!point) return;
point->start.pos = point->prev.pos = point->cur.pos = _pos;
point->start.timestamp = point->prev.timestamp = point->cur.timestamp = timestamp;
point->id = id;
//Add to the hash
eina_hash_add(pd->touch_points, &id, point);
//FIXME: finger_list was broken
if (id)
pd->multi_touch = EINA_TRUE;
eina_array_push(pd->touch_points, point);
}
if (pd->cur_touch != point)
pd->prev_touch = pd->cur_touch;
pd->cur_touch = point;
point->action = action;
if (!id && (action == EFL_POINTER_ACTION_DOWN))
if (!id && (action == EFL_POINTER_ACTION_DOWN))
{
point->cur.pressed = EINA_TRUE;
pd->state = EFL_GESTURE_TOUCH_STATE_BEGIN;
}
else if (action == EFL_POINTER_ACTION_UP)
else if (action == EFL_POINTER_ACTION_UP)
{
point->cur.pressed = EINA_FALSE;
pd->state = EFL_GESTURE_TOUCH_STATE_END;
}
else
{
pd->state = EFL_GESTURE_TOUCH_STATE_UPDATE;
}
point->cur.pressed |= action == EFL_POINTER_ACTION_DOWN || action == EFL_POINTER_ACTION_MOVE;
return;
finished_touch:
@ -123,11 +128,34 @@ _efl_canvas_gesture_touch_multi_touch_get(const Eo *obj EINA_UNUSED, Efl_Canvas_
return pd->multi_touch;
}
EOLIAN static Eina_Position2D
_efl_canvas_gesture_touch_start_point_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
EOLIAN static unsigned int
_efl_canvas_gesture_touch_touch_points_count_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
{
int tool = 0;
Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
return pd->touch_down;
}
EOLIAN static const Efl_Gesture_Touch_Point_Data *
_efl_canvas_gesture_touch_cur_data_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
{
return pd->cur_touch;
}
EOLIAN static const Efl_Gesture_Touch_Point_Data *
_efl_canvas_gesture_touch_prev_data_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
{
return pd->prev_touch;
}
EOLIAN static const Efl_Gesture_Touch_Point_Data *
_efl_canvas_gesture_touch_data_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd, unsigned int id)
{
return eina_array_count(pd->touch_points) ? eina_array_data_get(pd->touch_points, id) : NULL;
}
EOLIAN static Eina_Position2D
_efl_canvas_gesture_touch_start_point_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd EINA_UNUSED)
{
const Efl_Gesture_Touch_Point_Data *point = efl_gesture_touch_data_get(obj, 0);
Eina_Position2D vec = { 0, 0 };
if (!point)
@ -139,8 +167,7 @@ _efl_canvas_gesture_touch_start_point_get(const Eo *obj EINA_UNUSED, Efl_Canvas_
EOLIAN static Eina_Position2D
_efl_canvas_gesture_touch_cur_point_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
{
int tool = 0;
Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
const Efl_Gesture_Touch_Point_Data *point = pd->cur_touch;
Eina_Position2D vec = { 0, 0 };
if (!point)
@ -152,8 +179,7 @@ _efl_canvas_gesture_touch_cur_point_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Ge
EOLIAN static unsigned int
_efl_canvas_gesture_touch_cur_timestamp_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd)
{
int tool = 0;
Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
const Efl_Gesture_Touch_Point_Data *point = pd->cur_touch;
if (!point)
return 0;
@ -164,11 +190,10 @@ _efl_canvas_gesture_touch_cur_timestamp_get(const Eo *obj EINA_UNUSED, Efl_Canva
EOLIAN static Eina_Vector2
_efl_canvas_gesture_touch_delta(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd, int tool)
{
Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
Efl_Gesture_Touch_Point_Data *point = eina_array_count(pd->touch_points) ? eina_array_data_get(pd->touch_points, tool) : NULL;
Eina_Vector2 vec = { 0, 0 };
if (!point)
return vec;
EINA_SAFETY_ON_NULL_RETURN_VAL(point, vec);
Eina_Vector2 v1 = { point->cur.pos.x, point->cur.pos.y };
Eina_Vector2 v2 = { point->prev.pos.x, point->prev.pos.y };
@ -180,11 +205,10 @@ _efl_canvas_gesture_touch_delta(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_To
EOLIAN static Eina_Vector2
_efl_canvas_gesture_touch_distance(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Touch_Data *pd, int tool)
{
Pointer_Data *point = eina_hash_find(pd->touch_points, &tool);
Efl_Gesture_Touch_Point_Data *point = eina_array_count(pd->touch_points) ? eina_array_data_get(pd->touch_points, tool) : NULL;
Eina_Vector2 vec = { 0, 0 };
if (!point)
return vec;
EINA_SAFETY_ON_NULL_RETURN_VAL(point, vec);
Eina_Vector2 v1 = { point->cur.pos.x, point->cur.pos.y };
Eina_Vector2 v2 = { point->start.pos.x, point->start.pos.y };

View File

@ -60,12 +60,43 @@ class @beta Efl.Canvas.Gesture_Touch extends Efl.Object
return: bool; [[returns $true if its a multi touch]]
}
}
@property touch_points_count {
[[This provides the number of touch points active.]]
get {
}
values {
touch_count: uint; [[The number of active touch points.]]
}
}
@property state {
[[This property holds the state of the touch event.]]
get {
return : Efl.Canvas.Gesture_Touch_State; [[touch event state]]
}
}
@property cur_data {
[[This property holds the data struct of the most recent touch point.]]
get {}
values {
data: const(Efl.Canvas.Gesture_Touch_Point_Data) @by_ref; [[The current data.]]
}
}
@property prev_data {
[[This property holds the data struct of the second-most recent touch point.
If there is only one touch point active, it will return NULL.
]]
get {}
values {
data: const(Efl.Canvas.Gesture_Touch_Point_Data) @by_ref; [[The previous touch point's data.]]
}
}
data_get @const {
[[This fetches the data for a specified touch point.]]
params {
@in id: uint; [[The id of the touch point to return.]]
}
return: const(Efl.Canvas.Gesture_Touch_Point_Data) @by_ref; [[The specified data if it exists.]]
}
/* FIXME: finger_list was broken by design - TODO */
}
implements {

View File

@ -1,3 +1,6 @@
import eina_types;
import efl_input_types;
enum @beta Efl.Canvas.Gesture_Touch_State
{
[[ This enum type describes the state of a touch event. ]]
@ -44,3 +47,19 @@ enum @beta Efl.Canvas.Gesture_Recognizer_Type
flick,
zoom,
}
struct @beta @c_name(Efl_Gesture_Touch_Point_Info) Efl.Canvas.Gesture_Touch_Point_Info {
[[This struct represents the underlying data of a touch point.]]
pos: Eina.Position2D; [[The canvas position of the touch point data.]]
pressed: bool; [[Whether this touch point is being pressed down.]]
timestamp: uint; [[The timestamp of the touch point data.]]
}
struct @beta @c_name(Efl_Gesture_Touch_Point_Data) Efl.Canvas.Gesture_Touch_Point_Data {
[[This struct represents the state of a touch point.]]
id: int; [[Touch id of the point.]]
action: Efl.Pointer.Action; [[The last event with this point.]]
start: Efl.Canvas.Gesture_Touch_Point_Info; [[The start data for the touch point.]]
prev: Efl.Canvas.Gesture_Touch_Point_Info; [[The previous data for the touch point.]]
cur: Efl.Canvas.Gesture_Touch_Point_Info; [[The current data for the touch point.]]
}

View File

@ -14,6 +14,7 @@ static const Efl_Test_Case etc[] = {
{ "efl_ui_config", efl_ui_test_config},
{ "efl_ui_focus", efl_ui_test_focus},
{ "efl_ui_focus_sub", efl_ui_test_focus_sub},
{ "efl_ui_gesture", efl_ui_test_gesture},
{ "efl_ui_box", efl_ui_test_box},
{ "efl_ui_box_flow", efl_ui_test_box_flow},
{ "efl_ui_box_stack", efl_ui_test_box_stack},

View File

@ -33,6 +33,7 @@ void efl_ui_test_image(TCase *tc);
void efl_ui_test_callback(TCase *tc);
void efl_ui_test_focus(TCase *tc);
void efl_ui_test_focus_sub(TCase *tc);
void efl_ui_test_gesture(TCase *tc);
void efl_ui_model(TCase *tc);
void efl_ui_test_widget(TCase *tc);
void efl_ui_test_spotlight(TCase *tc);

View File

@ -0,0 +1,507 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Efl_Ui.h>
#include "efl_ui_suite.h"
/* mouse feeding */
#include <Evas_Legacy.h>
#include <evas_canvas_eo.h>
/*
typedef enum
{
EFL_GESTURE_STATE_NONE = 0,
EFL_GESTURE_STATE_STARTED = 1,
EFL_GESTURE_STATE_UPDATED,
EFL_GESTURE_STATE_FINISHED,
EFL_GESTURE_STATE_CANCELED
} Efl_Canvas_Gesture_State;
*/
enum
{
TAP,
LONG_TAP,
DOUBLE_TAP,
TRIPLE_TAP,
MOMENTUM,
FLICK,
ZOOM,
LAST
};
static int count[LAST][4] = {0};
/* macros to simplify checking gesture counts */
#define CHECK_START(type, val) \
ck_assert_int_eq(count[(type)][EFL_GESTURE_STATE_STARTED - 1], (val))
#define CHECK_UPDATE(type, val) \
ck_assert_int_eq(count[(type)][EFL_GESTURE_STATE_UPDATED - 1], (val))
#define CHECK_FINISH(type, val) \
ck_assert_int_eq(count[(type)][EFL_GESTURE_STATE_FINISHED - 1], (val))
#define CHECK_CANCEL(type, val) \
ck_assert_int_eq(count[(type)][EFL_GESTURE_STATE_CANCELED - 1], (val))
#define CHECK_ALL(type, ...) \
do {\
int state_vals[] = {__VA_ARGS__}; \
for (int i = 0; i < 4; i++) \
ck_assert_int_eq(count[(type)][i], state_vals[i]); \
} while (0)
#define CHECK_NONZERO(type) \
do {\
for (int i = 0; i < 4; i++) \
ck_assert_int_ne(count[(type)][i], 0); \
} while (0)
#define CHECK_ZERO(type) CHECK_ALL((type), 0, 0, 0, 0)
#define RESET memset(count, 0, sizeof(count))
static void
gesture_cb(void *data , const Efl_Event *ev)
{
Efl_Canvas_Gesture *g = ev->info;
int *count = data;
/* increment counter for event state which has been processed */
count[efl_gesture_state_get(g) - 1]++;
}
static void
test_cb(void *data EINA_UNUSED , const Efl_Event *ev EINA_UNUSED)
{
}
static Eo *
setup(void)
{
Eo *win, *rect;
RESET;
win = win_add();
efl_gfx_entity_size_set(win, EINA_SIZE2D(1000, 1000));
rect = efl_add(EFL_CANVAS_RECTANGLE_CLASS, win);
efl_content_set(win, rect);
/* add extra random cb to verify that we aren't getting double events */
efl_event_callback_add(rect, EFL_EVENT_GESTURE_MOMENTUM, test_cb, NULL);
#define WATCH(type) \
efl_event_callback_add(rect, EFL_EVENT_GESTURE_##type, gesture_cb, &count[(type)])
WATCH(TAP);
WATCH(LONG_TAP);
WATCH(DOUBLE_TAP);
WATCH(TRIPLE_TAP);
WATCH(MOMENTUM);
WATCH(FLICK);
WATCH(ZOOM);
get_me_to_those_events(win);
return rect;
}
EFL_START_TEST(test_efl_ui_gesture_taps)
{
Eo *rect = setup();
/* basic tap */
click_object(rect);
CHECK_ALL(TAP, 1, 0, 1, 0);
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
CHECK_ALL(DOUBLE_TAP, 1, 1, 0, 0);
CHECK_ALL(TRIPLE_TAP, 1, 1, 0, 0);
CHECK_ZERO(MOMENTUM);
CHECK_ZERO(FLICK);
CHECK_ZERO(ZOOM);
RESET;
/* add a second tap */
click_object(rect);
CHECK_ALL(TAP, 1, 0, 1, 0);
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* UPDATE -> FINISH */
CHECK_ALL(DOUBLE_TAP, 0, 1, 1, 0);
CHECK_ALL(TRIPLE_TAP, 0, 2, 0, 0);
CHECK_ZERO(MOMENTUM);
CHECK_ZERO(FLICK);
CHECK_ZERO(ZOOM);
RESET;
/* add a third tap */
click_object(rect);
CHECK_ALL(TAP, 1, 0, 1, 0);
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* UPDATE -> FINISH */
CHECK_ALL(DOUBLE_TAP, 1, 1, 0, 0);
CHECK_ALL(TRIPLE_TAP, 0, 1, 1, 0);
CHECK_ZERO(MOMENTUM);
CHECK_ZERO(FLICK);
CHECK_ZERO(ZOOM);
/* clear states */
wait_timer(0.4);
RESET;
/* verify multiple simultaneous presses treated as same press */
multi_click_object(rect, 2);
CHECK_ALL(TAP, 1, 0, 1, 0);
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
CHECK_ALL(DOUBLE_TAP, 1, 1, 0, 0);
CHECK_ALL(TRIPLE_TAP, 1, 1, 0, 0);
CHECK_ZERO(MOMENTUM);
CHECK_ZERO(FLICK);
/* this is two fingers, so we have a zoom start */
CHECK_ALL(ZOOM, 1, 0, 0, 1);
RESET;
multi_click_object(rect, 2);
CHECK_ALL(TAP, 1, 0, 1, 0);
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* UPDATE -> FINISH */
CHECK_ALL(DOUBLE_TAP, 0, 1, 1, 0);
CHECK_ALL(TRIPLE_TAP, 0, 2, 0, 0);
CHECK_ZERO(MOMENTUM);
CHECK_ZERO(FLICK);
/* this is two fingers, so we have a zoom start */
CHECK_ALL(ZOOM, 1, 0, 0, 1);
RESET;
multi_click_object(rect, 2);
CHECK_ALL(TAP, 1, 0, 1, 0);
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* UPDATE -> FINISH */
CHECK_ALL(DOUBLE_TAP, 1, 1, 0, 0);
CHECK_ALL(TRIPLE_TAP, 0, 1, 1, 0);
CHECK_ZERO(MOMENTUM);
CHECK_ZERO(FLICK);
/* this is two fingers, so we have a zoom start */
CHECK_ALL(ZOOM, 1, 0, 0, 1);
/* clear states */
wait_timer(0.4);
RESET;
}
EFL_END_TEST
EFL_START_TEST(test_efl_ui_gesture_long_tap)
{
Eo *rect = setup();
double timeout = 1.2;
Eina_Value *val;
Eo *e = efl_provider_find(rect, EVAS_CANVAS_CLASS);
val = efl_gesture_manager_config_get(efl_provider_find(rect, EFL_CANVAS_GESTURE_MANAGER_CLASS), "glayer_long_tap_start_timeout");
eina_value_get(val, &timeout);
/* press */
press_object(rect);
CHECK_ALL(TAP, 1, 0, 0, 0);
CHECK_ALL(LONG_TAP, 1, 0, 0, 0);
CHECK_ALL(DOUBLE_TAP, 1, 0, 0, 0);
CHECK_ALL(TRIPLE_TAP, 1, 0, 0, 0);
CHECK_ZERO(MOMENTUM);
CHECK_ZERO(FLICK);
CHECK_ZERO(ZOOM);
RESET;
wait_timer(timeout + 0.01);
/* verify longpress */
CHECK_ALL(TAP, 0, 0, 0, 1);
CHECK_ALL(LONG_TAP, 0, 1, 0, 0);
CHECK_ALL(DOUBLE_TAP, 0, 0, 0, 1);
CHECK_ALL(TRIPLE_TAP, 0, 0, 0, 1);
CHECK_ZERO(MOMENTUM);
CHECK_ZERO(FLICK);
CHECK_ZERO(ZOOM);
RESET;
evas_event_feed_mouse_up(e, 1, 0, 2, NULL);
CHECK_ZERO(TAP);
CHECK_ALL(LONG_TAP, 0, 0, 1, 0);
CHECK_ZERO(DOUBLE_TAP);
CHECK_ZERO(TRIPLE_TAP);
CHECK_ZERO(MOMENTUM);
CHECK_ZERO(FLICK);
CHECK_ZERO(ZOOM);
RESET;
press_object_at(rect, 0, 0);
RESET;
/* move off-canvas */
evas_event_feed_mouse_move(e, -1, 0, 2, NULL);
wait_timer(timeout + 0.01);
/* verify longpress */
CHECK_ALL(TAP, 0, 1, 0, 0);
CHECK_ALL(LONG_TAP, 0, 1, 0, 0);
CHECK_ALL(DOUBLE_TAP, 0, 0, 0, 1);
CHECK_ALL(TRIPLE_TAP, 0, 0, 0, 1);
CHECK_ALL(MOMENTUM, 1, 0, 0, 0);
CHECK_ALL(FLICK, 1, 0, 0, 0);
CHECK_ZERO(ZOOM);
RESET;
evas_event_feed_mouse_up(e, 1, 0, 3, NULL);
}
EFL_END_TEST
EFL_START_TEST(test_efl_ui_gesture_flick)
{
int moves, i;
Eo *rect = setup();
/* basic flick */
drag_object(rect, 0, 0, 75, 0, EINA_FALSE);
/* canceled */
CHECK_ALL(TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(DOUBLE_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(TRIPLE_TAP, 1, 0, 0, 1);
/* updated but canceled */
CHECK_ALL(MOMENTUM, 1, DRAG_OBJECT_NUM_MOVES - 1, 0, 1);
/* triggered */
CHECK_ALL(FLICK, 1, DRAG_OBJECT_NUM_MOVES - 1, 1, 0);
CHECK_ZERO(ZOOM);
RESET;
/* reverse flick */
drag_object(rect, 75, 0, -75, 0, EINA_FALSE);
/* canceled */
CHECK_ALL(TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(DOUBLE_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(TRIPLE_TAP, 1, 0, 0, 1);
/* updated but canceled */
CHECK_ALL(MOMENTUM, 1, DRAG_OBJECT_NUM_MOVES - 1, 0, 1);
/* triggered */
CHECK_ALL(FLICK, 1, DRAG_OBJECT_NUM_MOVES - 1, 1, 0);
CHECK_ZERO(ZOOM);
RESET;
/* vertical flick */
drag_object(rect, 0, 0, 0, 75, EINA_FALSE);
/* canceled */
CHECK_ALL(TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(DOUBLE_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(TRIPLE_TAP, 1, 0, 0, 1);
/* updated but canceled */
CHECK_ALL(MOMENTUM, 1, DRAG_OBJECT_NUM_MOVES - 1, 0, 1);
/* triggered */
CHECK_ALL(FLICK, 1, DRAG_OBJECT_NUM_MOVES - 1, 1, 0);
CHECK_ZERO(ZOOM);
RESET;
/* reverse vertical flick */
drag_object(rect, 0, 75, 0, -75, EINA_FALSE);
/* canceled */
CHECK_ALL(TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(DOUBLE_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(TRIPLE_TAP, 1, 0, 0, 1);
/* updated but canceled */
CHECK_ALL(MOMENTUM, 1, DRAG_OBJECT_NUM_MOVES - 1, 0, 1);
/* triggered */
CHECK_ALL(FLICK, 1, DRAG_OBJECT_NUM_MOVES - 1, 1, 0);
CHECK_ZERO(ZOOM);
RESET;
/* diagonal flick */
drag_object(rect, 0, 0, 75, 75, EINA_FALSE);
/* canceled */
CHECK_ALL(TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(DOUBLE_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(TRIPLE_TAP, 1, 0, 0, 1);
/* updated but canceled */
CHECK_ALL(MOMENTUM, 1, DRAG_OBJECT_NUM_MOVES - 1, 0, 1);
/* triggered */
CHECK_ALL(FLICK, 1, DRAG_OBJECT_NUM_MOVES - 1, 1, 0);
CHECK_ZERO(ZOOM);
RESET;
/* off-canvas flick */
drag_object(rect, 999, 0, 50, 0, EINA_FALSE);
/* canceled */
CHECK_ALL(TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(DOUBLE_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(TRIPLE_TAP, 1, 0, 0, 1);
CHECK_START(MOMENTUM, 1);
CHECK_FINISH(MOMENTUM, 0);
CHECK_CANCEL(MOMENTUM, 1);
CHECK_START(FLICK, 1);
CHECK_FINISH(FLICK, 1);
CHECK_CANCEL(FLICK, 0);
CHECK_ZERO(ZOOM);
RESET;
/* definitely not a flick */
moves = drag_object_around(rect, 500, 500, 450, 180);
for (i = 0; i <= TRIPLE_TAP; i++)
{
/* canceled */
CHECK_START(TAP, 1);
CHECK_CANCEL(TAP, 1);
}
/* completed: a momentum gesture is any completed motion */
CHECK_ALL(MOMENTUM, 1, moves - 2, 1, 0);
/* NOT triggered; this is going to have some crazy number of update events since it ignores a bunch */
CHECK_FINISH(FLICK, 0);
CHECK_ZERO(ZOOM);
RESET;
/* definitely not a flick, also outside canvas */
moves = drag_object_around(rect, 25, 50, 50, 180);
for (i = 0; i <= TRIPLE_TAP; i++)
{
/* canceled */
CHECK_START(TAP, 1);
CHECK_CANCEL(TAP, 1);
}
/* momentum should only begin at the initial press or if canceled due to timeout */
CHECK_START(MOMENTUM, 1);
CHECK_FINISH(MOMENTUM, 1);
/* canceled: the motion ends outside the canvas, so there is no momentum */
CHECK_CANCEL(MOMENTUM, 0);
/* flick checks a tolerance value for straight lines, so "start" will be >= 1 */
ck_assert_int_ge(count[FLICK][EFL_GESTURE_STATE_STARTED - 1], 1);
CHECK_FINISH(FLICK, 0);
/* flick checks a tolerance value for straight lines, so "start" will be >= 1 */
ck_assert_int_ge(count[FLICK][EFL_GESTURE_STATE_CANCELED - 1], 1);
CHECK_ZERO(ZOOM);
RESET;
/* definitely not a flick, test re-entering canvas */
moves = drag_object_around(rect, 500, 750, 400, 180);
for (i = 0; i <= TRIPLE_TAP; i++)
{
/* canceled */
CHECK_START(TAP, 1);
CHECK_CANCEL(TAP, 1);
}
/* momentum should only begin at the initial press or if canceled due to timeout */
CHECK_START(MOMENTUM, 1);
/* finished: the motion ends outside the canvas, but we still count it */
CHECK_FINISH(MOMENTUM, 1);
CHECK_CANCEL(MOMENTUM, 0);
/* flick checks a tolerance value for straight lines, so "start" will be >= 1 */
ck_assert_int_ge(count[FLICK][EFL_GESTURE_STATE_STARTED - 1], 1);
CHECK_FINISH(FLICK, 0);
/* flick checks a tolerance value for straight lines, so "start" will be >= 1 */
ck_assert_int_ge(count[FLICK][EFL_GESTURE_STATE_CANCELED - 1], 1);
CHECK_ZERO(ZOOM);
RESET;
}
EFL_END_TEST
EFL_START_TEST(test_efl_ui_gesture_zoom)
{
Eo *rect = setup();
int moves;
moves = pinch_object(rect, 500, 500, 501, 501, -250, -250, 250, 250);
/* canceled */
CHECK_ALL(TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(DOUBLE_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(TRIPLE_TAP, 1, 0, 0, 1);
CHECK_START(MOMENTUM, 1);
CHECK_UPDATE(MOMENTUM, moves * 2 + 1);
CHECK_FINISH(MOMENTUM, 0);
CHECK_CANCEL(MOMENTUM, 1);
/* only finish is verifiable */
CHECK_FINISH(FLICK, 0);
/* started 1x */
CHECK_START(ZOOM, 1);
/* 2 touch points tracked, so this will be roughly (2 * moves) but probably less */
ck_assert_int_ge(count[ZOOM][EFL_GESTURE_STATE_UPDATED - 1], moves);
/* finished 1x */
CHECK_FINISH(ZOOM, 1);
CHECK_CANCEL(ZOOM, 0);
RESET;
moves = pinch_object(rect, 250, 250, 750, 750, 250, 250, -250, -250);
/* canceled */
CHECK_ALL(TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(LONG_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(DOUBLE_TAP, 1, 0, 0, 1);
/* canceled */
CHECK_ALL(TRIPLE_TAP, 1, 0, 0, 1);
CHECK_START(MOMENTUM, 1);
CHECK_UPDATE(MOMENTUM, moves * 2 + 1);
CHECK_FINISH(MOMENTUM, 0);
CHECK_CANCEL(MOMENTUM, 1);
/* only finish is verifiable */
CHECK_FINISH(FLICK, 0);
/* started 1x */
CHECK_START(ZOOM, 1);
/* 2 touch points tracked, so this will be roughly (2 * moves) but probably less */
ck_assert_int_ge(count[ZOOM][EFL_GESTURE_STATE_UPDATED - 1], moves);
/* finished 1x */
CHECK_FINISH(ZOOM, 1);
CHECK_CANCEL(ZOOM, 0);
RESET;
}
EFL_END_TEST
void efl_ui_test_gesture(TCase *tc)
{
tcase_add_test(tc, test_efl_ui_gesture_taps);
tcase_add_test(tc, test_efl_ui_gesture_long_tap);
tcase_add_test(tc, test_efl_ui_gesture_flick);
tcase_add_test(tc, test_efl_ui_gesture_zoom);
}

View File

@ -129,6 +129,7 @@ efl_ui_suite_src = [
'efl_ui_test_focus_common.h',
'efl_ui_test_focus.c',
'efl_ui_test_focus_sub.c',
'efl_ui_test_gesture.c',
'efl_ui_test_box.c',
'efl_ui_test_box_flow.c',
'efl_ui_test_box_stack.c',

View File

@ -19,6 +19,7 @@ static Eina_Bool buffer = EINA_FALSE;
static Eina_Bool legacy_mode = EINA_FALSE;
static int log_abort;
static int log_abort_level;
static unsigned int ts = 1;
Eina_Bool abort_on_warnings = EINA_FALSE;
@ -50,6 +51,7 @@ _elm2_suite_init(void)
ck_assert_int_eq(elm_init(1, args), 1);
if (abort_on_warnings)
fail_on_errors_setup();
ts = 1;
}
void
@ -142,6 +144,20 @@ real_timer_add(double in, Ecore_Task_Cb cb, void *data)
return ecore_timer_add(in, cb, data);
}
static Eina_Bool
_timer_quit()
{
ecore_main_loop_quit();
return EINA_FALSE;
}
void
wait_timer(double in)
{
ecore_timer_add(in, _timer_quit, NULL);
ecore_main_loop_begin();
}
static void
_win_manual_render(void *data, const Efl_Event *event EINA_UNUSED)
{
@ -450,29 +466,42 @@ attempt_to_find_the_right_point_for_mouse_positioning(Eo *obj, int dir)
}
static void
click_object_internal(Eo *obj, int dir, int flags)
click_object_internal(Eo *obj, int dir, int flags, Eina_Bool up)
{
Evas *e = evas_object_evas_get(obj);
Eina_Position2D pos = attempt_to_find_the_right_point_for_mouse_positioning(obj, dir);
evas_event_feed_mouse_move(e, pos.x, pos.y, 0, NULL);
evas_event_feed_mouse_down(e, 1, flags, 0, NULL);
evas_event_feed_mouse_up(e, 1, 0, 0, NULL);
evas_event_feed_mouse_move(e, pos.x, pos.y, ts++, NULL);
evas_event_feed_mouse_down(e, 1, flags, ts++, NULL);
if (up)
evas_event_feed_mouse_up(e, 1, 0, ts++, NULL);
}
void
click_object(Eo *obj)
{
click_object_internal(obj, NONE, 0);
click_object_internal(obj, NONE, 0, EINA_TRUE);
}
void
press_object(Eo *obj)
{
click_object_internal(obj, NONE, 0, EINA_FALSE);
}
void
click_object_flags(Eo *obj, int flags)
{
click_object_internal(obj, NONE, flags);
click_object_internal(obj, NONE, flags, EINA_TRUE);
}
void
click_part_flags(Eo *obj, const char *part, int flags)
press_object_flags(Eo *obj, int flags)
{
click_object_internal(obj, NONE, flags, EINA_FALSE);
}
static void
click_part_flags_internal(Eo *obj, const char *part, int flags, Eina_Bool up)
{
Efl_Part *part_obj = efl_ref(efl_part(obj, part));
Eo *content;
@ -492,19 +521,37 @@ click_part_flags(Eo *obj, const char *part, int flags)
else if (strstr(part, "bottom"))
dir |= BOTTOM;
}
click_object_internal(content, dir, flags);
click_object_internal(content, dir, flags, up);
if (efl_isa(content, EFL_LAYOUT_SIGNAL_INTERFACE))
edje_object_message_signal_process(content);
edje_object_message_signal_process(obj);
efl_unref(part_obj);
}
void
click_part_flags(Eo *obj, const char *part, int flags)
{
click_part_flags_internal(obj, part, flags, EINA_TRUE);
}
void
press_part_flags(Eo *obj, const char *part, int flags)
{
click_part_flags_internal(obj, part, flags, EINA_FALSE);
}
void
click_part(Eo *obj, const char *part)
{
click_part_flags(obj, part, 0);
}
void
press_part(Eo *obj, const char *part)
{
press_part_flags(obj, part, 0);
}
static void
wheel_object_internal(Eo *obj, int dir, Eina_Bool horiz, Eina_Bool down)
{
@ -573,18 +620,77 @@ void
click_object_at(Eo *obj, int x, int y)
{
Evas *e = evas_object_evas_get(obj);
evas_event_feed_mouse_move(e, x, y, 0, NULL);
evas_event_feed_mouse_down(e, 1, 0, 0, NULL);
evas_event_feed_mouse_up(e, 1, 0, 0, NULL);
evas_event_feed_mouse_move(e, x, y, ts++, NULL);
evas_event_feed_mouse_down(e, 1, 0, ts++, NULL);
evas_event_feed_mouse_up(e, 1, 0, ts++, NULL);
}
void
multi_click_object(Eo *obj, int ids)
{
Evas *e = evas_object_evas_get(obj);
Eina_Position2D pos = attempt_to_find_the_right_point_for_mouse_positioning(obj, NONE);
for (int i = 0; i < ids; i++)
evas_event_feed_multi_down(e, i, pos.x + i, pos.y + i, 1, 1, 1, 1, 0, pos.x + i, pos.y + i, 0, ts, NULL);
ts++;
for (int i = 0; i < ids; i++)
evas_event_feed_multi_up(e, i, pos.x + i, pos.y + i, 1, 1, 1, 1, 0, pos.x + i, pos.y + i, 0, ts, NULL);
}
void
multi_press_object(Eo *obj, int ids)
{
Evas *e = evas_object_evas_get(obj);
Eina_Position2D pos = attempt_to_find_the_right_point_for_mouse_positioning(obj, NONE);
for (int i = 0; i < ids; i++)
evas_event_feed_multi_down(e, i, pos.x + i, pos.y + i, 1, 1, 1, 1, 0, pos.x + i, pos.y + i, 0, ts, NULL);
ts++;
}
void
multi_click_object_at(Eo *obj, int x, int y, int ids)
{
Evas *e = evas_object_evas_get(obj);
for (int i = 0; i < ids; i++)
evas_event_feed_multi_down(e, i, x + i, y + i, 1, 1, 1, 1, 0, x + i, y + i, 0, ts, NULL);
ts++;
for (int i = 0; i < ids; i++)
evas_event_feed_multi_up(e, i, x + i, y + i, 1, 1, 1, 1, 0, x + i, y + i, 0, ts, NULL);
ts++;
}
void
press_object_at(Eo *obj, int x, int y)
{
Evas *e = evas_object_evas_get(obj);
evas_event_feed_mouse_move(e, x, y, ts++, NULL);
evas_event_feed_mouse_down(e, 1, 0, ts++, NULL);
}
void
multi_press_object_at(Eo *obj, int x, int y, int ids)
{
Evas *e = evas_object_evas_get(obj);
for (int i = 0; i < ids; i++)
evas_event_feed_multi_down(e, i, x + i, y + i, 1, 1, 1, 1, 0, x + i, y + i, 0, ts, NULL);
ts++;
}
void
click_object_at_flags(Eo *obj, int x, int y, int flags)
{
Evas *e = evas_object_evas_get(obj);
evas_event_feed_mouse_move(e, x, y, 0, NULL);
evas_event_feed_mouse_down(e, 1, flags, 0, NULL);
evas_event_feed_mouse_up(e, 1, 0, 0, NULL);
evas_event_feed_mouse_move(e, x, y, ts++, NULL);
evas_event_feed_mouse_down(e, 1, flags, ts++, NULL);
evas_event_feed_mouse_up(e, 1, 0, ts++, NULL);
}
void
press_object_at_flags(Eo *obj, int x, int y, int flags)
{
Evas *e = evas_object_evas_get(obj);
evas_event_feed_mouse_move(e, x, y, ts++, NULL);
evas_event_feed_mouse_down(e, 1, flags, ts++, NULL);
}
void
@ -600,8 +706,8 @@ drag_object(Eo *obj, int x, int y, int dx, int dy, Eina_Bool iterate)
{
Evas *e = evas_object_evas_get(obj);
int i;
evas_event_feed_mouse_move(e, x, y, 0, NULL);
evas_event_feed_mouse_down(e, 1, 0, 0, NULL);
evas_event_feed_mouse_move(e, x, y, ts++, NULL);
evas_event_feed_mouse_down(e, 1, 0, ts++, NULL);
if (iterate)
{
/* iterate twice to trigger timers */
@ -611,10 +717,64 @@ drag_object(Eo *obj, int x, int y, int dx, int dy, Eina_Bool iterate)
/* create DRAG_OBJECT_NUM_MOVES move events distinct from up/down */
for (i = 0; i < DRAG_OBJECT_NUM_MOVES; i++)
{
evas_event_feed_mouse_move(e, x + (i * dx / DRAG_OBJECT_NUM_MOVES), y + (i * dy / DRAG_OBJECT_NUM_MOVES), 0, NULL);
evas_event_feed_mouse_move(e, x + (i * dx / DRAG_OBJECT_NUM_MOVES), y + (i * dy / DRAG_OBJECT_NUM_MOVES), ts++, NULL);
/* also trigger smart calc if we're iterating just in case that's important */
evas_smart_objects_calculate(e);
}
evas_event_feed_mouse_move(e, x + dx, y + dy, 0, NULL);
evas_event_feed_mouse_up(e, 1, 0, 0, NULL);
evas_event_feed_mouse_move(e, x + dx, y + dy, ts++, NULL);
evas_event_feed_mouse_up(e, 1, 0, ts++, NULL);
}
int
drag_object_around(Eo *obj, int cx, int cy, int radius, int degrees)
{
Evas *e = evas_object_evas_get(obj);
/* clamp num mouse moves to a vaguely sane value */
int i, num = MIN(degrees, DRAG_OBJECT_AROUND_NUM_MOVES);
int last_x = round(cx + radius);
int last_y = round(cy);
/* start at 0 degrees */
evas_event_feed_mouse_move(e, last_x, last_y, ts++, NULL);
evas_event_feed_mouse_down(e, 1, 0, ts++, NULL);
for (i = 1; i < num; i++)
{
/* x = cx + r * cos(a), y = cy + r * sin(a) */
int ax, ay;
/* each iteration is 1 degree */
double angle = (i * (degrees / DRAG_OBJECT_AROUND_NUM_MOVES)) * M_PI / 180.0;
ax = round(cx + radius * cos(angle));
ay = round(cy + radius * sin(angle));
if ((ax == last_x) && (ay == last_y)) continue;
evas_event_feed_mouse_move(e, ax, ay, ts++, NULL);
last_x = ax, last_y = ay;
}
evas_event_feed_mouse_up(e, 1, 0, ts++, NULL);
/* only count arc motion: subtract initial move, mouse down, mouse up */
return num;
}
int
pinch_object(Eo *obj, int x, int y, int x2, int y2, int dx, int dy, int dx2, int dy2)
{
Evas *e = evas_object_evas_get(obj);
int i, idx, idy, idx2, idy2;
evas_event_feed_multi_down(e, 0, x, y, 1, 1, 1, 1, 0, x, y, 0, ts, NULL);
evas_event_feed_multi_down(e, 1, x2, y2, 1, 1, 1, 1, 0, x2, y2, 0, ts++, NULL);
for (i = 1; i < abs(dx); i++)
{
idx = (i * dx / abs(dx));
idy = (i * dy / abs(dx));
idx2 = (i * dx2 / abs(dx));
idy2 = (i * dy2 / abs(dx));
/* move first point along positive vector */
evas_event_feed_multi_move(e, 0, x + idx, y + idy, 1, 1, 1, 1, 0, x + idx, y + idy, ts, NULL);
/* move second point along negative vector */
evas_event_feed_multi_move(e, 1, x2 + idx2, y2 + idy2, 1, 1, 1, 1, 0, x2 + idx2, y2 + idy2, ts++, NULL);
/* also trigger smart calc if we're iterating just in case that's important */
evas_smart_objects_calculate(e);
}
evas_event_feed_multi_up(e, 0, x + idx, y + idy, 1, 1, 1, 1, 0, x + idx, y + idy, 0, ts, NULL);
evas_event_feed_multi_up(e, 1, x2 + idx2, y2 + idy2, 1, 1, 1, 1, 0, x2 + idx2, y2 + idy2, 0, ts++, NULL);
return i - 2;
}

View File

@ -4,11 +4,13 @@
#include <Evas.h>
#define DRAG_OBJECT_NUM_MOVES 4
#define DRAG_OBJECT_AROUND_NUM_MOVES 60
int suite_setup(Eina_Bool legacy);
void _elm2_suite_init(void);
void _elm_suite_shutdown(void);
void *real_timer_add(double in, Ecore_Task_Cb cb, void *data);
void wait_timer(double in);
void fail_on_errors_teardown(void);
void fail_on_errors_setup(void);
Eina_Bool is_forked(void);
@ -22,7 +24,19 @@ void click_part(Eo *obj, const char *part);
void click_part_flags(Eo *obj, const char *part, int flags);
void click_object_at(Eo *obj, int x, int y);
void click_object_at_flags(Eo *obj, int x, int y, int flags);
void press_object(Eo *obj);
void press_object_flags(Eo *obj, int flags);
void press_part(Eo *obj, const char *part);
void press_part_flags(Eo *obj, const char *part, int flags);
void press_object_at(Eo *obj, int x, int y);
void press_object_at_flags(Eo *obj, int x, int y, int flags);
void multi_click_object(Eo *obj, int ids);
void multi_press_object(Eo *obj, int ids);
void multi_click_object_at(Eo *obj, int x, int y, int ids);
void multi_press_object_at(Eo *obj, int x, int y, int ids);
void drag_object(Eo *obj, int x, int y, int dx, int dy, Eina_Bool iterate);
int drag_object_around(Eo *obj, int cx, int cy, int radius, int degrees);
int pinch_object(Eo *obj, int x, int y, int x2, int y2, int dx, int dy, int dx2, int dy2);
void wheel_object(Eo *obj, Eina_Bool horiz, Eina_Bool down);
void wheel_part(Eo *obj, const char *part, Eina_Bool horiz, Eina_Bool down);
void wheel_object_at(Eo *obj, int x, int y, Eina_Bool horiz, Eina_Bool down);