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
*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)
{
}
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
{
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);
}
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);
{
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:
_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)
{
{
_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);
{
_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);
{
_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);
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;
}
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;
}
}
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,
_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 */
#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)
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;
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;
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
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;
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];