efl_input_clickable: add longpress_abort

Now, a specific class which uses efl_input_clickable_util is able
to cancel ongoing longpress event by calling longpress_abort.

This commit shows how efl_ui_text uses longpress_abort to satisfy
its own longpress use case

ref T7847

Reviewed-by: Marcel Hollerbach <mail@marcel-hollerbach.de>
Differential Revision: https://phab.enlightenment.org/D9455
This commit is contained in:
WooHyun Jung 2019-08-01 09:19:51 +00:00 committed by Marcel Hollerbach
parent d2f7bacc2c
commit d02a3ecb66
4 changed files with 67 additions and 37 deletions

View File

@ -47,7 +47,6 @@ struct _Efl_Ui_Text_Data
Evas_Object *start_handler;
Evas_Object *end_handler;
Ecore_Job *deferred_decoration_job;
Ecore_Timer *longpress_timer;
Ecore_Timer *delay_write;
/* for deferred appending */
Ecore_Idler *append_text_idler;
@ -1427,8 +1426,6 @@ _long_press_cb(void *data, const Efl_Event *ev EINA_UNUSED)
_menu_call(data);
sd->long_pressed = EINA_TRUE;
sd->longpress_timer = NULL;
}
static void
@ -1522,7 +1519,8 @@ _mouse_up_cb(void *data,
if (sd->disabled) return;
if (ev->button == 1)
{
ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
efl_input_clickable_longpress_abort(data, 1);
/* Since context menu disabled flag was checked at long press start while mouse
* down, hence the same should be checked at mouse up from a long press
* as well */
@ -1563,6 +1561,7 @@ _mouse_move_cb(void *data,
void *event_info)
{
Evas_Event_Mouse_Move *ev = event_info;
Evas_Coord dx, dy;
EFL_UI_TEXT_DATA_GET(data, sd);
@ -1592,38 +1591,18 @@ _mouse_move_cb(void *data,
{
if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
{
ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
}
else if (sd->longpress_timer)
{
Evas_Coord dx, dy;
dx = sd->downx - ev->cur.canvas.x;
dx *= dx;
dy = sd->downy - ev->cur.canvas.y;
dy *= dy;
if ((dx + dy) >
((_elm_config->finger_size / 2) *
(_elm_config->finger_size / 2)))
{
ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
}
efl_input_clickable_longpress_abort(data, 1);
}
}
else if (sd->longpress_timer)
{
Evas_Coord dx, dy;
dx = sd->downx - ev->cur.canvas.x;
dx *= dx;
dy = sd->downy - ev->cur.canvas.y;
dy *= dy;
if ((dx + dy) >
((_elm_config->finger_size / 2) *
(_elm_config->finger_size / 2)))
{
ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
}
dx = sd->downx - ev->cur.canvas.x;
dx *= dx;
dy = sd->downy - ev->cur.canvas.y;
dy *= dy;
if ((dx + dy) > ((_elm_config->finger_size / 2) *
(_elm_config->finger_size / 2)))
{
efl_input_clickable_longpress_abort(data, 1);
}
}
@ -1716,7 +1695,7 @@ _selection_handlers_offset_calc(Evas_Object *obj, Evas_Object *handler)
sd->oy = pos.y + cy + (ch / 2);
}
ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
efl_input_clickable_longpress_abort(obj, 1);
sd->long_pressed = EINA_FALSE;
}
@ -1799,7 +1778,7 @@ _start_handler_mouse_move_cb(void *data,
efl_text_cursor_position_set(sd->text_obj,
efl_text_cursor_get(sd->text_obj, EFL_TEXT_CURSOR_GET_TYPE_MAIN), pos);
ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
efl_input_clickable_longpress_abort(data, 1);
sd->long_pressed = EINA_FALSE;
}
@ -1879,7 +1858,7 @@ _end_handler_mouse_move_cb(void *data,
pos = efl_text_cursor_position_get(sd->text_obj, sd->sel_handler_cursor);
/* Set the main cursor. */
efl_text_cursor_position_set(sd->text_obj, efl_text_cursor_get(data, EFL_TEXT_CURSOR_GET_TYPE_MAIN), pos);
ELM_SAFE_FREE(sd->longpress_timer, ecore_timer_del);
efl_input_clickable_longpress_abort(data, 1);
sd->long_pressed = EINA_FALSE;
}
@ -2266,7 +2245,6 @@ _efl_ui_text_efl_object_destructor(Eo *obj, Efl_Ui_Text_Data *sd)
ELM_SAFE_FREE(sd->append_text_left, free);
sd->append_text_idler = NULL;
}
ecore_timer_del(sd->longpress_timer);
EINA_LIST_FREE(sd->items, it)
{
eina_stringshare_del(it->label);

View File

@ -118,4 +118,19 @@ _efl_input_clickable_button_state_reset(Eo *obj EINA_UNUSED, Efl_Input_Clickable
state->pressed = EINA_FALSE;
}
EOLIAN static void
_efl_input_clickable_longpress_abort(Eo *obj EINA_UNUSED, Efl_Input_Clickable_Data *pd, unsigned int button)
{
Button_State *state;
EINA_SAFETY_ON_FALSE_RETURN(button < 3);
state = &pd->state[button];
EINA_SAFETY_ON_NULL_RETURN(state);
INF("Widget %s,%p - longpress is aborted(%d)", efl_class_name_get(obj), obj, button);
if (state->timer)
efl_del(state->timer);
state->timer = NULL;
}
#include "efl_input_clickable.eo.c"

View File

@ -36,6 +36,15 @@ mixin @beta Efl.Input.Clickable
button : uint;
}
}
longpress_abort @protected {
[[This aborts ongoing longpress event.
That is, this will stop the timer for longpress.
]]
params {
button : uint;
}
}
}
events {
clicked: Efl.Input.Clickable_Clicked; [[Called when object is in sequence pressed and unpressed, by the primary button]]

View File

@ -220,6 +220,33 @@ EFL_START_TEST(long_press_event)
}
EFL_END_TEST
EFL_START_TEST(long_press_abort)
{
efl_event_callback_array_add(widget, clickable(), NULL);
down(1);
iterate_mainloop(0.1);
ck_assert_int_eq(event_caller.pressed, 1);
event_caller.pressed = 0;
assert_event_empty();
efl_input_clickable_longpress_abort(widget, 1);
iterate_mainloop(2.0);
assert_event_empty();
up(1);
iterate_mainloop(0.1);
ck_assert_int_eq(event_caller.clicked, 1);
event_caller.clicked = 0;
ck_assert_int_eq(event_caller.clicked_params.repeated, 0);
ck_assert_int_eq(event_caller.clicked_params.button, 1);
ck_assert_int_eq(event_caller.clicked_all, 1);
event_caller.clicked_all = 0;
ck_assert_int_eq(event_caller.clicked_all_params.repeated, 0);
ck_assert_int_eq(event_caller.clicked_all_params.button, 1);
ck_assert_int_eq(event_caller.unpressed, 1);
event_caller.unpressed = 0;
assert_event_empty();
}
EFL_END_TEST
EFL_START_TEST(repeated_event)
{
efl_event_callback_array_add(widget, clickable(), NULL);
@ -254,5 +281,6 @@ efl_ui_clickable_behavior_test(TCase *tc)
tcase_add_checked_fixture(tc, prepare_window, NULL);
tcase_add_test(tc, simple_left_down_up);
tcase_add_test(tc, long_press_event);
tcase_add_test(tc, long_press_abort);
tcase_add_test(tc, repeated_event);
}