summaryrefslogtreecommitdiff
path: root/src/lib/evas/canvas/efl_input_clickable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/evas/canvas/efl_input_clickable.c')
-rw-r--r--src/lib/evas/canvas/efl_input_clickable.c121
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"