summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-03-24 14:07:11 +0100
committerSven Gothel <[email protected]>2013-03-24 14:07:11 +0100
commit21cde04129ea241744b95cad8fd0a545d3474b05 (patch)
tree32f345bdd6ecf15f3854b33b90c354c65d14fc90 /src
parentded080fd890c21b54ba1f96d84f9e355711dc88a (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')
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/event/AndroidNewtEventFactory.java224
-rw-r--r--src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java2
-rw-r--r--src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java1
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java15
4 files changed, 154 insertions, 88 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);
+ }
}
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
index 6aa2a045e..3e61e509c 100644
--- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
+++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivity0.java
@@ -54,7 +54,7 @@ public class MovieCubeActivity0 extends NewtBaseActivity {
MouseAdapter showKeyboardMouseListener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
- if(e.getPressure(true)>0.8f) {
+ if( e.getPointerCount() == 4 && e.getPressure(true) > 0.7f ) {
((com.jogamp.newt.Window) e.getSource()).setKeyboardVisible(true);
}
}
diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java
index 35cf9e7dd..af5b70776 100644
--- a/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java
+++ b/src/test/com/jogamp/opengl/test/android/NEWTGearsES2ActivityLauncher.java
@@ -60,6 +60,7 @@ public class NEWTGearsES2ActivityLauncher extends LauncherUtil.BaseActivityLaunc
props.setProperty("newt.debug.Window", "true");
props.setProperty("newt.debug.Window.MouseEvent", "true");
props.setProperty("newt.debug.Window.KeyEvent", "true");
+ // props.setProperty("newt.debug.Android.MouseEvent", "true");
}
@Override
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
index 06635f2d5..49f1940dc 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
@@ -434,12 +434,15 @@ public class GearsES2 implements GLEventListener {
}
public void mousePressed(MouseEvent e) {
- if( !gesture2PtrZoom.isWithinGesture() && e.getPointerCount()==1 ) {
- prevMouseX = e.getX();
- prevMouseY = e.getY();
- Object src = e.getSource();
- if(e.getPressure(true)>0.8f && src instanceof Window) { // show Keyboard
- ((Window) src).setKeyboardVisible(true);
+ if( !gesture2PtrZoom.isWithinGesture() ) {
+ if( e.getPointerCount()==1 ) {
+ prevMouseX = e.getX();
+ prevMouseY = e.getY();
+ } else if( e.getPointerCount() == 4 ) {
+ final Object src = e.getSource();
+ if( e.getPressure(true) > 0.7f && src instanceof Window) { // show Keyboard
+ ((Window) src).setKeyboardVisible(true);
+ }
}
}
}