_e_gesture_edge_swipe_cancel();
}
+unsigned int
+e_gesture_util_tap_max_fingers_get(void)
+{
+ E_Gesture_Event_Tap *taps = &gesture->gesture_events.taps;
+ int i;
+ unsigned int max = 0;
+
+ for (i = 0; i < E_GESTURE_FINGER_MAX +1; i++)
+ {
+ if (taps->fingers[i].enabled) max = i;
+ }
+
+ return max;
+}
+
+unsigned int
+e_gesture_util_tap_max_repeats_get(unsigned int fingers)
+{
+ E_Gesture_Event_Tap *taps = &gesture->gesture_events.taps;
+ int i;
+ unsigned int max = 0;
+
+ for (i = 0; i < E_GESTURE_TAP_REPEATS_MAX + 1; i++)
+ {
+ if (taps->fingers[fingers].repeats[i].client) max = i;
+ }
+
+ return max;
+}
+
+static void
+_e_gesture_tap_cancel(void)
+{
+ E_Gesture_Event_Tap *taps = &gesture->gesture_events.taps;
+
+ if (taps->start_timer)
+ {
+ ecore_timer_del(taps->start_timer);
+ taps->start_timer = NULL;
+ }
+ if (taps->done_timer)
+ {
+ ecore_timer_del(taps->done_timer);
+ taps->done_timer = NULL;
+ }
+ if (taps->interval_timer)
+ {
+ ecore_timer_del(taps->interval_timer);
+ taps->interval_timer = NULL;
+ }
+
+ taps->repeats = 0;
+ taps->enabled_finger = 0;
+ taps->state = E_GESTURE_TAP_STATE_READY;
+ gesture->gesture_filter |= TIZEN_GESTURE_TYPE_TAP;
+ _e_gesture_event_flush();
+ gesture->gesture_events.recognized_gesture &= ~TIZEN_GESTURE_TYPE_TAP;
+}
+
+static void
+_e_gesture_send_tap(int fingers, int repeats, struct wl_client *client, struct wl_resource *res)
+{
+ GTINF("Send Tap gesture. %d fingers %d repeats to client (%p)\n", fingers, repeats, client);
+ tizen_gesture_send_tap(res, TIZEN_GESTURE_MODE_DONE, fingers, repeats);
+ _e_gesture_event_drop();
+ gesture->gesture_events.recognized_gesture |= TIZEN_GESTURE_TYPE_TAP;
+
+ _e_gesture_tap_cancel();
+}
+
+static Eina_Bool
+_e_gesture_timer_tap_start(void *data)
+{
+ E_Gesture_Event_Tap *taps = &gesture->gesture_events.taps;
+
+ if (taps->fingers[taps->enabled_finger].enabled)
+ {
+ taps->state = E_GESTURE_TAP_STATE_PROCESS;
+ }
+ else
+ {
+ _e_gesture_tap_cancel();
+ }
+
+ taps->start_timer = NULL;
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool
+_e_gesture_timer_tap_done(void *data)
+{
+ E_Gesture_Event_Tap *taps = &gesture->gesture_events.taps;
+
+ if (gesture->gesture_events.num_pressed)
+ {
+ _e_gesture_tap_cancel();
+ }
+
+ taps->done_timer = NULL;
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static Eina_Bool
+_e_gesture_timer_tap_interval(void *data)
+{
+ E_Gesture_Event_Tap *taps = &gesture->gesture_events.taps;
+
+ if (taps->fingers[taps->enabled_finger].repeats[taps->repeats].client)
+ {
+ _e_gesture_send_tap(taps->enabled_finger, taps->repeats,
+ taps->fingers[taps->enabled_finger].repeats[taps->repeats].client,
+ taps->fingers[taps->enabled_finger].repeats[taps->repeats].res);
+ gesture->event_state = E_GESTURE_EVENT_STATE_KEEP;
+ gesture->gesture_events.recognized_gesture &= ~TIZEN_GESTURE_TYPE_TAP;
+ gesture->gesture_filter = E_GESTURE_TYPE_ALL & ~gesture->grabbed_gesture;
+ }
+ else
+ {
+ _e_gesture_tap_cancel();
+
+ gesture->event_state = E_GESTURE_EVENT_STATE_KEEP;
+ gesture->gesture_filter = E_GESTURE_TYPE_ALL & ~gesture->grabbed_gesture;
+ }
+
+ taps->interval_timer = NULL;
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_e_gesture_tap_start(void)
+{
+ E_Gesture_Event_Tap *taps = &gesture->gesture_events.taps;
+
+ taps->state = E_GESTURE_TAP_STATE_START;
+ if (!taps->start_timer)
+ {
+ taps->start_timer = ecore_timer_add(E_GESTURE_TAP_START_TIME, _e_gesture_timer_tap_start, NULL);
+ }
+ if (!taps->done_timer)
+ {
+ taps->done_timer = ecore_timer_add(E_GESTURE_TAP_DONE_TIME, _e_gesture_timer_tap_done, NULL);
+ }
+}
+
+static void
+_e_gesture_tap_done(void)
+{
+ E_Gesture_Event_Tap *taps = &gesture->gesture_events.taps;
+
+ if (taps->repeats >= E_GESTURE_TAP_REPEATS_MAX)
+ _e_gesture_tap_cancel();
+
+ if (!taps->fingers[taps->enabled_finger].enabled)
+ _e_gesture_tap_cancel();
+
+ if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_TAP) &&
+ gesture->gesture_events.num_pressed == 0)
+ {
+ taps->state = E_GESTURE_TAP_STATE_WAIT;
+ taps->repeats++;
+ if (taps->done_timer)
+ {
+ ecore_timer_del(taps->done_timer);
+ taps->done_timer = NULL;
+ }
+ if (taps->repeats == taps->fingers[taps->enabled_finger].max_repeats)
+ {
+ ecore_timer_del(taps->interval_timer);
+ _e_gesture_timer_tap_interval(NULL);
+ }
+ else
+ {
+ if (!taps->interval_timer)
+ {
+ taps->interval_timer = ecore_timer_add(E_GESTURE_TAP_INTERVAL_TIME, _e_gesture_timer_tap_interval, NULL);
+ }
+ }
+ }
+}
+
+static void
+_e_gesture_process_tap_down(Ecore_Event_Mouse_Button *ev)
+{
+ E_Gesture_Event_Tap *taps = &gesture->gesture_events.taps;
+
+ if (taps->enabled_finger < gesture->gesture_events.num_pressed)
+ taps->enabled_finger = gesture->gesture_events.num_pressed;
+
+ if (taps->enabled_finger > taps->max_fingers)
+ _e_gesture_tap_cancel();
+
+ switch (taps->state)
+ {
+ case E_GESTURE_TAP_STATE_NONE:
+ return;
+
+ case E_GESTURE_TAP_STATE_READY:
+ _e_gesture_tap_start();
+ break;
+
+ case E_GESTURE_TAP_STATE_START:
+ break;
+
+ case E_GESTURE_TAP_STATE_PROCESS:
+ _e_gesture_tap_cancel();
+ break;
+
+ case E_GESTURE_TAP_STATE_WAIT:
+ if (taps->interval_timer)
+ {
+ ecore_timer_del(taps->interval_timer);
+ taps->interval_timer = NULL;
+ }
+ _e_gesture_tap_start();
+ break;
+
+ case E_GESTURE_TAP_STATE_DONE:
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+_e_gesture_process_tap_move(Ecore_Event_Mouse_Move *ev)
+{
+ int diff_x, diff_y;
+
+ diff_x = gesture->gesture_events.base_point[ev->multi.device].axis.x - ev->x;
+ diff_y = gesture->gesture_events.base_point[ev->multi.device].axis.y - ev->y;
+
+ if (ABS(diff_x) > E_GESTURE_TAP_MOVING_LANGE ||
+ ABS(diff_y) > E_GESTURE_TAP_MOVING_LANGE)
+ {
+ GTDBG("%d finger moving too large diff: (%d, %d)\n", ev->multi.device, diff_x, diff_y);
+ _e_gesture_tap_cancel();
+ }
+}
+
+static void
+_e_gesture_process_tap_up(Ecore_Event_Mouse_Button *ev)
+{
+ E_Gesture_Event_Tap *taps = &gesture->gesture_events.taps;
+
+ switch (taps->state)
+ {
+ case E_GESTURE_TAP_STATE_NONE:
+ return;
+
+ case E_GESTURE_TAP_STATE_READY:
+ _e_gesture_tap_cancel();
+ break;
+
+ case E_GESTURE_TAP_STATE_START:
+ taps->state = E_GESTURE_TAP_STATE_PROCESS;
+ if (taps->start_timer)
+ {
+ ecore_timer_del(taps->start_timer);
+ taps->start_timer = NULL;
+ }
+ _e_gesture_tap_done();
+ break;
+
+ case E_GESTURE_TAP_STATE_PROCESS:
+ _e_gesture_tap_done();
+ break;
+
+ case E_GESTURE_TAP_STATE_WAIT:
+ if (taps->interval_timer)
+ {
+ ecore_timer_del(taps->interval_timer);
+ taps->interval_timer = NULL;
+ }
+ _e_gesture_tap_start();
+ break;
+
+ case E_GESTURE_TAP_STATE_DONE:
+ break;
+
+ default:
+ break;
+ }
+}
+
static E_Gesture_Event_State
_e_gesture_process_mouse_button_down(void *event)
{
return E_GESTURE_EVENT_STATE_PROPAGATE;
}
+ gesture->gesture_events.base_point[ev->multi.device].pressed = EINA_TRUE;
+ gesture->gesture_events.base_point[ev->multi.device].axis.x = ev->x;
+ gesture->gesture_events.base_point[ev->multi.device].axis.y = ev->y;
+
if (gesture->gesture_events.recognized_gesture)
{
return E_GESTURE_EVENT_STATE_IGNORE;
{
_e_gesture_process_edge_swipe_down(ev);
}
+ if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_TAP))
+ {
+ _e_gesture_process_tap_down(ev);
+ }
return gesture->event_state;
}
{
return E_GESTURE_EVENT_STATE_PROPAGATE;
}
+ if (ev->multi.device > E_GESTURE_FINGER_MAX)
+ {
+ return E_GESTURE_EVENT_STATE_PROPAGATE;
+ }
+
+ gesture->gesture_events.base_point[ev->multi.device].pressed = EINA_FALSE;
+ gesture->gesture_events.base_point[ev->multi.device].axis.x = 0;
+ gesture->gesture_events.base_point[ev->multi.device].axis.y = 0;
+
+ if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_EDGE_SWIPE))
+ {
+ _e_gesture_process_edge_swipe_up(ev);
+ }
+ if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_TAP))
+ {
+ _e_gesture_process_tap_up(ev);
+ }
if (gesture->gesture_events.recognized_gesture)
{
return E_GESTURE_EVENT_STATE_IGNORE;
}
- if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_EDGE_SWIPE))
- {
- _e_gesture_process_edge_swipe_up(ev);
- }
-
return gesture->event_state;
}
{
return E_GESTURE_EVENT_STATE_PROPAGATE;
}
+ if (ev->multi.device > E_GESTURE_FINGER_MAX)
+ {
+ return E_GESTURE_EVENT_STATE_PROPAGATE;
+ }
if (gesture->gesture_events.num_pressed == 0)
{
return gesture->event_state;
{
return E_GESTURE_EVENT_STATE_PROPAGATE;
}
+ if (gesture->gesture_events.base_point[ev->multi.device].pressed != EINA_TRUE)
+ {
+ return gesture->event_state;
+ }
if (gesture->gesture_events.recognized_gesture)
{
return E_GESTURE_EVENT_STATE_IGNORE;
{
_e_gesture_process_edge_swipe_move(ev);
}
+ if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_TAP))
+ {
+ _e_gesture_process_tap_move(ev);
+ }
return gesture->event_state;
}
if (gesture->gesture_events.num_pressed == 0&&
type == ECORE_EVENT_MOUSE_BUTTON_UP)
{
- if ((gesture->grabbed_gesture & TIZEN_GESTURE_TYPE_EDGE_SWIPE) &&
- gesture->gesture_events.edge_swipes.event_keep)
- gesture->event_state = E_GESTURE_EVENT_STATE_KEEP;
+ if (gesture->grabbed_gesture & TIZEN_GESTURE_TYPE_TAP ||
+ ((gesture->grabbed_gesture & TIZEN_GESTURE_TYPE_EDGE_SWIPE) &&
+ gesture->gesture_events.edge_swipes.event_keep))
+ gesture->event_state = E_GESTURE_EVENT_STATE_KEEP;
gesture->gesture_filter = E_GESTURE_TYPE_ALL & ~gesture->grabbed_gesture;
}
return;
}
+static void
+_e_gesture_cb_grab_tap(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t fingers, uint32_t repeats)
+{
+ E_Gesture_Event *gev;
+ int ret = TIZEN_GESTURE_ERROR_NONE;
+
+ GTINF("client %p requested to grab tap gesture (fingers: %d, repeats: %d)\n", client, fingers, repeats);
+
+ if (fingers > E_GESTURE_FINGER_MAX || repeats > E_GESTURE_TAP_REPEATS_MAX)
+ {
+ GTWRN("Not supported fingers /repeats bigger than their maximum values\n");
+ ret = TIZEN_GESTURE_ERROR_INVALID_DATA;
+ goto finish;
+ }
+
+ gev = &gesture->gesture_events;
+
+ if (gev->taps.fingers[fingers].repeats[repeats].client)
+ {
+ GTWRN("%d finger %d repeats is already grabbed by %p client\n", fingers, repeats, gev->taps.fingers[fingers].repeats[repeats].client);
+ ret = TIZEN_GESTURE_ERROR_GRABBED_ALREADY;
+ goto finish;
+ }
+
+ gev->taps.fingers[fingers].repeats[repeats].client = client;
+ gev->taps.fingers[fingers].repeats[repeats].res = resource;
+ gev->taps.fingers[fingers].enabled = EINA_TRUE;
+
+ if (gev->taps.max_fingers < fingers)
+ gev->taps.max_fingers = fingers;
+ if (gev->taps.fingers[fingers].max_repeats < repeats)
+ gev->taps.fingers[fingers].max_repeats = repeats;
+
+ gesture->grabbed_gesture |= TIZEN_GESTURE_TYPE_TAP;
+ gev->taps.state = E_GESTURE_TAP_STATE_READY;
+ gesture->event_state = E_GESTURE_EVENT_STATE_KEEP;
+ gesture->gesture_filter = E_GESTURE_TYPE_ALL & ~gesture->grabbed_gesture;
+
+finish:
+ tizen_gesture_send_tap_notify(resource, fingers, repeats, ret);
+}
+
+static void
+_e_gesture_cb_ungrab_tap(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t fingers, uint32_t repeats)
+{
+ int i;
+ E_Gesture_Event *gev;
+ int ret = TIZEN_GESTURE_ERROR_NONE;
+
+ GTINF("client %p requested to ungrab tap gesture (fingers: %d, repeats: %d)\n", client, fingers, fingers);
+
+ if (fingers > E_GESTURE_FINGER_MAX || repeats > E_GESTURE_TAP_REPEATS_MAX)
+ {
+ GTWRN("Not supported fingers /repeats bigger than their maximum values\n");
+ ret = TIZEN_GESTURE_ERROR_INVALID_DATA;
+ goto finish;
+ }
+
+ gev = &gesture->gesture_events;
+
+ if (gev->taps.fingers[fingers].repeats[repeats].client == client)
+ {
+ gev->taps.fingers[fingers].repeats[repeats].client = NULL;
+ gev->taps.fingers[fingers].repeats[repeats].res = NULL;
+ }
+
+ gev->taps.fingers[fingers].enabled = EINA_FALSE;
+ for (i = 0; i < E_GESTURE_TAP_REPEATS_MAX; i++)
+ {
+ if (gev->taps.fingers[fingers].repeats[i].client)
+ {
+ gev->taps.fingers[fingers].enabled = EINA_TRUE;
+ break;
+ }
+ }
+
+ gesture->grabbed_gesture &= ~TIZEN_GESTURE_TYPE_TAP;
+ gev->taps.state = E_GESTURE_TAP_STATE_NONE;
+ gesture->event_state = E_GESTURE_EVENT_STATE_PROPAGATE;
+ for (i = 0; i < E_GESTURE_FINGER_MAX; i++)
+ {
+ if (gev->taps.fingers[i].enabled)
+ {
+ gesture->grabbed_gesture |= TIZEN_GESTURE_TYPE_TAP;
+ gev->taps.state = E_GESTURE_TAP_STATE_READY;
+ gesture->event_state = E_GESTURE_EVENT_STATE_KEEP;
+ break;
+ }
+ }
+
+ gev->taps.max_fingers = e_gesture_util_tap_max_fingers_get();
+ gev->taps.fingers[fingers].max_repeats = e_gesture_util_tap_max_repeats_get(fingers);
+
+finish:
+ tizen_gesture_send_tap_notify(resource, fingers, repeats, ret);
+}
+
static const struct tizen_gesture_interface _e_gesture_implementation = {
_e_gesture_cb_grab_edge_swipe,
- _e_gesture_cb_ungrab_edge_swipe
+ _e_gesture_cb_ungrab_edge_swipe,
+ _e_gesture_cb_grab_tap,
+ _e_gesture_cb_ungrab_tap
};
/* tizen_gesture global object destroy function */
#define GTDBG(msg, ARG...) DBG("[tizen_gesture][%s:%d] "msg, __FUNCTION__, __LINE__, ##ARG)
#define E_GESTURE_FINGER_MAX 3
-#define E_GESTURE_TYPE_MAX TIZEN_GESTURE_TYPE_EDGE_SWIPE+1
-#define E_GESTURE_TYPE_ALL TIZEN_GESTURE_TYPE_EDGE_SWIPE
+#define E_GESTURE_TYPE_MAX TIZEN_GESTURE_TYPE_TAP+1
+#define E_GESTURE_TYPE_ALL (TIZEN_GESTURE_TYPE_EDGE_SWIPE | TIZEN_GESTURE_TYPE_TAP)
#define E_GESTURE_KEYBOARD_NAME "Gesture Keyboard"
#define E_GESTURE_AUX_HINT_GESTURE_DISABLE "wm.policy.win.gesture.disable"
#define E_GESTURE_EDGE_SWIPE_BACK_KEY 166
#define E_GESTURE_EDGE_SWIPE_BACK_DEFAULT_ENABLE EINA_TRUE
-#define ABS(x) ((x)>0)?(x):-(x)
+#define E_GESTURE_TAP_REPEATS_MAX 3
+#define E_GESTURE_TAP_START_TIME 0.05
+#define E_GESTURE_TAP_DONE_TIME 1
+#define E_GESTURE_TAP_INTERVAL_TIME 1
+#define E_GESTURE_TAP_MOVING_LANGE 25
+
+#define ABS(x) (((x)>0)?(x):-(x))
typedef struct _E_Gesture E_Gesture;
typedef struct _E_Gesture* E_GesturePtr;
typedef struct _E_Gesture_Conf_Edd E_Gesture_Conf_Edd;
typedef struct _E_Gesture_Config_Data E_Gesture_Config_Data;
+typedef struct _E_Gesture_Event_Tap_Finger_Repeats E_Gesture_Event_Tap_Finger_Repeats;
+typedef struct _E_Gesture_Event_Tap_Finger E_Gesture_Event_Tap_Finger;
+typedef struct _E_Gesture_Event_Tap E_Gesture_Event_Tap;
+
typedef struct _Coords Coords;
+typedef struct _E_Gesture_Finger E_Gesture_Finger;
typedef struct _E_Gesture_Event_Info E_Gesture_Event_Info;
typedef enum _E_Gesture_Edge E_Gesture_Edge;
typedef enum _E_Gesture_Event_State E_Gesture_Event_State;
+typedef enum _E_Gesture_Tap_State E_Gesture_Tap_State;
extern E_GesturePtr gesture;
E_GESTURE_EVENT_STATE_IGNORE
};
+enum _E_Gesture_Tap_State
+{
+ E_GESTURE_TAP_STATE_NONE,
+ E_GESTURE_TAP_STATE_READY, // tap is required, idle
+ E_GESTURE_TAP_STATE_START, // first finger is pressed
+ E_GESTURE_TAP_STATE_PROCESS, // all fingers are pressed or first release
+ E_GESTURE_TAP_STATE_WAIT, // all fingers are released and wait next tap
+ E_GESTURE_TAP_STATE_DONE
+};
+
struct _Coords
{
int x, y;
};
+struct _E_Gesture_Finger
+{
+ Eina_Bool pressed;
+ Coords axis;
+};
+
struct _E_Gesture_Event_Info
{
int type;
Eina_Bool event_keep;
};
+struct _E_Gesture_Event_Tap_Finger_Repeats
+{
+ struct wl_client *client;
+ struct wl_resource *res;
+};
+
+struct _E_Gesture_Event_Tap_Finger
+{
+ Eina_Bool enabled;
+ unsigned int max_repeats;
+ E_Gesture_Event_Tap_Finger_Repeats repeats[E_GESTURE_TAP_REPEATS_MAX+1];
+};
+
+struct _E_Gesture_Event_Tap
+{
+ E_Gesture_Event_Tap_Finger fingers[E_GESTURE_FINGER_MAX+1];
+ E_Gesture_Tap_State state;
+ unsigned int enabled_finger;
+ unsigned int repeats;
+ unsigned int max_fingers;
+
+ /* pressed timer */
+ Ecore_Timer *start_timer;
+ /* release timer */
+ Ecore_Timer *done_timer;
+ /* interval timer */
+ Ecore_Timer *interval_timer;
+};
+
struct _E_Gesture_Event
{
E_Gesture_Event_Edge_Swipe edge_swipes;
+ E_Gesture_Event_Tap taps;
+
+ E_Gesture_Finger base_point[E_GESTURE_FINGER_MAX + 1];
int num_pressed;
Eina_Bool recognized_gesture;
char *kbd_identifier;
char *kbd_name;
Ecore_Device *kbd_device;
- }device;
+ } device;
unsigned int grabbed_gesture;
E_Gesture_Event gesture_events;
void e_gesture_event_filter_enable(Eina_Bool enabled);
+/* Util functions */
+unsigned int e_gesture_util_tap_max_fingers_get(void);
+unsigned int e_gesture_util_tap_max_repeats_get(unsigned int);
+
#endif