Add a pan gesture 49/99249/10
authorJengHyun Kang <jhyuni.kang@samsung.com>
Tue, 21 Feb 2017 02:11:09 +0000 (11:11 +0900)
committerJengHyun Kang <jhyuni.kang@samsung.com>
Fri, 12 May 2017 05:22:58 +0000 (14:22 +0900)
Change-Id: Ie6aefb3394a7d7cb6067778483c3540c9ee0c579

src/e_mod_gesture_events.c
src/e_mod_main.c
src/e_mod_main.h

index d95ae94..13109ad 100644 (file)
@@ -431,6 +431,167 @@ _e_gesture_process_edge_swipe_up(Ecore_Event_Mouse_Button *ev)
    _e_gesture_edge_swipe_cancel();
 }
 
+static void
+_e_gesture_pan_send(int mode, int fingers, int cx, int cy, struct wl_resource *res, struct wl_client *client)
+{
+   Ecore_Event_Mouse_Button *ev_cancel;
+
+   if (mode == TIZEN_GESTURE_MODE_BEGIN)
+     {
+        ev_cancel = E_NEW(Ecore_Event_Mouse_Button, 1);
+        EINA_SAFETY_ON_NULL_RETURN(ev_cancel);
+
+        ev_cancel->timestamp = (int)(ecore_time_get()*1000);
+        ev_cancel->same_screen = 1;
+
+        ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_CANCEL, ev_cancel, NULL, NULL);
+     }
+
+   GTINF("Send pan gesture %d fingers. (%d, %d) to client: %p, mode: %d\n", fingers, cx, cy, client, mode);
+
+   tizen_gesture_send_pan(res, mode, fingers, cx, cy);
+
+   gesture->gesture_events.recognized_gesture |= TIZEN_GESTURE_TYPE_PAN;
+}
+
+static void
+_e_gesture_pan_cancel(void)
+{
+   E_Gesture_Event_Pan *pans = &gesture->gesture_events.pans;
+
+   if (pans->start_timer)
+     {
+        ecore_timer_del(pans->start_timer);
+        pans->start_timer = NULL;
+     }
+   if (pans->move_timer)
+     {
+        ecore_timer_del(pans->move_timer);
+        pans->move_timer = NULL;
+     }
+
+   if (pans->state == E_GESTURE_PAN_STATE_MOVING)
+     _e_gesture_pan_send(TIZEN_GESTURE_MODE_END, pans->num_pan_fingers, 0, 0,
+                         pans->fingers[pans->num_pan_fingers].res,
+                         pans->fingers[pans->num_pan_fingers].client);
+
+   gesture->gesture_filter |= TIZEN_GESTURE_TYPE_PAN;
+   pans->state = E_GESTURE_PAN_STATE_DONE;
+}
+
+static void
+_e_gesture_util_center_axis_get(int num_finger, int *x, int *y)
+{
+   int i;
+   int calc_x = 0, calc_y = 0;
+
+   for (i = 1; i <= num_finger; i++)
+     {
+        calc_x += gesture->gesture_events.base_point[i].axis.x;
+        calc_y += gesture->gesture_events.base_point[i].axis.y;
+     }
+
+   calc_x = (int)(calc_x / num_finger);
+   calc_y = (int)(calc_y / num_finger);
+
+   *x = calc_x;
+   *y = calc_y;
+}
+
+static Eina_Bool
+_e_gesture_timer_pan_start(void *data)
+{
+   E_Gesture_Event_Pan *pans = &gesture->gesture_events.pans;
+   int num_pressed = gesture->gesture_events.num_pressed;
+   int i;
+
+   if (pans->fingers[num_pressed].client)
+     {
+        for (i = 1; i <= num_pressed; i++)
+          {
+             pans->start_point.x += gesture->gesture_events.base_point[i].axis.x;
+             pans->start_point.y += gesture->gesture_events.base_point[i].axis.y;
+          }
+        pans->center_point.x = pans->start_point.x = (int)(pans->start_point.x / num_pressed);
+        pans->center_point.y = pans->start_point.y = (int)(pans->start_point.y / num_pressed);
+        pans->state = E_GESTURE_PAN_STATE_START;
+     }
+   else
+     {
+        _e_gesture_pan_cancel();
+     }
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_e_gesture_process_pan_down(Ecore_Event_Mouse_Button *ev)
+{
+   E_Gesture_Event_Pan *pans = &gesture->gesture_events.pans;
+
+   if (gesture->gesture_events.recognized_gesture &&
+       !((gesture->gesture_events.recognized_gesture & TIZEN_GESTURE_TYPE_PAN)))
+     _e_gesture_pan_cancel();
+
+   if (gesture->gesture_events.num_pressed == 1)
+     {
+        pans->state = E_GESTURE_PAN_STATE_READY;
+        if (pans->start_timer) ecore_timer_del(pans->start_timer);
+        pans->start_timer = ecore_timer_add(E_GESTURE_PAN_START_TIME, _e_gesture_timer_pan_start, NULL);
+     }
+}
+
+static void
+_e_gesture_process_pan_move(Ecore_Event_Mouse_Move *ev)
+{
+   E_Gesture_Event_Pan *pans = &gesture->gesture_events.pans;
+   Coords cur_point = {0,};
+   int idx, diff_x, diff_y, mode;
+
+   if (gesture->gesture_events.recognized_gesture &&
+       !((gesture->gesture_events.recognized_gesture & TIZEN_GESTURE_TYPE_PAN)))
+     _e_gesture_pan_cancel();
+
+   idx = gesture->gesture_events.num_pressed;
+   if (idx <= 0) return;
+   if (pans->state == E_GESTURE_PAN_STATE_READY) return;
+
+   _e_gesture_util_center_axis_get(gesture->gesture_events.num_pressed, &cur_point.x, &cur_point.y);
+
+   diff_x = cur_point.x - pans->center_point.x;
+   diff_y = cur_point.y - pans->center_point.y;
+
+   if ((ABS(diff_x) > E_GESTURE_PAN_MOVING_RANGE) || (ABS(diff_y) > E_GESTURE_PAN_MOVING_RANGE))
+     {
+        switch (pans->state)
+          {
+             case E_GESTURE_PAN_STATE_START:
+                mode = TIZEN_GESTURE_MODE_BEGIN;
+                pans->state = E_GESTURE_PAN_STATE_MOVING;
+                pans->num_pan_fingers = idx;
+                break;
+             case E_GESTURE_PAN_STATE_MOVING:
+                mode = TIZEN_GESTURE_MODE_UPDATE;
+                break;
+             default:
+                return;
+          }
+
+        if (ABS(diff_x) > E_GESTURE_PAN_MOVING_RANGE) pans->center_point.x = cur_point.x;
+        if (ABS(diff_y) > E_GESTURE_PAN_MOVING_RANGE) pans->center_point.y = cur_point.y;
+
+        _e_gesture_pan_send(mode, idx, cur_point.x, cur_point.y, pans->fingers[idx].res, pans->fingers[idx].client);
+
+        if (mode == TIZEN_GESTURE_MODE_BEGIN)
+          mode = TIZEN_GESTURE_MODE_UPDATE;
+     }
+}
+
+static void
+_e_gesture_process_pan_up(Ecore_Event_Mouse_Button *ev)
+{
+   _e_gesture_pan_cancel();
+}
+
 unsigned int
 e_gesture_util_tap_max_fingers_get(void)
 {
@@ -755,6 +916,10 @@ _e_gesture_process_mouse_button_down(void *event)
      {
         _e_gesture_process_edge_swipe_down(ev);
      }
+   if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_PAN))
+     {
+        _e_gesture_process_pan_down(ev);
+     }
    if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_TAP))
      {
         _e_gesture_process_tap_down(ev);
@@ -789,6 +954,10 @@ _e_gesture_process_mouse_button_up(void *event)
      {
         _e_gesture_process_edge_swipe_up(ev);
      }
+   if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_PAN))
+     {
+        _e_gesture_process_pan_up(ev);
+     }
    if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_TAP))
      {
         _e_gesture_process_tap_up(ev);
@@ -828,19 +997,22 @@ _e_gesture_process_mouse_move(void *event)
      {
         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;
-     }
+   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_filter & TIZEN_GESTURE_TYPE_EDGE_SWIPE))
      {
         _e_gesture_process_edge_swipe_move(ev);
      }
