From: Kim Kibum Date: Sun, 29 Apr 2012 08:04:43 +0000 (+0900) Subject: upload tizen1.0 source X-Git-Tag: 2.0_alpha~2 X-Git-Url: http://review.tizen.org/git/?p=adaptation%2Fxorg%2Fdriver%2Fxserver-xorg-input-gesture.git;a=commitdiff_plain;h=ab72e792b9a59904f95454f02463df54dd991c88 upload tizen1.0 source --- diff --git a/configure.ac b/configure.ac index 2aff572..8f20226 100644 --- a/configure.ac +++ b/configure.ac @@ -22,10 +22,10 @@ # Process this file with autoconf to produce a configure script AC_PREREQ(2.57) -AC_INIT([xf86-input-gesture], - 0.0.1, +AC_INIT([xserver-xorg-input-gesture], + 0.1.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], - xf86-input-gesture) + xserver-xorg-input-gesture) AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_AUX_DIR(.) diff --git a/packaging/xorg-x11-drv-input-gesture.spec b/packaging/xorg-x11-drv-input-gesture.spec index 0d34515..14cd9bb 100644 --- a/packaging/xorg-x11-drv-input-gesture.spec +++ b/packaging/xorg-x11-drv-input-gesture.spec @@ -5,11 +5,13 @@ Release: 4 Group: System/X Hardware Support License: MIT Source0: %{name}-%{version}.tar.gz -Requires: xorg-x11-server +Requires: xserver-xorg-core BuildRequires: pkgconfig(xorg-server) BuildRequires: pkgconfig(gestureproto) BuildRequires: pkgconfig(xproto) BuildRequires: pkgconfig(inputproto) +BuildRequires: pkgconfig(xorg-macros) + %description This package provides the driver for recognizing gesture(s) using button and motion events inside X server. diff --git a/src/gesture.c b/src/gesture.c index cf1c32d..6f41e66 100755 --- a/src/gesture.c +++ b/src/gesture.c @@ -58,10 +58,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #endif -#define __DEBUG__ -//#define __DETAIL_DEBUG__ -//#define __DEBUG_EVENT_HANDLER__ - #include #include #include @@ -115,9 +111,10 @@ void GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr de static Bool PointInBorderSize(WindowPtr pWin, int x, int y); static WindowPtr GestureWindowOnXY(int x, int y); Bool GestureHasFingerEventMask(int eventType, int num_finger); +static double get_angle(int x1, int y1, int x2, int y2); //Gesture recognizer and handlers -void GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx); +void GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired); void GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx); void GestureRecognize_GroupPan(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired); void GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired); @@ -125,7 +122,7 @@ void GestureRecognize_GroupTapNHold(int type, InternalEvent *ev, DeviceIntPtr de void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired); void GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction); void GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy); -void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy); +void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy, int kinds); void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds); void GestureHandleGesture_TapNHold(int num_fingers, int cx, int cy, Time interval, Time holdtime, int kinds); void GestureHandleGesture_Pan(int num_fingers, short int dx, short int dy, int direction, int distance, Time duration, int kinds); @@ -267,6 +264,63 @@ GestureHasFingerEventMask(int eventType, int num_finger) return ret; } +static double +get_angle(int x1, int y1, int x2, int y2) +{ + double a, xx, yy; + xx = fabs(x2 - x1); + yy = fabs(y2 - y1); + + if (((int) xx) && ((int) yy)) + { + a = atan(yy / xx); + if (x1 < x2) + { + if (y1 < y2) + { + return (RAD_360DEG - a); + } + else + { + return (a); + } + } + else + { + if (y1 < y2) + { + return (RAD_180DEG + a); + } + else + { + return (RAD_180DEG - a); + } + } + } + + if (((int) xx)) + { /* Horizontal line */ + if (x2 < x1) + { + return (RAD_180DEG); + } + else + { + return (0.0); + } + } + + /* Vertical line */ + if (y2 < y1) + { + return (RAD_90DEG); + } + else + { + return (RAD_270DEG); + } +} + void GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction) { @@ -352,21 +406,21 @@ GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy) GestureSendEvent(target_pWin, GestureNotifyTap, GestureTapMask, (xGestureCommonEvent *)&tev); } -void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy) +void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy, int kinds) { Window target_win; WindowPtr target_pWin; xGestureNotifyPinchRotationEvent prev; #ifdef __DETAIL_DEBUG__ - ErrorF("[X11][GestureHandleGesture_PinchRotation] num_fingers=%d, zoom=%.2f, angle=%.2f, distance=%d\n", - num_of_fingers, zoom, angle, distance, cx, cy); + ErrorF("[X11][GestureHandleGesture_PinchRotation] num_fingers=%d, zoom=%.2f, angle=%.2f(deg=%.2f), distance=%d, cx=%d, cy=%d\n", + num_of_fingers, zoom, angle, rad2degree(angle), distance, cx, cy); #endif//__DETAIL_DEBUG__ g_pGesture->recognized_gesture |= PinchRotationFilterMask; memset(&prev, 0, sizeof(xGestureNotifyPinchRotationEvent)); prev.type = GestureNotifyPinchRotation; - prev.kind = GestureDone; + prev.kind = kinds; prev.num_finger = num_of_fingers; prev.zoom = XDoubleToFixed(zoom); prev.angle = XDoubleToFixed(angle); @@ -387,7 +441,7 @@ void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double } #ifdef __DETAIL_DEBUG__ - ErrorF("[X11][GestureHandleGesture_PinchRotation] prev.window=0x%x, g_pGesture->grabMask=0x%x\n", prev.window, g_pGesture->grabMask); + ErrorF("[X11][GestureHandleGesture_PinchRotation] prev.window=0x%x, g_pGesture->grabMask=0x%x\n", (unsigned int)prev.window, (unsigned int)g_pGesture->grabMask); #endif//__DETAIL_DEBUG__ GestureSendEvent(target_pWin, GestureNotifyPinchRotation, GesturePinchRotationMask, (xGestureCommonEvent *)&prev); @@ -514,11 +568,266 @@ void GestureHandleGesture_Pan(int num_fingers, short int dx, short int dy, int d } void -GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx) +GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired) { + static int cx, cy; + + static int num_pressed = 0; + static int state = GestureEnd; + static int event_type = GestureNotifyPinchRotation; + static OsTimerPtr pinchrotation_event_timer = NULL; + + static pixman_region16_t base_area; + static pixman_region16_t cur_area; + + static double base_distance = 0.0f; + static double base_angle = 0.0f; + + static double prev_distance = 0.0f; + static double prev_angle = 0.0f; + + static double cur_distance = 0.0f; + static double cur_angle = 0.0f; + + double diff_distance = 0.0f; + double diff_angle = 0.0f; + + static int has_event_mask = 0; + + static Time base_time = 0; + Time current_time; + + if( timer_expired ) + { + if( state == GestureEnd ) + { + current_time = GetTimeInMillis(); + if( (current_time - base_time) >= PINCHROTATION_TIME_THRESHOLD ) + { +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][Timer] You must move farther than dist threshold(=%.2f) or angle threshold(=%2f) within time threshold(=%d) !\n", PINCHROTATION_DIST_THRESHOLD, PINCHROTATION_ANGLE_THRESHOLD, PINCHROTATION_TIME_THRESHOLD); +#endif//__DETAIL_DEBUG__ + goto cleanup_pinchrotation; + } + } + + return; + } + + switch( type ) + { + case ET_ButtonPress: + g_pGesture->fingers[idx].flags |= PressFlagPinchRotation; + + if( g_pGesture->num_pressed < 2 ) + return; + + if( g_pGesture->num_pressed < num_pressed && state != GestureEnd ) + { +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); +#endif//__DETAIL_DEBUG__ + goto cleanup_pinchrotation; + } + + if( base_distance == 0.0f && g_pGesture->num_pressed == 2 ) + { +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][First Time !!!] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); +#endif//__DETAIL_DEBUG__ + + base_time = GetTimeInMillis(); + pixman_region_init(&base_area); + pixman_region_union(&base_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]); + + prev_distance = base_distance = AREA_DIAG_LEN(&base_area.extents); + +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][P] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].px, g_pGesture->fingers[1].px, + g_pGesture->fingers[0].py, g_pGesture->fingers[1].py); +#endif//__DETAIL_DEBUG__ + + prev_angle = base_angle = get_angle(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py, g_pGesture->fingers[1].px, g_pGesture->fingers[1].py); +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][P] base_angle=%.2f(deg=%.2f)\n", base_angle, rad2degree(base_angle)); +#endif//__DETAIL_DEBUG__ + event_type = GestureNotifyPinchRotation; + pinchrotation_event_timer = TimerSet(pinchrotation_event_timer, 0, PINCHROTATION_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type); + } + num_pressed = g_pGesture->num_pressed; + +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][P][num_pressed=%d] AREA_SIZE(base_area.extents)=%d\n", num_pressed, AREA_SIZE(&base_area.extents)); + ErrorF("[GroupPinchRotation][P][num_pressed=%d] base_distance=%.2f, base_angle=%.2f(deg=%.2f)\n", num_pressed, base_distance, base_angle, rad2degree(base_angle)); +#endif//__DETAIL_DEBUG__ + break; + + case ET_Motion: + if( !(g_pGesture->fingers[idx].flags & PressFlagPinchRotation) ) + break; + + if( (num_pressed != g_pGesture->num_pressed) && (state != GestureEnd) ) + { +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); +#endif//__DETAIL_DEBUG__ + goto cleanup_pinchrotation; + } + + if( num_pressed < 2 ) + return; + + if( g_pGesture->fingers[0].mx && g_pGesture->fingers[0].my && g_pGesture->fingers[1].mx && g_pGesture->fingers[1].my ) + { + pixman_region_init(&cur_area); + pixman_region_union(&cur_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]); + + cur_distance = AREA_DIAG_LEN(&cur_area.extents); + +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][M] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].mx, g_pGesture->fingers[1].mx, + g_pGesture->fingers[0].my, g_pGesture->fingers[1].my); +#endif//__DETAIL_DEBUG__ + + cur_angle = get_angle(g_pGesture->fingers[0].mx, g_pGesture->fingers[0].my, g_pGesture->fingers[1].mx, g_pGesture->fingers[1].my); +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][M] cur_angle=%.2f(deg=%.2f)\n", cur_angle, rad2degree(cur_angle)); +#endif//__DETAIL_DEBUG__ + + diff_distance = prev_distance - cur_distance; + diff_angle = prev_angle - cur_angle; + + cx = AREA_CENTER_X(&cur_area.extents); + cy = AREA_CENTER_Y(&cur_area.extents); + +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][M][state=%d] cx=%d, cy=%d\n", state, cx, cy); +#endif//__DETAIL_DEBUG__ + +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][M][num_pressed=%d] prev_distance=%.2f, cur_distance=%.2f, diff=%.2f\n", num_pressed, prev_distance, cur_distance, diff_distance); + ErrorF("[GroupPinchRotation][M][num_pressed=%d] prev_angle=%.2f(deg=%.2f), cur_angle=%.2f(deg=%.2f), diff=%.2f(deg=%.2f)\n", num_pressed, prev_angle, rad2degree(prev_angle), cur_angle, rad2degree(cur_angle), diff_angle, rad2degree(diff_angle)); +#endif//__DETAIL_DEBUG__ + + switch( state ) + { + case GestureEnd: + if( (ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD) || (ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD) ) + { +#ifdef __DETAIL_DEBUG__ + if( ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD ) + ErrorF("[GroupPinchRotation][M] zoom changed !\n"); + + if( ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD ) + ErrorF("[GroupPinchRotation][M] angle changed !\n"); +#endif//__DETAIL_DEBUG__ + + TimerCancel(pinchrotation_event_timer); + state = GestureBegin; + goto gesture_begin_handle; + } + break; + + case GestureBegin: +gesture_begin_handle: +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation] PINCHROTATION Begin !cx=%d, cy=%d, state=%d\n", cx, cy, state); +#endif//__DETAIL_DEBUG__ + if( GestureHasFingerEventMask(GestureNotifyPinchRotation, num_pressed) ) + { + GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureBegin); + prev_distance = cur_distance; + prev_angle = cur_angle; + state = GestureUpdate; + has_event_mask = 1; + } + else + { + has_event_mask = 0; + goto cleanup_pinchrotation; + } + break; + + case GestureUpdate: + //if( ABS(diff_distance) < PINCHROTATION_DIST_THRESHOLD && ABS(diff_angle) < PINCHROTATION_ANGLE_THRESHOLD ) + // break; + +#ifdef __DETAIL_DEBUG__ + if( ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD ) + ErrorF("[GroupPinchRotation][M] zoom changed !\n"); + + if( ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD ) + ErrorF("[GroupPinchRotation][M] angle changed !\n"); +#endif//__DETAIL_DEBUG__ + +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation] PINCHROTATION Update ! cx=%d, cy=%d, state=%d\n", cx, cy, state); +#endif//__DETAIL_DEBUG__ + GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureUpdate); + prev_distance = cur_distance; + prev_angle = cur_angle; + break; + + case GestureDone: + default: + break; + } + } + break; + + case ET_ButtonRelease: + if( state != GestureEnd && num_pressed >= 2) + { +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); +#endif//__DETAIL_DEBUG__ + goto cleanup_pinchrotation; + } + + if( g_pGesture->num_pressed ) + break; + + goto cleanup_pinchrotation; + break; + } + + return; + +cleanup_pinchrotation: + + if( has_event_mask && (state == GestureBegin || state == GestureUpdate) ) + { + state = GestureEnd; +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation] PINCHROTATION End ! cx=%d, cy=%d, state=%d\n", cx, cy, state); +#endif//__DETAIL_DEBUG__ + GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureEnd); + } + else + { + g_pGesture->recognized_gesture &= ~PinchRotationFilterMask; + } - g_pGesture->recognized_gesture &= ~PinchRotationFilterMask; g_pGesture->filter_mask |= PinchRotationFilterMask; + + if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL ) + { +#ifdef __DETAIL_DEBUG__ + ErrorF("[GroupPinchRotation][cleanup] GestureFlushOrDrop() !\n"); +#endif//__DETAIL_DEBUG__ + + if( ERROR_INVALPTR == GestureFlushOrDrop() ) + { + GestureControl(g_pGesture->this_device, DEVICE_OFF); + } + } + + prev_distance = base_distance = 0.0f; + prev_angle = base_angle = 0.0f; + has_event_mask = num_pressed = 0; + state = GestureEnd; + cx = cy = 0; + TimerCancel(pinchrotation_event_timer); return; } @@ -1642,6 +1951,13 @@ GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg) GestureRecognize_GroupTapNHold(event_type, NULL, NULL, 0, 1); break; + case GestureNotifyPinchRotation: +#ifdef __DETAIL_DEBUG__ + ErrorF("[GestureEventTimerHandler] GestureNotifyPinchRotation (event_type = %d)\n", event_type); +#endif//__DETAIL_DEBUG__ + GestureRecognize_GroupPinchRotation(event_type, NULL, NULL, 0, 1); + break; + default: #ifdef __DETAIL_DEBUG__ ErrorF("[GestureEventTimerHandler] unknown event_type (=%d)\n", event_type); @@ -1675,13 +1991,23 @@ void GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device) { int i; - int idx = device->id - g_pGesture->first_fingerid; static OsTimerPtr single_finger_timer = NULL; + int idx = -1; - if( PROPAGATE_EVENTS == g_pGesture->ehtype ) + if( PROPAGATE_EVENTS == g_pGesture->ehtype || + device->id < g_pGesture->first_fingerid ) return; - if( device->id < g_pGesture->first_fingerid )//filtering device id : 2 + for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ ) + { + if( device->id == g_pGesture->mt_devices[i]->id ) + { + idx = i; + break; + } + } + + if( idx < 0 ) return; switch( type ) @@ -1827,7 +2153,7 @@ GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device) } if( !(g_pGesture->filter_mask & PinchRotationFilterMask) ) { - GestureRecognize_GroupPinchRotation(type, ev, device, idx); + GestureRecognize_GroupPinchRotation(type, ev, device, idx, 0); } if( !(g_pGesture->filter_mask & TapFilterMask) ) { diff --git a/src/gesture.h b/src/gesture.h index e9e17ff..8f7bed0 100755 --- a/src/gesture.h +++ b/src/gesture.h @@ -59,6 +59,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define AREA_CENTER_Y(extents) ((extents)->y1 + (((extents)->y2-(extents)->y1)/2)) #define AREA_SIZE(extents) (ABS((extents)->x2-(extents)->x1)*ABS((extents)->y2-(extents)->y1)) #define INBOX(r,x,y) ( ((r)->x2 > x) && ((r)->x1 <= x) && ((r)->y2 > y) && ((r)->y1 <= y) ) +#define AREA_HEIGHT(extents) (((extents)->y2)-((extents)->y1)) +#define AREA_WIDTH(extents) (((extents)->x2)-((extents)->x1)) +#define AREA_DIAG_LEN(extents) sqrt((AREA_WIDTH(extents)*AREA_WIDTH(extents))+(AREA_HEIGHT(extents)*AREA_HEIGHT(extents))) //tap #define TAP_THRESHOLD 100//in pixel @@ -95,6 +98,12 @@ enum #define PAN_UPDATE_MOVE_THRESHOLD 3//pixel #define PAN_TIME_THRESHOLD 300//ms +#define PINCHROTATION_TIME_THRESHOLD 500//ms +#define PINCHROTATION_INIT_DIST_THRESHOLD 25.0f +#define PINCHROTATION_INIT_ANGLE_THRESHOLD 0.2f +#define PINCHROTATION_DIST_THRESHOLD 25.0f +#define PINCHROTATION_ANGLE_THRESHOLD 0.2f + #define HOLD_AREA_THRESHOLD 2500//=50pixel * 50pixel #define HOLD_MOVE_THRESHOLD 10//pixel #define HOLD_TIME_THRESHOLD 500//ms @@ -116,6 +125,12 @@ enum #define FLICK_MOVE_THRESHOLD 100//pixel #define FLICK_MOVE_TIMEOUT 1000//ms +#define RAD_90DEG M_PI_2 +#define RAD_180DEG M_PI +#define RAD_270DEG (M_PI_2 * 3) +#define RAD_360DEG (M_PI * 2) +#define rad2degree(r) ((r) * 180/M_PI) + typedef enum _MTSyncType { MTOUCH_FRAME_SYNC_END,