2019-05-14 12:50:15 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2019-07-29 02:42:34 -07:00
|
|
|
#define EFL_INPUT_CLICKABLE_PROTECTED 1
|
2019-05-14 12:50:15 -07:00
|
|
|
|
2019-07-29 02:42:34 -07:00
|
|
|
#include <Evas.h>
|
|
|
|
#include <Ecore.h>
|
|
|
|
#include "evas_common_private.h"
|
2019-05-14 12:50:15 -07:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
Eina_Bool pressed;
|
|
|
|
int pressed_before;
|
|
|
|
Efl_Loop_Timer *timer;
|
|
|
|
double clicked_last_time;
|
|
|
|
} Button_State;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
Button_State state[3];
|
2019-08-20 11:09:16 -07:00
|
|
|
Eina_Bool interaction;
|
2019-07-29 02:42:34 -07:00
|
|
|
} Efl_Input_Clickable_Data;
|
2019-05-14 12:50:15 -07:00
|
|
|
|
2019-07-29 02:42:34 -07:00
|
|
|
#define MY_CLASS EFL_INPUT_CLICKABLE_MIXIN
|
2019-05-14 12:50:15 -07:00
|
|
|
|
efl_input_clickable: increase the time interval for repeated counter
Summary:
The repeated counter in Efl.Input.Clickable_Clicked can be used to
identify double click or triple click.
Previously, the repeated counter in Efl.Input.Clickable_Clicked was
calculated within the time interval 0.1 second.
Now, the time interval for the repeated counter is increased to 0.25
second. It seems that 0.25 second is more appropriate to identify if the
two consecutive clicks should be considered together.
(e.g. considered as double click or triple click)
Moreover, in ecore_event and edje, 0.25 second is already used as a time
interval for double click.
Test Plan:
1. Run Efl.Ui.Button in elementary_test
2. Do double click or triple click the buttons
Reviewers: segfaultxavi, bu5hm4n, YOhoho
Reviewed By: segfaultxavi, YOhoho
Subscribers: YOhoho, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D9485
2019-08-02 01:43:45 -07:00
|
|
|
#define DOUBLE_CLICK_TIME ((double)0.25) //in seconds
|
2019-05-14 12:50:15 -07:00
|
|
|
#define LONGPRESS_TIMEOUT ((double)1.0) //in seconds
|
|
|
|
|
|
|
|
static void
|
|
|
|
_timer_longpress(void *data, const Efl_Event *ev)
|
|
|
|
{
|
|
|
|
Button_State *state;
|
2019-07-29 02:42:34 -07:00
|
|
|
Efl_Input_Clickable_Data *pd = efl_data_scope_get(data, MY_CLASS);
|
2019-05-14 12:50:15 -07:00
|
|
|
|
|
|
|
for (int i = 0; i < 3; ++i)
|
|
|
|
{
|
|
|
|
state = &pd->state[i];
|
|
|
|
if (state->timer == ev->object)
|
|
|
|
{
|
|
|
|
efl_del(state->timer);
|
|
|
|
state->timer = NULL;
|
2019-07-29 02:42:34 -07:00
|
|
|
efl_event_callback_call(data, EFL_INPUT_EVENT_LONGPRESSED, &i);
|
2019-05-14 12:50:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2019-07-29 02:42:34 -07:00
|
|
|
_efl_input_clickable_press(Eo *obj EINA_UNUSED, Efl_Input_Clickable_Data *pd, unsigned int button)
|
2019-05-14 12:50:15 -07:00
|
|
|
{
|
|
|
|
Button_State *state;
|
|
|
|
EINA_SAFETY_ON_FALSE_RETURN(button < 3);
|
|
|
|
|
2019-08-20 11:09:16 -07:00
|
|
|
pd->interaction = EINA_TRUE;
|
2019-05-14 12:50:15 -07:00
|
|
|
INF("Widget %s,%p is pressed(%d)", efl_class_name_get(obj), obj, button);
|
|
|
|
|
|
|
|
state = &pd->state[button];
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(state);
|
|
|
|
|
|
|
|
state->pressed = EINA_TRUE;
|
|
|
|
if (state->timer) efl_del(state->timer);
|
|
|
|
state->timer = efl_add(EFL_LOOP_TIMER_CLASS, obj,
|
|
|
|
efl_loop_timer_interval_set(efl_added, LONGPRESS_TIMEOUT),
|
|
|
|
efl_event_callback_add(efl_added, EFL_LOOP_TIMER_EVENT_TIMER_TICK, _timer_longpress, obj));
|
|
|
|
|
2019-07-29 02:42:34 -07:00
|
|
|
efl_event_callback_call(obj, EFL_INPUT_EVENT_PRESSED, &button);
|
2019-08-20 11:09:16 -07:00
|
|
|
pd->interaction = EINA_FALSE;
|
2019-05-14 12:50:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2019-07-29 02:42:34 -07:00
|
|
|
_efl_input_clickable_unpress(Eo *obj EINA_UNUSED, Efl_Input_Clickable_Data *pd, unsigned int button)
|
2019-05-14 12:50:15 -07:00
|
|
|
{
|
2019-07-29 02:42:34 -07:00
|
|
|
Efl_Input_Clickable_Clicked clicked;
|
2019-05-14 12:50:15 -07:00
|
|
|
Button_State *state;
|
|
|
|
Eina_Bool pressed;
|
|
|
|
EINA_SAFETY_ON_FALSE_RETURN(button < 3);
|
|
|
|
|
2019-08-20 11:09:16 -07:00
|
|
|
pd->interaction = EINA_TRUE;
|
|
|
|
|
2019-05-14 12:50:15 -07:00
|
|
|
state = &pd->state[button];
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(state);
|
|
|
|
|
|
|
|
INF("Widget %s,%p is unpressed(%d):%d", efl_class_name_get(obj), obj, button, state->pressed);
|
|
|
|
|
|
|
|
//eval if this is a repeated click
|
|
|
|
if (state->clicked_last_time > 0.0 && ecore_time_unix_get() - state->clicked_last_time < DOUBLE_CLICK_TIME)
|
|
|
|
state->pressed_before++;
|
|
|
|
else
|
|
|
|
state->pressed_before = 0;
|
|
|
|
//reset state
|
|
|
|
state->clicked_last_time = ecore_time_unix_get();
|
|
|
|
pressed = state->pressed;
|
|
|
|
state->pressed = EINA_FALSE;
|
|
|
|
if (state->timer)
|
|
|
|
efl_del(state->timer);
|
|
|
|
state->timer = NULL;
|
|
|
|
|
|
|
|
//populate state
|
2019-07-29 02:42:34 -07:00
|
|
|
efl_event_callback_call(obj, EFL_INPUT_EVENT_UNPRESSED, &button);
|
2019-05-14 12:50:15 -07:00
|
|
|
if (pressed)
|
|
|
|
{
|
|
|
|
INF("Widget %s,%p is clicked(%d)", efl_class_name_get(obj), obj, button);
|
|
|
|
clicked.repeated = state->pressed_before;
|
|
|
|
clicked.button = button;
|
|
|
|
if (button == 1)
|
2019-07-29 02:42:34 -07:00
|
|
|
efl_event_callback_call(obj, EFL_INPUT_EVENT_CLICKED, &clicked);
|
|
|
|
efl_event_callback_call(obj, EFL_INPUT_EVENT_CLICKED_ANY, &clicked);
|
2019-05-14 12:50:15 -07:00
|
|
|
}
|
2019-08-20 11:09:16 -07:00
|
|
|
pd->interaction = EINA_FALSE;
|
2019-05-14 12:50:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2019-07-29 02:42:34 -07:00
|
|
|
_efl_input_clickable_button_state_reset(Eo *obj EINA_UNUSED, Efl_Input_Clickable_Data *pd, unsigned int button)
|
2019-05-14 12:50:15 -07:00
|
|
|
{
|
|
|
|
Button_State *state;
|
|
|
|
EINA_SAFETY_ON_FALSE_RETURN(button < 3);
|
|
|
|
|
|
|
|
state = &pd->state[button];
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(state);
|
|
|
|
|
|
|
|
INF("Widget %s,%p is press is aborted(%d):%d", efl_class_name_get(obj), obj, button, state->pressed);
|
|
|
|
|
|
|
|
if (state->timer)
|
|
|
|
efl_del(state->timer);
|
|
|
|
state->timer = NULL;
|
|
|
|
state->pressed = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2019-08-01 02:19:51 -07:00
|
|
|
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;
|
|
|
|
}
|
2019-08-20 11:09:16 -07:00
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
|
|
|
_efl_input_clickable_interaction_get(const Eo *obj EINA_UNUSED, Efl_Input_Clickable_Data *pd)
|
|
|
|
{
|
|
|
|
return pd->interaction;
|
|
|
|
}
|
|
|
|
|
2019-07-29 02:42:34 -07:00
|
|
|
#include "efl_input_clickable.eo.c"
|