Kaydet (Commit) 2c15cb70 authored tarafından Tomaž Vajngerl's avatar Tomaž Vajngerl

android: extract touch handling into TouchEventHandler

Change-Id: I138f746940bf89349d4662c95427113bff221231
üst b0a1d430
...@@ -35,11 +35,11 @@ public final class DisplayPortMetrics { ...@@ -35,11 +35,11 @@ public final class DisplayPortMetrics {
public String toJSON() { public String toJSON() {
StringBuffer sb = new StringBuffer(256); StringBuffer sb = new StringBuffer(256);
sb.append("{ \"left\": ").append(mPosition.left) sb.append("{ \"left\": ").append(mPosition.left)
.append(", \"top\": ").append(mPosition.top) .append(", \"top\": ").append(mPosition.top)
.append(", \"right\": ").append(mPosition.right) .append(", \"right\": ").append(mPosition.right)
.append(", \"bottom\": ").append(mPosition.bottom) .append(", \"bottom\": ").append(mPosition.bottom)
.append(", \"resolution\": ").append(mResolution) .append(", \"resolution\": ").append(mResolution)
.append('}'); .append('}');
return sb.toString(); return sb.toString();
} }
......
...@@ -212,7 +212,7 @@ public class GeckoLayerClient { ...@@ -212,7 +212,7 @@ public class GeckoLayerClient {
mLayerController.getView().postDelayed(new AdjustRunnable(), MIN_VIEWPORT_CHANGE_DELAY - timeDelta); mLayerController.getView().postDelayed(new AdjustRunnable(), MIN_VIEWPORT_CHANGE_DELAY - timeDelta);
mPendingViewportAdjust = true; mPendingViewportAdjust = true;
} else { } else {
adjustViewport(); adjustViewport(null);
} }
} }
...@@ -220,15 +220,21 @@ public class GeckoLayerClient { ...@@ -220,15 +220,21 @@ public class GeckoLayerClient {
mViewportSizeChanged = true; mViewportSizeChanged = true;
} }
private void adjustViewport() { void adjustViewport(DisplayPortMetrics displayPort) {
ViewportMetrics viewportMetrics = ImmutableViewportMetrics metrics = mLayerController.getViewportMetrics();
new ViewportMetrics(mLayerController.getViewportMetrics());
viewportMetrics.setViewport(viewportMetrics.getClampedViewport()); ViewportMetrics clampedMetrics = new ViewportMetrics(metrics);
clampedMetrics.setViewport(clampedMetrics.getClampedViewport());
mDisplayPort = DisplayPortCalculator.calculate(mLayerController.getViewportMetrics()); if (displayPort == null) {
displayPort = DisplayPortCalculator.calculate(metrics,
mLayerController.getPanZoomController().getVelocityVector());
}
mDisplayPort = displayPort;
mGeckoViewport = clampedMetrics;
LOKitShell.sendEvent(LOEvent.viewport(viewportMetrics)); LOKitShell.sendEvent(LOEvent.viewport(clampedMetrics));
if (mViewportSizeChanged) { if (mViewportSizeChanged) {
mViewportSizeChanged = false; mViewportSizeChanged = false;
LOKitShell.viewSizeChanged(); LOKitShell.viewSizeChanged();
...@@ -240,7 +246,7 @@ public class GeckoLayerClient { ...@@ -240,7 +246,7 @@ public class GeckoLayerClient {
public void geometryChanged() { public void geometryChanged() {
sendResizeEventIfNecessary(false); sendResizeEventIfNecessary(false);
if (mLayerController.getRedrawHint()) if (mLayerController.getRedrawHint())
adjustViewport(); adjustViewport(null);
} }
public ViewportMetrics getGeckoViewportMetrics() { public ViewportMetrics getGeckoViewportMetrics() {
...@@ -267,7 +273,7 @@ public class GeckoLayerClient { ...@@ -267,7 +273,7 @@ public class GeckoLayerClient {
private class AdjustRunnable implements Runnable { private class AdjustRunnable implements Runnable {
public void run() { public void run() {
mPendingViewportAdjust = false; mPendingViewportAdjust = false;
adjustViewport(); adjustViewport(null);
} }
} }
} }
\ No newline at end of file
...@@ -44,7 +44,6 @@ import android.graphics.Bitmap; ...@@ -44,7 +44,6 @@ import android.graphics.Bitmap;
import android.graphics.PixelFormat; import android.graphics.PixelFormat;
import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView;
import android.util.Log; import android.util.Log;
import android.view.GestureDetector;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
...@@ -53,10 +52,8 @@ import android.view.inputmethod.EditorInfo; ...@@ -53,10 +52,8 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
import org.libreoffice.LibreOfficeMainActivity; import org.libreoffice.LibreOfficeMainActivity;
import org.mozilla.gecko.ui.SimpleScaleGestureDetector;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.util.LinkedList;
/** /**
* A view rendered by the layer compositor. * A view rendered by the layer compositor.
...@@ -67,18 +64,16 @@ import java.util.LinkedList; ...@@ -67,18 +64,16 @@ import java.util.LinkedList;
* Note that LayerView is accessed by Robocop via reflection. * Note that LayerView is accessed by Robocop via reflection.
*/ */
public class LayerView extends SurfaceView implements SurfaceHolder.Callback { public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
private static String LOGTAG = "GeckoLayerView";
private Context mContext; private Context mContext;
private LayerController mController; private LayerController mController;
private TouchEventHandler mTouchEventHandler;
private GLController mGLController; private GLController mGLController;
private InputConnectionHandler mInputConnectionHandler; private InputConnectionHandler mInputConnectionHandler;
private LayerRenderer mRenderer; private LayerRenderer mRenderer;
private GestureDetector mGestureDetector;
private SimpleScaleGestureDetector mScaleGestureDetector;
private long mRenderTime; private long mRenderTime;
private boolean mRenderTimeReset; private boolean mRenderTimeReset;
private static String LOGTAG = "GeckoLayerView";
/* List of events to be processed if the page does not prevent them. Should only be touched on the main thread */
private LinkedList<MotionEvent> mEventQueue = new LinkedList<MotionEvent>();
/* Must be a PAINT_xxx constant */ /* Must be a PAINT_xxx constant */
private int mPaintState = PAINT_NONE; private int mPaintState = PAINT_NONE;
...@@ -101,11 +96,8 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback { ...@@ -101,11 +96,8 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
mGLController = new GLController(this); mGLController = new GLController(this);
mContext = context; mContext = context;
mController = controller; mController = controller;
mTouchEventHandler = new TouchEventHandler(context, this, mController);
mRenderer = new LayerRenderer(this); mRenderer = new LayerRenderer(this);
mGestureDetector = new GestureDetector(context, controller.getGestureListener());
mScaleGestureDetector =
new SimpleScaleGestureDetector(controller.getScaleGestureListener());
mGestureDetector.setOnDoubleTapListener(controller.getDoubleTapListener());
mInputConnectionHandler = null; mInputConnectionHandler = null;
setFocusable(true); setFocusable(true);
...@@ -114,43 +106,13 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback { ...@@ -114,43 +106,13 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
createGLThread(); createGLThread();
} }
private void addToEventQueue(MotionEvent event) {
MotionEvent copy = MotionEvent.obtain(event);
mEventQueue.add(copy);
}
public void processEventQueue() {
MotionEvent event = mEventQueue.poll();
while(event != null) {
processEvent(event);
event = mEventQueue.poll();
}
}
public void clearEventQueue() {
mEventQueue.clear();
}
@Override @Override
public boolean onTouchEvent(MotionEvent event) { public boolean onTouchEvent(MotionEvent event) {
if (mController.onTouchEvent(event)) { return mTouchEventHandler.handleEvent(event);
addToEventQueue(event);
return true;
}
return processEvent(event);
}
private boolean processEvent(MotionEvent event) {
if (mGestureDetector.onTouchEvent(event))
return true;
mScaleGestureDetector.onTouchEvent(event);
if (mScaleGestureDetector.isInProgress())
return true;
mController.getPanZoomController().onTouchEvent(event);
return true;
} }
public LayerController getController() { return mController; } public LayerController getController() { return mController; }
public TouchEventHandler getTouchEventHandler() { return mTouchEventHandler; }
/** The LayerRenderer calls this to indicate that the window has changed size. */ /** The LayerRenderer calls this to indicate that the window has changed size. */
public void setViewportSize(IntSize size) { public void setViewportSize(IntSize size) {
...@@ -215,11 +177,6 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback { ...@@ -215,11 +177,6 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
} }
} }
public void changeCheckerboardBitmap(Bitmap bitmap) {
mRenderer.resetCheckerboard();
mRenderer.setCheckerboardBitmap(bitmap);
}
public void addLayer(Layer layer) { public void addLayer(Layer layer) {
mRenderer.addLayer(layer); mRenderer.addLayer(layer);
} }
...@@ -390,4 +347,9 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback { ...@@ -390,4 +347,9 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
super(e); super(e);
} }
} }
public void changeCheckerboardBitmap(Bitmap bitmap) {
mRenderer.resetCheckerboard();
mRenderer.setCheckerboardBitmap(bitmap);
}
} }
...@@ -114,7 +114,8 @@ public class PanZoomController ...@@ -114,7 +114,8 @@ public class PanZoomController
* similar to TOUCHING but after starting a pan */ * similar to TOUCHING but after starting a pan */
PANNING_HOLD_LOCKED, /* like PANNING_HOLD, but axis lock still in effect */ PANNING_HOLD_LOCKED, /* like PANNING_HOLD, but axis lock still in effect */
PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */ PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */
ANIMATED_ZOOM /* animated zoom to a new rect */ ANIMATED_ZOOM, /* animated zoom to a new rect */
BOUNCE /* in a bounce animation */
} }
private final LayerController mController; private final LayerController mController;
...@@ -172,22 +173,39 @@ public class PanZoomController ...@@ -172,22 +173,39 @@ public class PanZoomController
// if that's the case, abort any animation in progress and re-zoom so that the page // if that's the case, abort any animation in progress and re-zoom so that the page
// snaps to edges. for other cases (where the user's finger(s) are down) don't do // snaps to edges. for other cases (where the user's finger(s) are down) don't do
// anything special. // anything special.
if (mState == PanZoomState.FLING) { switch (mState) {
case FLING:
mX.stopFling(); mX.stopFling();
mY.stopFling(); mY.stopFling();
// fall through
case BOUNCE:
case ANIMATED_ZOOM:
// the zoom that's in progress likely makes no sense any more (such as if
// the screen orientation changed) so abort it
mState = PanZoomState.NOTHING; mState = PanZoomState.NOTHING;
// fall through
case NOTHING:
// Don't do animations here; they're distracting and can cause flashes on page
// transitions.
synchronized (mController) {
mController.setViewportMetrics(getValidViewportMetrics());
mController.notifyLayerClientOfGeometryChange();
}
break;
} }
} }
/** This must be called on the UI thread. */ /** This must be called on the UI thread. */
public void pageSizeUpdated() { public void pageSizeUpdated() {
if (mState == PanZoomState.NOTHING) { if (mState == PanZoomState.NOTHING) {
ViewportMetrics validated = getValidViewportMetrics(); synchronized (mController) {
if (! (new ViewportMetrics(mController.getViewportMetrics())).fuzzyEquals(validated)) { ViewportMetrics validated = getValidViewportMetrics();
// page size changed such that we are now in overscroll. snap to the if (! (new ViewportMetrics(mController.getViewportMetrics())).fuzzyEquals(validated)) {
// the nearest valid viewport // page size changed such that we are now in overscroll. snap to the
mController.setViewportMetrics(validated); // the nearest valid viewport
mController.notifyLayerClientOfGeometryChange(); mController.setViewportMetrics(validated);
mController.notifyLayerClientOfGeometryChange();
}
} }
} }
} }
...@@ -206,6 +224,7 @@ public class PanZoomController ...@@ -206,6 +224,7 @@ public class PanZoomController
case ANIMATED_ZOOM: case ANIMATED_ZOOM:
return false; return false;
case FLING: case FLING:
case BOUNCE:
case NOTHING: case NOTHING:
startTouch(event.getX(0), event.getY(0), event.getEventTime()); startTouch(event.getX(0), event.getY(0), event.getEventTime());
return false; return false;
...@@ -227,6 +246,7 @@ public class PanZoomController ...@@ -227,6 +246,7 @@ public class PanZoomController
switch (mState) { switch (mState) {
case NOTHING: case NOTHING:
case FLING: case FLING:
case BOUNCE:
// should never happen // should never happen
Log.e(LOGTAG, "Received impossible touch move while in " + mState); Log.e(LOGTAG, "Received impossible touch move while in " + mState);
return false; return false;
...@@ -268,6 +288,7 @@ public class PanZoomController ...@@ -268,6 +288,7 @@ public class PanZoomController
switch (mState) { switch (mState) {
case NOTHING: case NOTHING:
case FLING: case FLING:
case BOUNCE:
// should never happen // should never happen
Log.e(LOGTAG, "Received impossible touch end while in " + mState); Log.e(LOGTAG, "Received impossible touch end while in " + mState);
return false; return false;
...@@ -297,6 +318,7 @@ public class PanZoomController ...@@ -297,6 +318,7 @@ public class PanZoomController
private boolean onTouchCancel(MotionEvent event) { private boolean onTouchCancel(MotionEvent event) {
mState = PanZoomState.NOTHING; mState = PanZoomState.NOTHING;
cancelTouch();
// ensure we snap back if we're overscrolled // ensure we snap back if we're overscrolled
bounce(); bounce();
return false; return false;
...@@ -401,8 +423,11 @@ public class PanZoomController ...@@ -401,8 +423,11 @@ public class PanZoomController
return; return;
} }
mState = PanZoomState.FLING; mState = PanZoomState.BOUNCE;
// set the animation target *after* setting state BOUNCE, so that
// the getRedrawHint() is returning false and we don't clobber the display
// port we set as a result of this animation target call.
mController.setAnimationTarget(metrics);
startAnimationTimer(new BounceRunnable(bounceStartMetrics, metrics)); startAnimationTimer(new BounceRunnable(bounceStartMetrics, metrics));
} }
...@@ -444,6 +469,10 @@ public class PanZoomController ...@@ -444,6 +469,10 @@ public class PanZoomController
return FloatMath.sqrt(xvel * xvel + yvel * yvel); return FloatMath.sqrt(xvel * xvel + yvel * yvel);
} }
public PointF getVelocityVector() {
return new PointF(mX.getRealVelocity(), mY.getRealVelocity());
}
private boolean stopped() { private boolean stopped() {
return getVelocity() < STOPPED_THRESHOLD; return getVelocity() < STOPPED_THRESHOLD;
} }
...@@ -456,6 +485,9 @@ public class PanZoomController ...@@ -456,6 +485,9 @@ public class PanZoomController
mX.displace(); mX.displace();
mY.displace(); mY.displace();
PointF displacement = getDisplacement(); PointF displacement = getDisplacement();
if (FloatUtils.fuzzyEquals(displacement.x, 0.0f) && FloatUtils.fuzzyEquals(displacement.y, 0.0f)) {
return;
}
if (! mSubscroller.scrollBy(displacement)) { if (! mSubscroller.scrollBy(displacement)) {
synchronized (mController) { synchronized (mController) {
mController.scrollBy(displacement); mController.scrollBy(displacement);
...@@ -510,7 +542,7 @@ public class PanZoomController ...@@ -510,7 +542,7 @@ public class PanZoomController
* animation by setting the state to PanZoomState.NOTHING. Handle this case and bail * animation by setting the state to PanZoomState.NOTHING. Handle this case and bail
* out. * out.
*/ */
if (mState != PanZoomState.FLING) { if (mState != PanZoomState.BOUNCE) {
finishAnimation(); finishAnimation();
return; return;
} }
...@@ -756,7 +788,18 @@ public class PanZoomController ...@@ -756,7 +788,18 @@ public class PanZoomController
} }
public boolean getRedrawHint() { public boolean getRedrawHint() {
return (mState != PanZoomState.PINCHING && mState != PanZoomState.ANIMATED_ZOOM); switch (mState) {
case PINCHING:
case ANIMATED_ZOOM:
case BOUNCE:
// don't redraw during these because the zoom is (or might be, in the case
// of BOUNCE) be changing rapidly and gecko will have to redraw the entire
// display port area. we trigger a force-redraw upon exiting these states.
return false;
default:
// allow redrawing in other states
return true;
}
} }
@Override @Override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment