Add a pinch gesture 94/128594/2
authorJengHyun Kang <jhyuni.kang@samsung.com>
Wed, 10 May 2017 11:59:07 +0000 (20:59 +0900)
committerJengHyun Kang <jhyuni.kang@samsung.com>
Fri, 12 May 2017 05:39:34 +0000 (14:39 +0900)
Change-Id: Ibb1c9e342cb44632cc7bb5ad8b9ac49143d3a648

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

index 4bdcc1d461a361e274be0093c1051380d0be80da..fa2992d095074df3299dad52f3c6b308b928eedc 100644 (file)
@@ -473,13 +473,13 @@ _e_gesture_pan_cancel(void)
         pans->move_timer = NULL;
      }
 
-   if (pans->state == E_GESTURE_PAN_STATE_MOVING)
+   if (pans->state == E_GESTURE_PANPINCH_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;
+   pans->state = E_GESTURE_PANPINCH_STATE_DONE;
 }
 
 static void
@@ -501,6 +501,50 @@ _e_gesture_util_center_axis_get(int num_finger, int *x, int *y)
    *y = calc_y;
 }
 
+static int
+_e_gesture_util_distance_get(int x1, int y1, int x2, int y2)
+{
+   int distance;
+
+   distance = sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
+
+   return distance;
+}
+
+static int
+_e_gesture_util_distances_get(int num_finger)
+{
+   int i;
+   int cx = 0, cy = 0, distance = 0;
+
+   _e_gesture_util_center_axis_get(num_finger, &cx, &cy);
+
+   for (i = 1; i <= num_finger; i++)
+     {
+        distance +=  _e_gesture_util_distance_get(cx, cy,
+                       gesture->gesture_events.base_point[i].axis.x,
+                       gesture->gesture_events.base_point[i].axis.y);
+     }
+
+   return distance;
+}
+
+static double
+_e_gesture_util_angle_get(int x1, int y1, int x2, int y2)
+{
+   double angle, xx, yy;
+
+   xx = fabs(x2 - x1);
+   yy = fabs(y2 - y1);
+
+   angle = atan2(yy, xx);
+   if ((x1 > x2) && (y1 > y2)) angle = angle + M_PI_2;
+   else if ((x2 > x1) && (y2 > y1)) angle = angle + M_PI_2;
+
+   angle = RAD2DEG(angle);
+   return angle;
+}
+
 static Eina_Bool
 _e_gesture_timer_pan_start(void *data)
 {
@@ -517,7 +561,7 @@ _e_gesture_timer_pan_start(void *data)
           }
         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;
+        pans->state = E_GESTURE_PANPINCH_STATE_START;
      }
    else
      {
@@ -532,12 +576,13 @@ _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)))
+       !((gesture->gesture_events.recognized_gesture & TIZEN_GESTURE_TYPE_PAN) ||
+       (gesture->gesture_events.recognized_gesture & TIZEN_GESTURE_TYPE_PINCH)))
      _e_gesture_pan_cancel();
 
    if (gesture->gesture_events.num_pressed == 1)
      {
-        pans->state = E_GESTURE_PAN_STATE_READY;
+        pans->state = E_GESTURE_PANPINCH_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);
      }
@@ -551,12 +596,13 @@ _e_gesture_process_pan_move(Ecore_Event_Mouse_Move *ev)
    int idx, diff_x, diff_y, mode;
 
    if (gesture->gesture_events.recognized_gesture &&
-       !((gesture->gesture_events.recognized_gesture & TIZEN_GESTURE_TYPE_PAN)))
+       !((gesture->gesture_events.recognized_gesture & TIZEN_GESTURE_TYPE_PAN) ||
+       (gesture->gesture_events.recognized_gesture & TIZEN_GESTURE_TYPE_PINCH)))
      _e_gesture_pan_cancel();
 
    idx = gesture->gesture_events.num_pressed;
    if (idx <= 0) return;
-   if (pans->state == E_GESTURE_PAN_STATE_READY) return;
+   if (pans->state == E_GESTURE_PANPINCH_STATE_READY) return;
 
    _e_gesture_util_center_axis_get(gesture->gesture_events.num_pressed, &cur_point.x, &cur_point.y);
 
