From: JengHyun Kang Date: Tue, 21 Feb 2017 02:11:09 +0000 (+0900) Subject: Add a pan gesture X-Git-Tag: accepted/tizen/unified/20170605.151559~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cc8a25c436324cf4965ae443b5f42fc05279217b;p=platform%2Fcore%2Fuifw%2Fe-mod-tizen-gesture.git Add a pan gesture Change-Id: Ie6aefb3394a7d7cb6067778483c3540c9ee0c579 --- diff --git a/src/e_mod_gesture_events.c b/src/e_mod_gesture_events.c index d95ae94..13109ad 100644 --- a/src/e_mod_gesture_events.c +++ b/src/e_mod_gesture_events.c @@ -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); diff --git a/src/e_mod_main.c b/src/e_mod_main.c index 7f1a86e..4223b31 100644 --- a/src/e_mod_main.c +++ b/src/e_mod_main.c @@ -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 */ diff --git a/src/e_mod_main.h b/src/e_mod_main.h index 67fa909..2c1aec1 100644 --- a/src/e_mod_main.h +++ b/src/e_mod_main.h @@ -36,8 +36,13 @@ #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;