+   if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_PAN))
+     {
+        _e_gesture_process_pan_move(ev);
+     }
    if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_TAP))
      {
         _e_gesture_process_tap_move(ev);
index 7f1a86e..4223b31 100644 (file)
@@ -66,6 +66,82 @@ e_gesture_add_client_destroy_listener(struct wl_client *client, int mode EINA_UN
    return TIZEN_KEYROUTER_ERROR_NONE;
 }
 
+static int
+_e_gesture_grab_pan(struct wl_client *client, struct wl_resource *resource, uint32_t num_of_fingers)
+{
+   E_Gesture_Event *gev;
+   int ret = TIZEN_GESTURE_ERROR_NONE;
+
+   GTINF("The client %p request to grab pan gesture, fingers: %d\n", client, num_of_fingers);
+
+   if (num_of_fingers > E_GESTURE_FINGER_MAX)
+     {
+        GTWRN("Do not support %d fingers (max: %d)\n", num_of_fingers, E_GESTURE_FINGER_MAX);
+        ret = TIZEN_GESTURE_ERROR_INVALID_DATA;
+        goto finish;
+     }
+
+   gev = &gesture->gesture_events;
+
+   if (gev->pans.fingers[num_of_fingers].client)
+     {
+        GTWRN("%d finger is already grabbed by %p client\n", num_of_fingers, gev->pans.fingers[num_of_fingers].client);
+        ret = TIZEN_GESTURE_ERROR_GRABBED_ALREADY;
+        goto finish;
+     }
+
+   gev->pans.fingers[num_of_fingers].client = client;
+   gev->pans.fingers[num_of_fingers].res = resource;
+   gev->pans.state = E_GESTURE_PAN_STATE_READY;
+
+   gesture->grabbed_gesture |= TIZEN_GESTURE_TYPE_PAN;
+   gesture->gesture_filter = E_GESTURE_TYPE_ALL & ~gesture->grabbed_gesture;
+
+finish:
+   return ret;
+}
+
+static int
+_e_gesture_ungrab_pan(struct wl_client *client, struct wl_resource *resource, uint32_t num_of_fingers)
+{
+   int i;
+   E_Gesture_Event *gev;
+   int ret = TIZEN_GESTURE_ERROR_NONE;
+
+   GTINF("The client %p request to ungrab pan gesture, fingers: %d\n", client, num_of_fingers);
+
+   if (num_of_fingers > E_GESTURE_FINGER_MAX)
+     {
+        GTWRN("Do not support %d fingers (max: %d)\n", num_of_fingers, E_GESTURE_FINGER_MAX);
+        ret = TIZEN_GESTURE_ERROR_INVALID_DATA;
+        goto finish;
+     }
+
+   gev = &gesture->gesture_events;
+
+   if (gev->pans.fingers[num_of_fingers].client == client)
+     {
+        gev->pans.fingers[num_of_fingers].client = NULL;
+        gev->pans.fingers[num_of_fingers].res = NULL;
+     }
+
+   gesture->grabbed_gesture &= ~TIZEN_GESTURE_TYPE_TAP;
+   gev->pans.state = E_GESTURE_PAN_STATE_NONE;
+
+   for (i = 0; i < E_GESTURE_FINGER_MAX; i++)
+     {
+        if (gev->pans.fingers[i].client)
+          {
+             gesture->grabbed_gesture |= TIZEN_GESTURE_TYPE_PAN;
+             gev->pans.state = E_GESTURE_PAN_STATE_READY;
+             break;
+          }
+     }
+
+finish:
+   return ret;
+}
+
 static void
 _e_gesture_remove_client_destroy_listener(struct wl_client *client, unsigned int fingers, unsigned int edge)
 {
@@ -392,11 +468,37 @@ finish:
    tizen_gesture_send_tap_notify(resource, fingers, repeats, ret);
 }
 
+static void
+_e_gesture_cb_grab_pan(struct wl_client *client,
+                   struct wl_resource *resource,
+                   uint32_t num_of_fingers)
+{
+   int ret = TIZEN_GESTURE_ERROR_NONE;
+
+   ret = _e_gesture_grab_pan(client, resource, num_of_fingers);
+
+   tizen_gesture_send_pan_notify(resource, num_of_fingers, ret);
+}
+
+static void
+_e_gesture_cb_ungrab_pan(struct wl_client *client,
+                   struct wl_resource *resource,
+                   uint32_t num_of_fingers)
+{
+   int ret = TIZEN_GESTURE_ERROR_NONE;
+
+   ret = _e_gesture_ungrab_pan(client, resource, num_of_fingers);
+
+   tizen_gesture_send_pan_notify(resource, num_of_fingers, 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_grab_tap,
-   _e_gesture_cb_ungrab_tap
+   _e_gesture_cb_ungrab_tap,
+   _e_gesture_cb_grab_pan,
+   _e_gesture_cb_ungrab_pan,
 };
 
 /* tizen_gesture global object destroy function */
index 67fa909..2c1aec1 100644 (file)
 #define E_GESTURE_TAP_INTERVAL_TIME 1
 #define E_GESTURE_TAP_MOVING_LANGE 25
 
+#define E_GESTURE_PAN_START_TIME 0.05
+#define E_GESTURE_PAN_MOVING_RANGE 15
+
 #define ABS(x) (((x)>0)?(x):-(x))
 
+#define RAD2DEG(x) ((x) * 57.295779513)
+
 typedef struct _E_Gesture E_Gesture;
 typedef struct _E_Gesture* E_GesturePtr;
 typedef struct _E_Gesture_Event E_Gesture_Event;
@@ -52,13 +57,17 @@ typedef struct _E_Gesture_Event_Tap_Finger_Repeats E_Gesture_Event_Tap_Finger_Re
 typedef struct _E_Gesture_Event_Tap_Finger E_Gesture_Event_Tap_Finger;
 typedef struct _E_Gesture_Event_Tap E_Gesture_Event_Tap;
 
+typedef struct _E_Gesture_Event_Pan E_Gesture_Event_Pan;
+
 typedef struct _Coords Coords;
 typedef struct _E_Gesture_Finger E_Gesture_Finger;
 typedef struct _E_Gesture_Event_Info E_Gesture_Event_Info;
+typedef struct _E_Gesture_Event_Client E_Gesture_Event_Client;
 
 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;
+typedef enum _E_Gesture_Pan_State E_Gesture_Pan_State;
 
 extern E_GesturePtr gesture;
 
@@ -91,6 +100,15 @@ enum _E_Gesture_Tap_State
    E_GESTURE_TAP_STATE_DONE
 };
 
+enum _E_Gesture_Pan_State
+{
+   E_GESTURE_PAN_STATE_NONE,
+   E_GESTURE_PAN_STATE_READY,
+   E_GESTURE_PAN_STATE_START,
+   E_GESTURE_PAN_STATE_MOVING,
+   E_GESTURE_PAN_STATE_DONE
+};
+
 struct _Coords
 {
    int x, y;
@@ -132,6 +150,12 @@ struct _E_Gesture_Config_Data
    E_Gesture_Conf_Edd *conf;
 };
 
+struct _E_Gesture_Event_Client
+{
+   struct wl_client *client;
+   struct wl_resource *res;
+};
+
 struct _E_Gesture_Event_Edge_Swipe_Finger_Edge
 {
    struct wl_client *client;
@@ -150,13 +174,13 @@ struct _E_Gesture_Grabbed_Client
    struct wl_client *client;
    struct wl_listener *destroy_listener;
 
-   E_Gesture_Event_Edge_Swipe_Finger edge_swipe_fingers[E_GESTURE_FINGER_MAX+1];
+   E_Gesture_Event_Edge_Swipe_Finger edge_swipe_fingers[E_GESTURE_FINGER_MAX+2];
 };
 
 
 struct _E_Gesture_Event_Edge_Swipe
 {
-   E_Gesture_Event_Edge_Swipe_Finger fingers[E_GESTURE_FINGER_MAX+1];
+   E_Gesture_Event_Edge_Swipe_Finger fingers[E_GESTURE_FINGER_MAX+2];
 
    unsigned int edge;
 
@@ -187,7 +211,7 @@ struct _E_Gesture_Event_Tap_Finger
 
 struct _E_Gesture_Event_Tap
 {
-   E_Gesture_Event_Tap_Finger fingers[E_GESTURE_FINGER_MAX+1];
+   E_Gesture_Event_Tap_Finger fingers[E_GESTURE_FINGER_MAX+2];
    E_Gesture_Tap_State state;
    unsigned int enabled_finger;
    unsigned int repeats;
@@ -201,12 +225,26 @@ struct _E_Gesture_Event_Tap
    Ecore_Timer *interval_timer;
 };
 
+struct _E_Gesture_Event_Pan
+{
+   E_Gesture_Event_Client fingers[E_GESTURE_FINGER_MAX + 2];
+   E_Gesture_Pan_State state;
+   Coords start_point;
+   Coords prev_point;
+   Coords center_point;
+   int num_pan_fingers;
+
+   Ecore_Timer *start_timer;
+   Ecore_Timer *move_timer;
+};
+
 struct _E_Gesture_Event
 {
    E_Gesture_Event_Edge_Swipe edge_swipes;
    E_Gesture_Event_Tap taps;
+   E_Gesture_Event_Pan pans;
 
-   E_Gesture_Finger base_point[E_GESTURE_FINGER_MAX + 1];
+   E_Gesture_Finger base_point[E_GESTURE_FINGER_MAX+2];
 
    int num_pressed;
    Eina_Bool recognized_gesture;