@@ -567,12 +613,12 @@ _e_gesture_process_pan_move(Ecore_Event_Mouse_Move *ev)
      {
         switch (pans->state)
           {
-             case E_GESTURE_PAN_STATE_START:
+             case E_GESTURE_PANPINCH_STATE_START:
                 mode = TIZEN_GESTURE_MODE_BEGIN;
-                pans->state = E_GESTURE_PAN_STATE_MOVING;
+                pans->state = E_GESTURE_PANPINCH_STATE_MOVING;
                 pans->num_pan_fingers = idx;
                 break;
-             case E_GESTURE_PAN_STATE_MOVING:
+             case E_GESTURE_PANPINCH_STATE_MOVING:
                 mode = TIZEN_GESTURE_MODE_UPDATE;
                 break;
              default:
@@ -595,6 +641,144 @@ _e_gesture_process_pan_up(Ecore_Event_Mouse_Button *ev)
    _e_gesture_pan_cancel();
 }
 
+static void
+_e_gesture_pinch_send(int mode, int fingers, int distance, int angle, 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 pinch gesture (fingers: %d, distance: %d, angle: %d, cx: %d, cy: %d) to client: %p, mode: %d\n", fingers, distance, angle, cx, cy, client, mode);
+
+   tizen_gesture_send_pinch(res, mode, fingers, distance, angle, cx, cy);
+
+   gesture->gesture_events.recognized_gesture |= TIZEN_GESTURE_TYPE_PINCH;
+}
+
+static void
+_e_gesture_pinch_cancel(void)
+{
+   E_Gesture_Event_Pinch *pinchs = &gesture->gesture_events.pinchs;
+
+   if (pinchs->start_timer)
+     {
+        ecore_timer_del(pinchs->start_timer);
+        pinchs->start_timer = NULL;
+     }
+   if (pinchs->move_timer)
+     {
+        ecore_timer_del(pinchs->move_timer);
+        pinchs->move_timer = NULL;
+     }
+
+   if (pinchs->state == E_GESTURE_PANPINCH_STATE_MOVING)
+     _e_gesture_pinch_send(TIZEN_GESTURE_MODE_END, pinchs->num_pinch_fingers, 0, 0, 0, 0,
+                           pinchs->fingers[pinchs->num_pinch_fingers].res,
+                           pinchs->fingers[pinchs->num_pinch_fingers].client);
+
+   gesture->gesture_filter |= TIZEN_GESTURE_TYPE_PINCH;
+   pinchs->state = E_GESTURE_PANPINCH_STATE_DONE;
+}
+
+static Eina_Bool
+_e_gesture_timer_pinch_start(void *data)
+{
+   E_Gesture_Event_Pinch *pinch = &gesture->gesture_events.pinchs;
+   int num_pressed = gesture->gesture_events.num_pressed;
+
+   if (pinch->fingers[num_pressed].client)
+     {
+        pinch->distance = _e_gesture_util_distances_get(num_pressed);
+        pinch->state = E_GESTURE_PANPINCH_STATE_START;
+     }
+   else
+     {
+        _e_gesture_pinch_cancel();
+     }
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static void
+_e_gesture_process_pinch_down(Ecore_Event_Mouse_Button *ev)
+{
+   E_Gesture_Event_Pinch *pinch = &gesture->gesture_events.pinchs;
+
+   if (gesture->gesture_events.recognized_gesture &&
+       !((gesture->gesture_events.recognized_gesture & TIZEN_GESTURE_TYPE_PAN) ||
+       (gesture->gesture_events.recognized_gesture & TIZEN_GESTURE_TYPE_PINCH)))
+     _e_gesture_pinch_cancel();
+
+   if (gesture->gesture_events.num_pressed == 1)
+     {
+        pinch->state = E_GESTURE_PANPINCH_STATE_READY;
+        if (pinch->start_timer) ecore_timer_del(pinch->start_timer);
+        pinch->start_timer = ecore_timer_add(E_GESTURE_PAN_START_TIME, _e_gesture_timer_pinch_start, NULL);
+     }
+}
+
+static void
+_e_gesture_process_pinch_move(Ecore_Event_Mouse_Move *ev)
+{
+   E_Gesture_Event_Pinch *pinch = &gesture->gesture_events.pinchs;
+   int idx, current_distance, mode, diff, angle, cx = 0, cy = 0;
+
+   if (gesture->gesture_events.recognized_gesture &&
+       !((gesture->gesture_events.recognized_gesture & TIZEN_GESTURE_TYPE_PAN) ||
+       (gesture->gesture_events.recognized_gesture & TIZEN_GESTURE_TYPE_PINCH)))
+     _e_gesture_pan_cancel();
+
+   idx = gesture->gesture_events.num_pressed;
+   if (idx <= 0) return;
+   if (pinch->state == E_GESTURE_PANPINCH_STATE_READY) return;
+
+   current_distance = _e_gesture_util_distances_get(idx);
+   diff = current_distance - pinch->distance;
+
+   if (ABS(diff) > E_GESTURE_PINCH_MOVING_DISTANCE_RANGE)
+     {
+        pinch->distance = current_distance;
+        switch (pinch->state)
+          {
+             case E_GESTURE_PANPINCH_STATE_START:
+                mode = TIZEN_GESTURE_MODE_BEGIN;
+                pinch->state = E_GESTURE_PANPINCH_STATE_MOVING;
+                pinch->num_pinch_fingers = idx;
+                break;
+             case E_GESTURE_PANPINCH_STATE_MOVING:
+                mode = TIZEN_GESTURE_MODE_UPDATE;
+                break;
+             default:
+                return;
+          }
+
+        if (idx == 2) angle = _e_gesture_util_angle_get(gesture->gesture_events.base_point[1].axis.x,
+                                                        gesture->gesture_events.base_point[1].axis.y,
+                                                        gesture->gesture_events.base_point[2].axis.x,
+                                                        gesture->gesture_events.base_point[2].axis.y);
+        else angle = 0;
+
+        _e_gesture_util_center_axis_get(idx, &cx, &cy);
+
+        _e_gesture_pinch_send(mode, idx, pinch->distance, angle, cx, cy, pinch->fingers[idx].res, pinch->fingers[idx].client);
+     }
+}
+
+static void
+_e_gesture_process_pinch_up(Ecore_Event_Mouse_Button *ev)
+{
+   _e_gesture_pinch_cancel();
+}
+
+
 unsigned int
 e_gesture_util_tap_max_fingers_get(void)
 {
@@ -932,6 +1116,10 @@ _e_gesture_process_mouse_button_down(void *event)
      {
         _e_gesture_process_pan_down(ev);
      }
+   if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_PINCH))
+     {
+        _e_gesture_process_pinch_down(ev);
+     }
    if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_TAP))
      {
         _e_gesture_process_tap_down(ev);
@@ -970,6 +1158,10 @@ _e_gesture_process_mouse_button_up(void *event)
      {
         _e_gesture_process_pan_up(ev);
      }
+   if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_PINCH))
+     {
+        _e_gesture_process_pinch_up(ev);
+     }
    if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_TAP))
      {
         _e_gesture_process_tap_up(ev);
@@ -1025,6 +1217,10 @@ _e_gesture_process_mouse_move(void *event)
      {
         _e_gesture_process_pan_move(ev);
      }
+   if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_PINCH))
+     {
+        _e_gesture_process_pinch_move(ev);
+     }
    if (!(gesture->gesture_filter & TIZEN_GESTURE_TYPE_TAP))
      {
         _e_gesture_process_tap_move(ev);
index 4223b31dee9a3ea5f4a7ad768a6a177f8eb8de14..627f30336fcf3a553ed0d2b1de858cb9981496f4 100644 (file)
@@ -92,7 +92,7 @@ _e_gesture_grab_pan(struct wl_client *client, struct wl_resource *resource, uint
 
    gev->pans.fingers[num_of_fingers].client = client;
    gev->pans.fingers[num_of_fingers].res = resource;
-   gev->pans.state = E_GESTURE_PAN_STATE_READY;
+   gev->pans.state = E_GESTURE_PANPINCH_STATE_READY;
 
    gesture->grabbed_gesture |= TIZEN_GESTURE_TYPE_PAN;
    gesture->gesture_filter = E_GESTURE_TYPE_ALL & ~gesture->grabbed_gesture;
@@ -126,14 +126,90 @@ _e_gesture_ungrab_pan(struct wl_client *client, struct wl_resource *resource, ui
      }
 
    gesture->grabbed_gesture &= ~TIZEN_GESTURE_TYPE_TAP;
-   gev->pans.state = E_GESTURE_PAN_STATE_NONE;
+   gev->pans.state = E_GESTURE_PANPINCH_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;
+             gev->pans.state = E_GESTURE_PANPINCH_STATE_READY;
+             break;
+          }
+     }
+
+finish:
+   return ret;
+}
+
+static int
+_e_gesture_grab_pinch(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 pinch 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->pinchs.fingers[num_of_fingers].client)
+     {
+        GTWRN("%d finger is already grabbed by %p client\n", num_of_fingers, gev->pinchs.fingers[num_of_fingers].client);
+        ret = TIZEN_GESTURE_ERROR_GRABBED_ALREADY;
+        goto finish;
+     }
+
+   gev->pinchs.fingers[num_of_fingers].client = client;
+   gev->pinchs.fingers[num_of_fingers].res = resource;
+
+   gev->pinchs.state = E_GESTURE_PANPINCH_STATE_READY;
+   gesture->grabbed_gesture |= TIZEN_GESTURE_TYPE_PINCH;
+   gesture->gesture_filter = E_GESTURE_TYPE_ALL & ~gesture->grabbed_gesture;
+
+finish:
+   return ret;
+}
+
+static int
+_e_gesture_ungrab_pinch(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 pinch 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->pinchs.fingers[num_of_fingers].client == client)
+     {
+        gev->pinchs.fingers[num_of_fingers].client = NULL;
+        gev->pinchs.fingers[num_of_fingers].res = NULL;
+     }
+
+   gesture->grabbed_gesture &= ~TIZEN_GESTURE_TYPE_PINCH;
+   gev->pinchs.state = E_GESTURE_PANPINCH_STATE_NONE;
+
+   for (i = 0; i < E_GESTURE_FINGER_MAX; i++)
+     {
+        if (gev->pinchs.fingers[i].client)
+          {
+             gesture->grabbed_gesture |= TIZEN_GESTURE_TYPE_PINCH;
+             gev->pinchs.state = E_GESTURE_PANPINCH_STATE_READY;
              break;
           }
      }
