diff options
author | Sven Gothel <[email protected]> | 2013-03-24 14:07:11 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-03-24 14:07:11 +0100 |
commit | 21cde04129ea241744b95cad8fd0a545d3474b05 (patch) | |
tree | 32f345bdd6ecf15f3854b33b90c354c65d14fc90 /src/newt/classes/jogamp | |
parent | ded080fd890c21b54ba1f96d84f9e355711dc88a (diff) |
Android/NEWT MouseEvent: Fix Detection/Processing of 2-Finger-Scroll Gesture - Part 2
Multiple tests on different devices disclosed that:
- 1 of 2 pointers get disconnected every now and then ..
-> Shall tolerate this case
- dist-delta within gesture may shrink below doubleTouchSlope
-> Remove constraint after gesture detection
- Always validate pointer-id
GearsES2
- Works quite stable on several devices now
- Moved soft-keyboad show to 4-pointer pressed >= 0.7f pressure
Diffstat (limited to 'src/newt/classes/jogamp')
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java | 224 |
1 files changed, 143 insertions, 81 deletions
diff --git a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java index 21f552fdb..4c2ed06e8 100644 --- a/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java +++ b/src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java @@ -244,12 +244,11 @@ public class AndroidNewtEventFactory { return maxPressure; } - private final int touchSlop, touchSlop2x, touchSlopSquare, doubleTapSlop, doubleTapSlopSquare; + private final int touchSlop, touchSlopSquare, doubleTapSlop, doubleTapSlopSquare; public AndroidNewtEventFactory(android.content.Context context, android.os.Handler handler) { final android.view.ViewConfiguration configuration = android.view.ViewConfiguration.get(context); touchSlop = configuration.getScaledTouchSlop(); - touchSlop2x = 2*touchSlop; touchSlopSquare = touchSlop * touchSlop; doubleTapSlop = configuration.getScaledDoubleTapSlop(); doubleTapSlopSquare = doubleTapSlop * doubleTapSlop; @@ -294,32 +293,31 @@ public class AndroidNewtEventFactory { { final int aType0 = event.getActionMasked(); if( isOnTouchEvent ) { - boolean action = false; switch ( aType0 ) { case MotionEvent.ACTION_DOWN: - action = true; - // fall through intended case MotionEvent.ACTION_POINTER_DOWN: - gesture2FingerScrl.onDown(event, action); + gesture2FingerScrl.onDown(event); break; case MotionEvent.ACTION_UP: - action = true; - // fall through intended case MotionEvent.ACTION_POINTER_UP: - gesture2FingerScrl.onUp(event, action); + gesture2FingerScrl.onUp(event); break; case MotionEvent.ACTION_MOVE: - gesture2FingerScrl.onActionMove(event); + gesture2FingerScrl.onMove(event); break; } } - if( gesture2FingerScrl.isWithinGesture() ) { - final float[] rot = gesture2FingerScrl.getScrollDistanceXY(); - rotationXYZ[0] = rot[0] / rotationScale; - rotationXYZ[1] = rot[1] / rotationScale; - aType = ACTION_SCROLL; // 8 - rotationSource = 1; + if( gesture2FingerScrl.gestureStarted() ) { + if( gesture2FingerScrl.hasGesture(true) ) { + final float[] rot = gesture2FingerScrl.getScrollDistanceXY(); + rotationXYZ[0] = rot[0] / rotationScale; + rotationXYZ[1] = rot[1] / rotationScale; + aType = ACTION_SCROLL; // 8 + rotationSource = 1; + } else { + return new com.jogamp.newt.event.MouseEvent[0]; // skip, but cont. sending events + } } else { aType = aType0; } @@ -342,7 +340,7 @@ public class AndroidNewtEventFactory { modifiers |= com.jogamp.newt.event.InputEvent.SHIFT_MASK; } if(DEBUG_MOUSE_EVENT) { - System.err.println("createMouseEvent: Scroll "+rotationXYZ[0]+"/"+rotationXYZ[1]+", "+rotationScale+", mods "+modifiers+", source "+rotationSource); + System.err.println("createMouseEvent: Gesture2FingerScrl Scroll "+rotationXYZ[0]+"/"+rotationXYZ[1]+", "+rotationScale+", mods "+modifiers+", source "+rotationSource); } } @@ -423,38 +421,59 @@ public class AndroidNewtEventFactory { } static interface GestureHandler { - /** Returns true if within the gesture */ - public boolean isWithinGesture(); + /** + * Returns true if last on* command produced a gesture, otherwise false. + * @param clear if true, method clears the gesture flag. + */ + public boolean hasGesture(boolean clear); + /** Returns true if the gesture has started */ + public boolean gestureStarted(); /** Returns distance of the last consecutive double-tab scrolling. */ public float[] getScrollDistanceXY(); - - public void onUp(android.view.MotionEvent e, boolean action); - public void onDown(android.view.MotionEvent e, boolean action); - public void onActionMove(android.view.MotionEvent e); + public void onDown(android.view.MotionEvent e); + public void onUp(android.view.MotionEvent e); + public void onMove(android.view.MotionEvent e); } /** * Criteria related to Android parameter: * - ScaledDoubleTapSlop: - * - Max 2 finger distance + * - Max 2 finger distance to start 'scroll' mode * * - ScaledTouchSlop: * - Min. movement w/ 2 pointer withing ScaledDoubleTapSlop starting 'scroll' mode - * - Max. change of finger distance in respect to initiating 2-finger distance (2x ScaledTouchSlop) - * - Max. distance growth in respect to initiating 2-finger distance. + * - Max. distance growth in respect to initiated 2-finger distance. + * + * - Tolerate temporary lift of 1/2 pointer + * + * - Always validate pointer-id */ private final GestureHandler gesture2FingerScrl = new GestureHandler() { private final float[] scrollDistance = new float[] { 0f, 0f }; - private int dStartDist = 0; - private float dDownY = 0; - private float dDownX = 0; - private float dLastY = 0; - private float dLastX = 0; + private int[] pIds = new int[] { -1, -1 }; + private int startDist = -1; + private float downY = 0; + private float downX = 0; + private float lastY = 0; + private float lastX = 0; private int pointerDownCount = 0; - private boolean dDownScroll = false; + private boolean withinGesture = false; + private boolean hasGesture = false; public String toString() { - return "Gesture2FingerScrl[in "+dDownScroll+", pc "+pointerDownCount+"]"; + return "Gesture2FingerScrl[in "+withinGesture+", has "+hasGesture+", pc "+pointerDownCount+"]"; + } + + private void clear() { + downX = 0f; + downY = 0f; + lastX = 0f; + lastY = 0f; + startDist = -1; + withinGesture = false; + hasGesture = false; + pIds[0] = -1; + pIds[1] = -1; } private final int getSquareDistance(float x1, float y1, float x2, float y2) { @@ -463,76 +482,119 @@ public class AndroidNewtEventFactory { return deltaX * deltaX + deltaY * deltaY; } - public boolean isWithinGesture() { - return dDownScroll; + private int gesturePointers(final android.view.MotionEvent e, final int excludeIndex) { + int j = 0; + for(int i=e.getPointerCount()-1; i>=0; i--) { + if( excludeIndex != i ) { + final int id = e.getPointerId(i); + if( pIds[0] == id || pIds[1] == id ) { + j++; + } + } + } + return j; } + + @Override + public boolean gestureStarted() { + return 0 <= startDist && withinGesture; + } + + @Override + public boolean hasGesture(boolean clear) { + final boolean r = hasGesture; + if( clear ) { + hasGesture = false; + } + return r; + } + @Override public final float[] getScrollDistanceXY() { return scrollDistance; } @Override - public void onDown(android.view.MotionEvent e, boolean action) { + public void onDown(android.view.MotionEvent e) { pointerDownCount = e.getPointerCount(); - if( 2 == pointerDownCount ) { - final int sqDist = getSquareDistance(e.getX(0), e.getY(0), e.getX(1), e.getY(1)); - final boolean isDistWithinDoubleTapSlop = sqDist < doubleTapSlopSquare; - if(DEBUG_MOUSE_EVENT) { - System.err.println(this+".onDown: action "+action+", dist "+Math.sqrt(sqDist)+", distWithin2DTSlop "+isDistWithinDoubleTapSlop+", "+e); - } - if( isDistWithinDoubleTapSlop ) { - dDownX = e.getX(); - dDownY = e.getY(); - dLastX = dDownX; - dLastY = dDownY; - dStartDist = (int)Math.sqrt(sqDist); - } + final int gPtr = gesturePointers(e, -1); + if( 2 <= gPtr ) { // pick-up dLast coordinate to cont. gesture after temp loosing 1/2 pointers + lastX = e.getX(0); + lastY = e.getY(0); + } + if(DEBUG_MOUSE_EVENT) { + System.err.println(this+".onDown: gPtr "+gPtr+", "+e); } } @Override - public void onUp(android.view.MotionEvent e, boolean action) { + public void onUp(android.view.MotionEvent e) { pointerDownCount = e.getPointerCount(); - if(DEBUG_MOUSE_EVENT) { - System.err.println(this+".onrUp: action "+action+", "+e); - } - if( 2 >= pointerDownCount ) { - dDownScroll = false; + final int gPtr = gesturePointers(e, e.getActionIndex()); // w/o lifted pointer + if( 1 > gPtr ) { // tolerate lifting 1/2 gesture pointers temporary + clear(); } pointerDownCount--; // lifted now! - if(!dDownScroll) { - dDownY = 0f; - dDownX = 0f; - dLastY = 0f; - dLastX = 0f; + if(DEBUG_MOUSE_EVENT) { + System.err.println(this+".onUp: gPtr "+gPtr+", "+e); } } - + @Override - public void onActionMove(android.view.MotionEvent e) { + public void onMove(android.view.MotionEvent e) { pointerDownCount = e.getPointerCount(); if( 2 <= pointerDownCount ) { - final int sqDist = getSquareDistance(e.getX(0), e.getY(0), e.getX(1), e.getY(1)); - final int dist = (int)Math.sqrt(sqDist); - final float x = e.getX(); - final float y = e.getY(); + final float x0 = e.getX(0); + final float y0 = e.getY(0); + final int sqDist = getSquareDistance(x0, y0, e.getX(1), e.getY(1)); final boolean isDistWithinDoubleTapSlop = sqDist < doubleTapSlopSquare; - final boolean isDistDeltaWithinTouchSlop = Math.abs( dStartDist - dist ) <= touchSlop2x && - dist - dStartDist <= touchSlop; - if( !isDistWithinDoubleTapSlop || !isDistDeltaWithinTouchSlop ) { - dDownScroll = false; - } else if( !dDownScroll ) { - final int dX = (int) (x - dDownX); - final int dY = (int) (y - dDownY); - final int d = (dX * dX) + (dY * dY); - dDownScroll = d > touchSlopSquare; + final int dist = (int)Math.sqrt(sqDist); + if( !withinGesture ) { + int gPtr = 0; + if( isDistWithinDoubleTapSlop ) { + if( 0 > startDist ) { + gPtr = 2; + pIds[0] = e.getPointerId(0); + pIds[1] = e.getPointerId(1); + downX = x0; + downY = y0; + lastX = x0; + lastY = y0; + startDist = dist; + } else { + gPtr = gesturePointers(e, -1); + if( 2 <= gPtr ) { + final int dX = (int) (x0 - downX); + final int dY = (int) (y0 - downY); + final int d = (dX * dX) + (dY * dY); + withinGesture = d > touchSlopSquare; + } + } + } + if(DEBUG_MOUSE_EVENT) { + final double dX = x0 - downX; + final double dY = y0 - downY; + final double d = Math.sqrt( (dX * dX) + (dY * dY) ); + System.err.println(this+".onMove.0: mDist "+d+", pStartDist "+dist+", gPtr "+gPtr+", distWithin2DTSlop "+isDistWithinDoubleTapSlop+", dLast "+lastX+"/"+lastY+", "+e); + } } - scrollDistance[0] = dLastX - x; - scrollDistance[1] = dLastY - y; - dLastX = x; - dLastY = y; - if(DEBUG_MOUSE_EVENT) { - System.err.println(this+".onActionMove: startDist "+dStartDist+", dist "+dist+", distWithin2DTSlop "+isDistWithinDoubleTapSlop+", distDeltaWithinTSlop "+isDistDeltaWithinTouchSlop+", d "+scrollDistance[0]+"/"+scrollDistance[1]+", "+e); + if( withinGesture ) { + final int gPtr = gesturePointers(e, -1); + final boolean isDistGrowthWithinTouchSlop = dist - startDist <= touchSlop; + if( 2 > gPtr || !isDistGrowthWithinTouchSlop ) { + clear(); + } else { + scrollDistance[0] = lastX - x0; + scrollDistance[1] = lastY - y0; + lastX = x0; + lastY = y0; + hasGesture = true; + } + if(DEBUG_MOUSE_EVENT) { + System.err.println(this+".onMove.1: pStartDist "+startDist+", pDist "+dist+", gPtr "+gPtr+" ["+pIds[0]+", "+pIds[1]+"]"+ + ", distWithin2DTSlop "+isDistWithinDoubleTapSlop+", distGrowthWithinTSlop "+isDistGrowthWithinTouchSlop+ + ", dLast "+lastX+"/"+lastY+", d "+scrollDistance[0]+"/"+scrollDistance[1]+", "+e); + } } } } |