diff options
Diffstat (limited to 'src/lib/evas/canvas/efl_input_clickable.c')
-rw-r--r-- | src/lib/evas/canvas/efl_input_clickable.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/lib/evas/canvas/efl_input_clickable.c b/src/lib/evas/canvas/efl_input_clickable.c new file mode 100644 index 0000000000..fb6c3fe457 --- /dev/null +++ b/src/lib/evas/canvas/efl_input_clickable.c @@ -0,0 +1,121 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#define EFL_INPUT_CLICKABLE_PROTECTED 1 + +#include <Evas.h> +#include <Ecore.h> +#include "evas_common_private.h" + +typedef struct { + Eina_Bool pressed; + int pressed_before; + Efl_Loop_Timer *timer; + double clicked_last_time; +} Button_State; + +typedef struct { + Button_State state[3]; +} Efl_Input_Clickable_Data; + +#define MY_CLASS EFL_INPUT_CLICKABLE_MIXIN + +#define DOUBLE_CLICK_TIME ((double)0.1) //in seconds +#define LONGPRESS_TIMEOUT ((double)1.0) //in seconds + +static void +_timer_longpress(void *data, const Efl_Event *ev) +{ + Button_State *state; + Efl_Input_Clickable_Data *pd = efl_data_scope_get(data, MY_CLASS); + + for (int i = 0; i < 3; ++i) + { + state = &pd->state[i]; + if (state->timer == ev->object) + { + efl_del(state->timer); + state->timer = NULL; + efl_event_callback_call(data, EFL_INPUT_EVENT_LONGPRESSED, &i); + } + } +} + +EOLIAN static void +_efl_input_clickable_press(Eo *obj EINA_UNUSED, Efl_Input_Clickable_Data *pd, unsigned int button) +{ + Button_State *state; + EINA_SAFETY_ON_FALSE_RETURN(button < 3); + + 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)); + + efl_event_callback_call(obj, EFL_INPUT_EVENT_PRESSED, &button); +} + +EOLIAN static void +_efl_input_clickable_unpress(Eo *obj EINA_UNUSED, Efl_Input_Clickable_Data *pd, unsigned int button) +{ + Efl_Input_Clickable_Clicked clicked; + Button_State *state; + Eina_Bool pressed; + EINA_SAFETY_ON_FALSE_RETURN(button < 3); + + 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 + efl_event_callback_call(obj, EFL_INPUT_EVENT_UNPRESSED, &button); + 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) + efl_event_callback_call(obj, EFL_INPUT_EVENT_CLICKED, &clicked); + efl_event_callback_call(obj, EFL_INPUT_EVENT_CLICKED_ANY, &clicked); + } +} + +EOLIAN static void +_efl_input_clickable_button_state_reset(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 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; +} + +#include "efl_input_clickable.eo.c" |