@@ -492,6 +568,30 @@ _e_gesture_cb_ungrab_pan(struct wl_client *client,
    tizen_gesture_send_pan_notify(resource, num_of_fingers, ret);
 }
 
+static void
+_e_gesture_cb_grab_pinch(struct wl_client *client,
+                   struct wl_resource *resource,
+                   uint32_t num_of_fingers)
+{
+   int ret = TIZEN_GESTURE_ERROR_NONE;
+
+   ret = _e_gesture_grab_pinch(client, resource, num_of_fingers);
+
+   tizen_gesture_send_pinch_notify(resource, num_of_fingers, ret);
+}
+
+static void
+_e_gesture_cb_ungrab_pinch(struct wl_client *client,
+                   struct wl_resource *resource,
+                   uint32_t num_of_fingers)
+{
+   int ret = TIZEN_GESTURE_ERROR_NONE;
+
+   ret = _e_gesture_ungrab_pinch(client, resource, num_of_fingers);
+
+   tizen_gesture_send_pinch_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,
@@ -499,6 +599,8 @@ static const struct tizen_gesture_interface _e_gesture_implementation = {
    _e_gesture_cb_ungrab_tap,
    _e_gesture_cb_grab_pan,
    _e_gesture_cb_ungrab_pan,
+   _e_gesture_cb_grab_pinch,
+   _e_gesture_cb_ungrab_pinch
 };
 
 /* tizen_gesture global object destroy function */
index a8dc2ac9cb200da72bc28de0c3a88d62adc002fd..4564713c73db00cd88dfe5b72f3ba22f921e16a4 100644 (file)
@@ -39,6 +39,8 @@
 #define E_GESTURE_PAN_START_TIME 0.05
 #define E_GESTURE_PAN_MOVING_RANGE 15
 
+#define E_GESTURE_PINCH_MOVING_DISTANCE_RANGE 15
+
 #define ABS(x) (((x)>0)?(x):-(x))
 
 #define RAD2DEG(x) ((x) * 57.295779513)
@@ -59,6 +61,8 @@ typedef struct _E_Gesture_Event_Tap E_Gesture_Event_Tap;
 
 typedef struct _E_Gesture_Event_Pan E_Gesture_Event_Pan;
 
+typedef struct _E_Gesture_Event_Pinch E_Gesture_Event_Pinch;
+
 typedef struct _Coords Coords;
 typedef struct _E_Gesture_Finger E_Gesture_Finger;
 typedef struct _E_Gesture_Event_Info E_Gesture_Event_Info;
@@ -67,7 +71,7 @@ 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;
+typedef enum _E_Gesture_PanPinch_State E_Gesture_PanPinch_State;
 
 extern E_GesturePtr gesture;
 
@@ -100,13 +104,13 @@ enum _E_Gesture_Tap_State
    E_GESTURE_TAP_STATE_DONE
 };
 
