win: Add EO API to query state of multi touch points

This combines evas canvas functions to list and query
touch points into a single iterator:
 - evas_touch_point_list_count
 - evas_touch_point_list_nth_xy_get
 - evas_touch_point_list_nth_id_get
 - evas_touch_point_list_nth_state_get

This also fixes a number of issues related to feeding fake
input events.

Note: I wanted to add delta x,y information as well but it's
in fact not really possible outside the event callback itself,
as the previous x,y position will not be updated unless there's
an event.

@feature
This commit is contained in:
Jean-Philippe Andre 2016-08-31 15:41:12 +09:00
parent e61b7139ff
commit b3993b684e
10 changed files with 442 additions and 97 deletions

View File

@ -4,7 +4,8 @@ enum Efl.Pointer.Action
@since 1.19
]]
none, [[Not a valid event.]]
none, [[Not a valid event, or nothing new happened (eg. when querying
current state of touch points).]]
move, [[Mouse or equivalent pointer moved.]]
down, [[Mouse button or equivalent pointer pressed down.
Always followed by up or cancel.]]

View File

@ -4,7 +4,7 @@
#define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
#define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
#define ELM_WIN_PROTECTED
#define EFL_INPUT_EVENT_PROTECTED
#include <Elementary.h>
#include <Elementary_Cursor.h>
@ -89,6 +89,7 @@ static const Elm_Win_Trap *trap = NULL;
typedef struct _Efl_Ui_Win_Data Efl_Ui_Win_Data;
typedef struct _Box_Item_Iterator Box_Item_Iterator;
typedef struct _Input_Pointer_Iterator Input_Pointer_Iterator;
struct _Efl_Ui_Win_Data
{
@ -223,6 +224,9 @@ struct _Efl_Ui_Win_Data
short pointer_out;
short pointer_cancel;
short pointer_wheel;
short finger_move;
short finger_down;
short finger_up;
short key_down;
short key_up;
short render_pre;
@ -261,6 +265,14 @@ struct _Box_Item_Iterator
Eo *object;
};
struct _Input_Pointer_Iterator
{
Eina_Iterator iterator;
Eina_List *list;
Eina_Iterator *real_iterator;
const Eo *object;
};
static const char SIG_DELETE_REQUEST[] = "delete,request";
static const char SIG_FOCUS_OUT[] = "focus,out"; // deprecated. use "unfocused" instead.
static const char SIG_FOCUS_IN[] = "focus,in"; // deprecated. use "focused" instead.
@ -1678,7 +1690,7 @@ _evas_event_key_cb(void *data, const Efl_Event *ev)
if (evas_focus_get(evas_object_evas_get(win)) == win)
return;
efl_event_callback_legacy_call(win, ev->desc, evt);
efl_event_callback_call(win, ev->desc, evt);
}
static void
@ -1692,7 +1704,7 @@ _evas_event_pointer_cb(void *data, const Efl_Event *ev)
if (!evdata || evdata->win_fed)
return;
efl_event_callback_legacy_call(win, ev->desc, evt);
efl_event_callback_call(win, ev->desc, evt);
}
/* feed events from the window to evas - for fake inputs */
@ -1711,7 +1723,7 @@ _evas_event_key_feed_fake_cb(void *data, const Efl_Event *ev)
return;
evdata->win_fed = EINA_TRUE;
efl_event_callback_legacy_call(evas, ev->desc, evt);
efl_event_callback_call(evas, ev->desc, evt);
evdata->win_fed = EINA_FALSE;
evdata->evas_done = EINA_FALSE;
}
@ -1731,7 +1743,7 @@ _evas_event_pointer_feed_fake_cb(void *data, const Efl_Event *ev)
return;
evdata->win_fed = EINA_TRUE;
efl_event_callback_legacy_call(evas, ev->desc, evt);
efl_event_callback_call(evas, ev->desc, evt);
evdata->win_fed = EINA_FALSE;
evdata->evas_done = EINA_FALSE;
}
@ -1744,6 +1756,9 @@ EFL_CALLBACKS_ARRAY_DEFINE(_elm_win_evas_feed_fake_callbacks,
{ EFL_EVENT_POINTER_OUT, _evas_event_pointer_feed_fake_cb },
{ EFL_EVENT_POINTER_CANCEL, _evas_event_pointer_feed_fake_cb },
{ EFL_EVENT_POINTER_WHEEL, _evas_event_pointer_feed_fake_cb },
{ EFL_EVENT_FINGER_MOVE, _evas_event_pointer_feed_fake_cb },
{ EFL_EVENT_FINGER_DOWN, _evas_event_pointer_feed_fake_cb },
{ EFL_EVENT_FINGER_UP, _evas_event_pointer_feed_fake_cb },
{ EFL_EVENT_KEY_DOWN, _evas_event_key_feed_fake_cb },
{ EFL_EVENT_KEY_UP, _evas_event_key_feed_fake_cb })
@ -1841,97 +1856,115 @@ _win_event_add_cb(void *data, const Efl_Event *ev)
for (i = 0; array[i].desc; i++)
{
if (ev->info == EFL_EVENT_POINTER_MOVE)
if (array[i].desc == EFL_EVENT_POINTER_MOVE)
{
if (!(sd->event_forward.pointer_move++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_DOWN)
else if (array[i].desc == EFL_EVENT_POINTER_DOWN)
{
if (!(sd->event_forward.pointer_down++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_UP)
else if (array[i].desc == EFL_EVENT_POINTER_UP)
{
if (!(sd->event_forward.pointer_up++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_IN)
else if (array[i].desc == EFL_EVENT_POINTER_IN)
{
if (!(sd->event_forward.pointer_in++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_OUT)
else if (array[i].desc == EFL_EVENT_POINTER_OUT)
{
if (!(sd->event_forward.pointer_out++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_CANCEL)
else if (array[i].desc == EFL_EVENT_POINTER_CANCEL)
{
if (!(sd->event_forward.pointer_cancel++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_WHEEL)
else if (array[i].desc == EFL_EVENT_POINTER_WHEEL)
{
if (!(sd->event_forward.pointer_wheel++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_KEY_DOWN)
else if (array[i].desc == EFL_EVENT_FINGER_MOVE)
{
if (!(sd->event_forward.finger_move++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (array[i].desc == EFL_EVENT_FINGER_DOWN)
{
if (!(sd->event_forward.finger_down++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (array[i].desc == EFL_EVENT_FINGER_UP)
{
if (!(sd->event_forward.finger_up++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (array[i].desc == EFL_EVENT_KEY_DOWN)
{
if (!(sd->event_forward.key_down++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_key_cb, win);
}
else if (ev->info == EFL_EVENT_KEY_UP)
else if (array[i].desc == EFL_EVENT_KEY_UP)
{
if (!(sd->event_forward.key_up++))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_key_cb, win);
}
else if (ev->info == EFL_CANVAS_EVENT_RENDER_POST)
else if (array[i].desc == EFL_CANVAS_EVENT_RENDER_POST)
{
if (!(sd->event_forward.render_post++))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_RENDER_POST,
_elm_win_evas_render_post, win);
}
else if (ev->info == EFL_CANVAS_EVENT_RENDER_PRE)
else if (array[i].desc == EFL_CANVAS_EVENT_RENDER_PRE)
{
if (!(sd->event_forward.render_pre++))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_RENDER_PRE,
_elm_win_evas_render_pre, win);
}
else if (ev->info == EFL_CANVAS_EVENT_FOCUS_IN)
else if (array[i].desc == EFL_CANVAS_EVENT_FOCUS_IN)
{
if (!(sd->event_forward.focus_in++))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_FOCUS_IN,
_elm_win_evas_focus_in, win);
}
else if (ev->info == EFL_CANVAS_EVENT_FOCUS_OUT)
else if (array[i].desc == EFL_CANVAS_EVENT_FOCUS_OUT)
{
if (!(sd->event_forward.focus_out++))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_FOCUS_OUT,
_elm_win_evas_focus_out, win);
}
else if (ev->info == EFL_CANVAS_EVENT_OBJECT_FOCUS_IN)
else if (array[i].desc == EFL_CANVAS_EVENT_OBJECT_FOCUS_IN)
{
if (!(sd->event_forward.object_focus_in++))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
_elm_win_evas_object_focus_in, win);
}
else if (ev->info == EFL_CANVAS_EVENT_OBJECT_FOCUS_OUT)
else if (array[i].desc == EFL_CANVAS_EVENT_OBJECT_FOCUS_OUT)
{
if (!(sd->event_forward.object_focus_out++))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT,
_elm_win_evas_object_focus_out, win);
}
else if (ev->info == EFL_CANVAS_EVENT_DEVICE_CHANGED)
else if (array[i].desc == EFL_CANVAS_EVENT_DEVICE_CHANGED)
{
if (!(sd->event_forward.device_changed++))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_DEVICE_CHANGED,
@ -1950,97 +1983,115 @@ _win_event_del_cb(void *data, const Efl_Event *ev)
for (i = 0; array[i].desc; i++)
{
if (ev->info == EFL_EVENT_POINTER_MOVE)
if (array[i].desc == EFL_EVENT_POINTER_MOVE)
{
if (!(--sd->event_forward.pointer_move))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_DOWN)
else if (array[i].desc == EFL_EVENT_POINTER_DOWN)
{
if (!(--sd->event_forward.pointer_down))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_UP)
else if (array[i].desc == EFL_EVENT_POINTER_UP)
{
if (!(--sd->event_forward.pointer_up))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_IN)
else if (array[i].desc == EFL_EVENT_POINTER_IN)
{
if (!(--sd->event_forward.pointer_in))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_OUT)
else if (array[i].desc == EFL_EVENT_POINTER_OUT)
{
if (!(--sd->event_forward.pointer_out))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_CANCEL)
else if (array[i].desc == EFL_EVENT_POINTER_CANCEL)
{
if (!(--sd->event_forward.pointer_cancel))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_POINTER_WHEEL)
else if (array[i].desc == EFL_EVENT_POINTER_WHEEL)
{
if (!(--sd->event_forward.pointer_wheel))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (ev->info == EFL_EVENT_KEY_DOWN)
else if (array[i].desc == EFL_EVENT_FINGER_MOVE)
{
if (!(--sd->event_forward.finger_move))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (array[i].desc == EFL_EVENT_FINGER_DOWN)
{
if (!(--sd->event_forward.finger_down))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (array[i].desc == EFL_EVENT_FINGER_UP)
{
if (!(--sd->event_forward.finger_up))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_pointer_cb, win);
}
else if (array[i].desc == EFL_EVENT_KEY_DOWN)
{
if (!(--sd->event_forward.key_down))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_key_cb, win);
}
else if (ev->info == EFL_EVENT_KEY_UP)
else if (array[i].desc == EFL_EVENT_KEY_UP)
{
if (!(--sd->event_forward.key_up))
efl_event_callback_add(sd->evas, array[i].desc,
_evas_event_key_cb, win);
}
else if (ev->info == EFL_CANVAS_EVENT_RENDER_POST)
else if (array[i].desc == EFL_CANVAS_EVENT_RENDER_POST)
{
if (!(--sd->event_forward.render_post))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_RENDER_POST,
_elm_win_evas_render_post, win);
}
else if (ev->info == EFL_CANVAS_EVENT_RENDER_PRE)
else if (array[i].desc == EFL_CANVAS_EVENT_RENDER_PRE)
{
if (!(--sd->event_forward.render_pre))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_RENDER_PRE,
_elm_win_evas_render_pre, win);
}
else if (ev->info == EFL_CANVAS_EVENT_FOCUS_IN)
else if (array[i].desc == EFL_CANVAS_EVENT_FOCUS_IN)
{
if (!(--sd->event_forward.focus_in))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_FOCUS_IN,
_elm_win_evas_focus_in, win);
}
else if (ev->info == EFL_CANVAS_EVENT_FOCUS_OUT)
else if (array[i].desc == EFL_CANVAS_EVENT_FOCUS_OUT)
{
if (!(--sd->event_forward.focus_out))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_FOCUS_OUT,
_elm_win_evas_focus_out, win);
}
else if (ev->info == EFL_CANVAS_EVENT_OBJECT_FOCUS_IN)
else if (array[i].desc == EFL_CANVAS_EVENT_OBJECT_FOCUS_IN)
{
if (!(--sd->event_forward.object_focus_in))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
_elm_win_evas_object_focus_in, win);
}
else if (ev->info == EFL_CANVAS_EVENT_OBJECT_FOCUS_OUT)
else if (array[i].desc == EFL_CANVAS_EVENT_OBJECT_FOCUS_OUT)
{
if (!(--sd->event_forward.object_focus_out))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT,
_elm_win_evas_object_focus_out, win);
}
else if (ev->info == EFL_CANVAS_EVENT_DEVICE_CHANGED)
else if (array[i].desc == EFL_CANVAS_EVENT_DEVICE_CHANGED)
{
if (!(--sd->event_forward.device_changed))
evas_object_event_callback_add(sd->evas, EVAS_CALLBACK_DEVICE_CHANGED,
@ -2157,6 +2208,104 @@ _efl_ui_win_efl_input_interface_pointer_inside_get(Eo *obj EINA_UNUSED, Efl_Ui_W
return evas_pointer_inside_get(sd->evas);
}
/* multi touch support */
static Eina_Bool
_input_pointer_iterator_next(Input_Pointer_Iterator *it, void **data)
{
Eo *sub;
if (!eina_iterator_next(it->real_iterator, (void **) &sub))
return EINA_FALSE;
if (data) *data = sub;
return EINA_TRUE;
}
static Eo *
_input_pointer_iterator_get_container(Input_Pointer_Iterator *it)
{
return (Eo *) it->object;
}
static void
_input_pointer_iterator_free(Input_Pointer_Iterator *it)
{
Efl_Input_Pointer *ptr;
EINA_LIST_FREE(it->list, ptr)
efl_del(ptr);
eina_iterator_free(it->real_iterator);
free(it);
}
EOLIAN static Eina_Iterator *
_efl_ui_win_efl_input_interface_pointer_iterate(const Eo *obj, Efl_Ui_Win_Data *sd,
Eina_Bool hover EINA_UNUSED)
{
Input_Pointer_Iterator *it;
Eina_List *list = NULL;
int i, cnt;
// Note: "hover" is here as a possible extension to this API. At the moment
// I don't have any device that could track the position of hovering fingers
// and Evas also wouldn't track those.
ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, NULL);
cnt = evas_canvas_touch_point_list_count(sd->evas);
if (!cnt) return NULL;
it = calloc(1, sizeof(*it));
if (!it) return NULL;
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
for (i = 0; i < cnt; i++)
{
Efl_Input_Pointer_Data *ptrdata;
Evas_Touch_Point_State state;
Efl_Input_Pointer *ptr;
double x, y;
ptr = efl_input_instance_get(EFL_INPUT_POINTER_CLASS, (Eo *) obj, (void **) &ptrdata);
if (!ptrdata) break;
ptrdata->tool = evas_canvas_touch_point_list_nth_id_get(sd->evas, i);
_efl_input_value_mark(ptrdata, EFL_INPUT_VALUE_TOOL);
// Note that "still" maps to "down" here.
state = evas_canvas_touch_point_list_nth_state_get(sd->evas, i);
switch (state)
{
case EVAS_TOUCH_POINT_DOWN: ptrdata->action = EFL_POINTER_ACTION_DOWN; break;
case EVAS_TOUCH_POINT_UP: ptrdata->action = EFL_POINTER_ACTION_UP; break;
case EVAS_TOUCH_POINT_MOVE: ptrdata->action = EFL_POINTER_ACTION_MOVE; break;
case EVAS_TOUCH_POINT_STILL: ptrdata->action = EFL_POINTER_ACTION_DOWN; break;
case EVAS_TOUCH_POINT_CANCEL: ptrdata->action = EFL_POINTER_ACTION_CANCEL; break;
default: ptrdata->action = EFL_POINTER_ACTION_NONE; break;
}
evas_canvas_touch_point_list_nth_xy_get(sd->evas, i, &x, &y);
_efl_input_value_mark(ptrdata, EFL_INPUT_VALUE_X);
_efl_input_value_mark(ptrdata, EFL_INPUT_VALUE_Y);
ptrdata->cur.x = x;
ptrdata->cur.y = y;
ptrdata->prev = ptrdata->cur;
list = eina_list_append(list, ptr);
}
it->list = list;
it->real_iterator = eina_list_iterator_new(it->list);
it->iterator.version = EINA_ITERATOR_VERSION;
it->iterator.next = FUNC_ITERATOR_NEXT(_input_pointer_iterator_next);
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_input_pointer_iterator_get_container);
it->iterator.free = FUNC_ITERATOR_FREE(_input_pointer_iterator_free);
it->object = obj;
return &it->iterator;
}
EOLIAN static Eina_Bool
_efl_ui_win_efl_canvas_image_max_size_get(Eo *obj EINA_UNUSED, Efl_Ui_Win_Data *sd, int *maxw, int *maxh)
{

View File

@ -846,6 +846,7 @@ class Efl.Ui.Win (Elm.Widget, Efl.Canvas, Elm.Interface.Atspi.Window,
Efl.Text.text.get;
Efl.Input.Interface.pointer_xy.get;
Efl.Input.Interface.pointer_inside.get;
Efl.Input.Interface.pointer_iterate;
Efl.Canvas.image_max_size.get;
Efl.Canvas.smart_objects_calculate;
Efl.Canvas.objects_at_xy_get;

View File

@ -57,6 +57,28 @@ interface Efl.Input.Interface ()
return: bool;
}
}
pointer_iterate @const {
[[Returns an iterator over the current known pointer positions.
This is used to iterate over the current known multi-touch positions,
including the first finger. Each pointer position is represented by
an object of type @Efl.Input.Pointer.
Each finger in a multi touch environment can then be identified
by the @Efl.Input.Pointer.tool property. The order of the pointers
in this iterator is not defined.
Note: If the input surface supports hovering input, some pointers
may not be in a "down" state. To retrieve the list of such pointers,
set the $hover value to $true. Remember though that most devices
currently don't support this.
]]
params {
hover: bool @optional; [[$false by default, $true means to include
fingers that are currently hovering.]]
}
return: iterator<const(Efl.Input.Pointer)>;
}
}
events {
pointer,move: Efl.Input.Pointer; [[Main pointer move (current and previous positions are known).]]

View File

@ -80,9 +80,10 @@ _efl_input_pointer_class_destructor(Efl_Class *klass EINA_UNUSED)
}
EOLIAN static Efl_Object *
_efl_input_pointer_efl_object_constructor(Eo *obj, Efl_Input_Pointer_Data *pd EINA_UNUSED)
_efl_input_pointer_efl_object_constructor(Eo *obj, Efl_Input_Pointer_Data *pd)
{
obj = efl_constructor(efl_super(obj, MY_CLASS));
pd->fake = 1;
efl_input_reset(obj);
return obj;
}
@ -375,6 +376,16 @@ _efl_input_pointer_value_has_get(Eo *obj EINA_UNUSED, Efl_Input_Pointer_Data *pd
{
if (!pd || (key <= EFL_INPUT_VALUE_NONE) || (key > EFL_INPUT_VALUE_SLIDER))
return EINA_FALSE;
if (key == EFL_INPUT_VALUE_DX)
{
return _efl_input_value_has(pd, EFL_INPUT_VALUE_X) &&
_efl_input_value_has(pd, EFL_INPUT_VALUE_PREVIOUS_X);
}
if (key == EFL_INPUT_VALUE_DY)
{
return _efl_input_value_has(pd, EFL_INPUT_VALUE_Y) &&
_efl_input_value_has(pd, EFL_INPUT_VALUE_PREVIOUS_Y);
}
return _efl_input_value_has(pd, key);
}

View File

@ -597,16 +597,6 @@ class Evas.Canvas (Efl.Object, Efl.Canvas, Efl.Animator, Efl.Input.Interface)
evas and point is removed whenever removing touched point from
the evas.
]]
/* FIXME-doc
Example:
@code
extern Evas *evas;
int count;
count = evas_touch_point_list_count(evas);
printf("The count of touch points: %i\n", count);
@endcode
*/
return: uint; [[The number of touched point on the evas.]]
}
nochange_pop {
@ -753,19 +743,6 @@ class Evas.Canvas (Efl.Object, Efl.Canvas, Efl.Animator, Efl.Input.Interface)
which comes from Multi Event has $id that is same as Multi
Event's device id.
]]
/* FIXME-doc
Example:
@code
extern Evas *evas;
int id;
if (evas_touch_point_list_count(evas))
{
id = evas_touch_point_nth_id_get(evas, 0);
printf("The first touch point's id: %i\n", id);
}
@endcode
*/
return: int; [[id of nth touch point, if the call succeeded, -1 otherwise.]]
params {
@in n: uint; [[The number of the touched point (0 being the first).]]
@ -786,24 +763,13 @@ class Evas.Canvas (Efl.Object, Efl.Canvas, Efl.Animator, Efl.Input.Interface)
Touch point's coordinates is updated whenever moving that point
on the canvas.
]]
/* FIXME-doc
Example:
@code
extern Evas *evas;
Evas_Coord x, y;
if (evas_touch_point_list_count(evas))
{
evas_touch_point_nth_xy_get(evas, 0, &x, &y);
printf("The first touch point's coordinate: (%i, %i)\n", x, y);
}
@endcode
*/
params {
@in n: uint; [[The number of the touched point (0 being the first).]]
@out x: Evas.Coord; [[The pointer to a Evas_Coord to be filled in.]]
@out y: Evas.Coord; [[The pointer to a Evas_Coord to be filled in.]]
@out x: double; [[Last known X position in window coordinates]]
@out y: double; [[Last known Y position in window coordinates]]
}
/* Legacy uses int. */
legacy: null;
}
key_lock_del {
[[Removes the $keyname key from the current list of lock keys on
@ -945,19 +911,6 @@ class Evas.Canvas (Efl.Object, Efl.Canvas, Efl.Animator, Efl.Input.Interface)
EVAS_TOUCH_POINT_MOVE when moved at least once after pressed and
EVAS_TOUCH_POINT_UP when released.
]]
/* FIXME-doc
Example:
@code
extern Evas *evas;
Evas_Touch_Point_State state;
if (evas_touch_point_list_count(evas))
{
state = evas_touch_point_nth_state_get(evas, 0);
printf("The first touch point's state: %i\n", state);
}
@endcode
*/
return: Evas.Touch_Point_State; [[
$state of nth touch point, if the call succeeded,
EVAS_TOUCH_POINT_CANCEL otherwise.

View File

@ -1590,6 +1590,7 @@ _canvas_event_feed_mouse_cancel_internal(Evas_Public_Data *e, Efl_Input_Pointer_
ev->tool = point->id;
ev->cur.x = point->x;
ev->cur.y = point->y;
ev->prev = ev->cur;
_canvas_event_feed_multi_up_internal(e, ev);
}
}
@ -3459,6 +3460,9 @@ EFL_CALLBACKS_ARRAY_DEFINE(_evas_canvas_event_pointer_callbacks,
{ EFL_EVENT_POINTER_CANCEL, _evas_canvas_event_pointer_cb },
{ EFL_EVENT_POINTER_WHEEL, _evas_canvas_event_pointer_cb },
{ EFL_EVENT_POINTER_AXIS, _evas_canvas_event_pointer_cb },
{ EFL_EVENT_FINGER_MOVE, _evas_canvas_event_pointer_cb },
{ EFL_EVENT_FINGER_DOWN, _evas_canvas_event_pointer_cb },
{ EFL_EVENT_FINGER_UP, _evas_canvas_event_pointer_cb },
{ EFL_EVENT_KEY_DOWN, _evas_canvas_event_key_cb },
{ EFL_EVENT_KEY_UP, _evas_canvas_event_key_cb })

View File

@ -60,7 +60,8 @@ _evas_canvas_touch_point_list_count(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e)
}
EOLIAN void
_evas_canvas_touch_point_list_nth_xy_get(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e, unsigned int n, Evas_Coord *x, Evas_Coord *y)
_evas_canvas_touch_point_list_nth_xy_get(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e,
unsigned int n, double *x, double *y)
{
Evas_Coord_Touch_Point *point = NULL;
@ -75,6 +76,16 @@ _evas_canvas_touch_point_list_nth_xy_get(Eo *eo_e EINA_UNUSED, Evas_Public_Data
if (y) *y = point->y;
}
EAPI void
evas_touch_point_list_nth_xy_get(Evas_Canvas *obj, unsigned int n, Evas_Coord *x, Evas_Coord *y)
{
double X = 0, Y = 0;
evas_canvas_touch_point_list_nth_xy_get(obj, n, &X, &Y);
if (x) *x = X;
if (y) *y = Y;
}
EOLIAN int
_evas_canvas_touch_point_list_nth_id_get(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e, unsigned int n)
{

View File

@ -646,7 +646,7 @@ MAGIC_CHECK_FAILED(o, t, m)
struct _Evas_Coord_Touch_Point
{
Evas_Coord x, y; // point's x, y position
double x, y;
int id; // id in order to distinguish each point
Evas_Touch_Point_State state;
};
@ -1768,11 +1768,6 @@ void _canvas_render_dump(Eo *obj, void *_pd, va_list *list);
void _canvas_object_bottom_get(Eo *e, void *_pd, va_list *list);
void _canvas_object_top_get(Eo *e, void *_pd, va_list *list);
void _canvas_touch_point_list_count(Eo *obj, void *_pd, va_list *list);
void _canvas_touch_point_list_nth_xy_get(Eo *obj, void *_pd, va_list *list);
void _canvas_touch_point_list_nth_id_get(Eo *obj, void *_pd, va_list *list);
void _canvas_touch_point_list_nth_state_get(Eo *obj, void *_pd, va_list *list);
void _canvas_image_cache_flush(Eo *e, void *_pd, va_list *list);
void _canvas_image_cache_reload(Eo *e, void *_pd, va_list *list);
void _canvas_image_cache_set(Eo *e, void *_pd, va_list *list);

View File

@ -12,6 +12,7 @@
static const double _timeout1 = 0.1;
static const double _timeout2 = 0.2;
static const double _timeout3 = 0.3;
static const double _timeout_fail = 2.0;
static void
@ -193,12 +194,209 @@ START_TEST (elm_win_autohide_and_policy_quit_last_window_hidden)
}
END_TEST
/* a very lax definition of == for doubles */
#define VALEQ(a, b) ((fabs((a) - (b))) <= 0.001)
typedef struct
{
double x, y;
} point_t;
static point_t points[2][4] =
{
{
{ 20, 20 },
{ 40, 10 },
{ 60, 120 },
{ 80, 80 }
},
{
{ 30, 30 },
{ 50, 50 },
{ 70, 60 },
{ 80, 80 }
},
};
static Eina_Bool
_inputs_timer1_cb(void *data)
{
Efl_Input_Pointer *ptr;
Eo *win = data;
/* Send down events first (note: stupid, all at once) */
for (size_t i = 0; i < 4; i++)
{
ptr = efl_add(EFL_INPUT_POINTER_CLASS, win);
efl_input_pointer_position_set(ptr, points[0][i].x, points[0][i].y);
efl_input_pointer_tool_set(ptr, i);
efl_input_pointer_button_set(ptr, 1);
if (i == 0)
{
/* in first */
efl_input_pointer_action_set(ptr, EFL_POINTER_ACTION_IN);
efl_event_callback_call(win, EFL_EVENT_POINTER_IN, ptr);
/* move second */
efl_input_pointer_position_set(ptr, points[0][i].x, points[0][i].y);
efl_input_pointer_action_set(ptr, EFL_POINTER_ACTION_MOVE);
efl_event_callback_call(win, EFL_EVENT_POINTER_MOVE, ptr);
}
/* down finally */
efl_input_pointer_action_set(ptr, EFL_POINTER_ACTION_DOWN);
efl_event_callback_call(win, EFL_EVENT_POINTER_DOWN, ptr);
}
return ECORE_CALLBACK_DONE;
}
static Eina_Bool
_inputs_timer2_cb(void *data)
{
Efl_Input_Pointer *ptr;
Eina_Iterator *it;
Eo *win = data;
size_t i = 0, cnt = 0;
it = efl_input_pointer_iterate(win, 0);
EINA_ITERATOR_FOREACH(it, ptr)
{
double x, y;
int tool, ok = 0;
fail_if(!efl_input_pointer_value_has_get(ptr, EFL_INPUT_VALUE_X));
fail_if(!efl_input_pointer_value_has_get(ptr, EFL_INPUT_VALUE_Y));
fail_if(!efl_input_pointer_value_has_get(ptr, EFL_INPUT_VALUE_TOOL));
fail_if(efl_input_pointer_action_get(ptr) != EFL_POINTER_ACTION_DOWN);
x = efl_input_pointer_value_get(ptr, EFL_INPUT_VALUE_X);
y = efl_input_pointer_value_get(ptr, EFL_INPUT_VALUE_Y);
tool = efl_input_pointer_tool_get(ptr);
for (i = 0; i < 4; i++)
if (tool == i)
{
fail_if(!VALEQ(x, points[0][i].x));
fail_if(!VALEQ(y, points[0][i].y));
ok = 1;
break;
}
fail_if(!ok);
cnt++;
}
eina_iterator_free(it);
fail_if(cnt != 4);
/* Send some moves */
for (i = 0; i < 4; i++)
{
ptr = efl_add(EFL_INPUT_POINTER_CLASS, win);
efl_input_pointer_position_set(ptr, points[1][i].x, points[1][i].y);
efl_input_pointer_tool_set(ptr, i);
efl_input_pointer_button_set(ptr, 1);
/* move first */
efl_input_pointer_action_set(ptr, EFL_POINTER_ACTION_MOVE);
efl_event_callback_call(win, EFL_EVENT_POINTER_MOVE, ptr);
/* then up (one 2 fingers up: #1 and #3) */
if ((i % 2) == 1)
{
efl_input_pointer_action_set(ptr, EFL_POINTER_ACTION_UP);
efl_event_callback_call(win, EFL_EVENT_POINTER_UP, ptr);
}
}
return ECORE_CALLBACK_DONE;
}
static Eina_Bool
_inputs_timer3_cb(void *data)
{
Efl_Input_Pointer *ptr;
Eina_Iterator *it;
Eo *win = data;
size_t i = 0, cnt = 0;
it = efl_input_pointer_iterate(win, 0);
EINA_ITERATOR_FOREACH(it, ptr)
{
int tool, ok = 0;
double x, y;
fail_if(!efl_input_pointer_value_has_get(ptr, EFL_INPUT_VALUE_X));
fail_if(!efl_input_pointer_value_has_get(ptr, EFL_INPUT_VALUE_Y));
fail_if(!efl_input_pointer_value_has_get(ptr, EFL_INPUT_VALUE_TOOL));
fail_if(efl_input_pointer_action_get(ptr) != EFL_POINTER_ACTION_MOVE);
x = efl_input_pointer_value_get(ptr, EFL_INPUT_VALUE_X);
y = efl_input_pointer_value_get(ptr, EFL_INPUT_VALUE_Y);
tool = efl_input_pointer_tool_get(ptr);
for (i = 0; i < 4; i++)
if (tool == i)
{
fail_if(!VALEQ(x, points[1][i].x));
fail_if(!VALEQ(y, points[1][i].y));
ok = 1;
break;
}
fail_if(!ok);
cnt++;
}
eina_iterator_free(it);
fail_if(cnt != 2); // 2 moves (in the list), 2 ups (gone)
elm_exit();
return ECORE_CALLBACK_DONE;
}
START_TEST (efl_ui_win_multi_touch_inputs)
{
Eina_Bool fail_flag = EINA_FALSE;
Eo *win;
/* this tests only multi touch inputs - a lot of code but quite basic
* faking events is quite hard, as an exact sequence must be followed:
*
* pointer 0: in, move, down, move, move, ...
* pointer x: down, move, move, ...
*/
elm_init(0, NULL);
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
win = elm_win_add(NULL, "win", ELM_WIN_BASIC);
elm_win_autohide_set(win, EINA_TRUE);
efl_gfx_visible_set(win, EINA_TRUE);
efl_gfx_size_set(win, 100, 100);
ecore_timer_add(_timeout1, _inputs_timer1_cb, win);
ecore_timer_add(_timeout2, _inputs_timer2_cb, win);
ecore_timer_add(_timeout3, _inputs_timer3_cb, win);
ecore_timer_add(_timeout_fail, _timer_fail_flag_cb, &fail_flag);
elm_run();
fail_if(fail_flag != EINA_FALSE);
elm_shutdown();
}
END_TEST
void elm_test_win(TCase *tc)
{
tcase_add_test(tc, elm_atspi_role_get);
tcase_add_test(tc, elm_atspi_component_position);
tcase_add_test(tc, elm_atspi_component_size);
tcase_add_test(tc, elm_win_policy_quit_last_window_hidden);
tcase_add_test(tc, efl_ui_win_multi_touch_inputs);
#ifdef HAVE_ELEMENTARY_X
tcase_add_test(tc, elm_win_autohide);
tcase_add_test(tc, elm_win_autohide_and_policy_quit_last_window_hidden);