-enum _E_Gesture_Pan_State
+enum _E_Gesture_PanPinch_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
+   E_GESTURE_PANPINCH_STATE_NONE,
+   E_GESTURE_PANPINCH_STATE_READY,
+   E_GESTURE_PANPINCH_STATE_START,
+   E_GESTURE_PANPINCH_STATE_MOVING,
+   E_GESTURE_PANPINCH_STATE_DONE
 };
 
 struct _Coords
@@ -228,7 +232,7 @@ struct _E_Gesture_Event_Tap
 struct _E_Gesture_Event_Pan
 {
    E_Gesture_Event_Client fingers[E_GESTURE_FINGER_MAX + 2];
-   E_Gesture_Pan_State state;
+   E_Gesture_PanPinch_State state;
    Coords start_point;
    Coords prev_point;
    Coords center_point;
@@ -238,11 +242,23 @@ struct _E_Gesture_Event_Pan
    Ecore_Timer *move_timer;
 };
 
+struct _E_Gesture_Event_Pinch
+{
+   E_Gesture_Event_Client fingers[E_GESTURE_FINGER_MAX + 2];
+   E_Gesture_PanPinch_State state;
+   int distance;
+   int num_pinch_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_Event_Pinch pinchs;
 
    E_Gesture_Finger base_point[E_GESTURE_FINGER_MAX + 2];