Kaydet (Commit) 93e7ffbd authored tarafından Tomaž Vajngerl's avatar Tomaž Vajngerl

android: PanZoomControler updates from Fennec

Change-Id: Ic338221ced6133771af8f46ae4a257e043a1709f
üst dc169a05
......@@ -80,6 +80,10 @@ public class LayerController {
layerClient.setLayerController(this);
}
public void destroy() {
mPanZoomController.destroy();
}
public void setForceRedraw() {
mForceRedraw = true;
}
......@@ -93,26 +97,10 @@ public class LayerController {
return mViewportMetrics.getViewport();
}
public RectF getCssViewport() {
return mViewportMetrics.getCssViewport();
}
public FloatSize getViewportSize() {
return mViewportMetrics.getSize();
}
public RectF getPageRect() {
return mViewportMetrics.getPageRect();
}
public RectF getCssPageRect() {
return mViewportMetrics.getCssPageRect();
}
public PointF getOrigin() {
return mViewportMetrics.getOrigin();
}
public float getZoomFactor() {
return mViewportMetrics.zoomFactor;
}
......@@ -321,11 +309,6 @@ public class LayerController {
public void setAllowZoom(final boolean aValue) {
mAllowZoom = aValue;
mView.post(new Runnable() {
public void run() {
mView.getTouchEventHandler().setDoubleTapEnabled(aValue);
}
});
}
public boolean getAllowZoom() {
......
......@@ -188,11 +188,9 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
@Override
protected void finalize() throws Throwable {
try {
if (mCoordByteBuffer != null) {
DirectBufferAllocator.free(mCoordByteBuffer);
mCoordByteBuffer = null;
mCoordBuffer = null;
}
DirectBufferAllocator.free(mCoordByteBuffer);
mCoordByteBuffer = null;
mCoordBuffer = null;
} finally {
super.finalize();
}
......@@ -333,14 +331,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
moveFrameRateLayer(width, height);
}
// updating the state in the view/controller/client should be
// done on the main UI thread, not the GL renderer thread
mView.post(new Runnable() {
public void run() {
mView.setViewportSize(new IntSize(width, height));
}
});
/* TODO: Throw away tile images? */
}
......
......@@ -74,6 +74,13 @@ public class LayerView extends SurfaceView implements SurfaceHolder.Callback {
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN)
requestFocus();
return mTouchEventHandler.handleEvent(event);
}
@Override
public boolean onHoverEvent(MotionEvent event) {
return mTouchEventHandler.handleEvent(event);
}
......
......@@ -7,6 +7,7 @@ package org.mozilla.gecko.gfx;
import android.content.Context;
import android.os.SystemClock;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View.OnTouchListener;
......@@ -58,7 +59,6 @@ public final class TouchEventHandler {
private final GestureDetector mGestureDetector;
private final SimpleScaleGestureDetector mScaleGestureDetector;
private final PanZoomController mPanZoomController;
private final GestureDetector.OnDoubleTapListener mDoubleTapListener;
// the queue of events that we are holding on to while waiting for a preventDefault
// notification
......@@ -133,8 +133,7 @@ public final class TouchEventHandler {
mListenerTimeoutProcessor = new ListenerTimeoutProcessor();
mDispatchEvents = true;
mDoubleTapListener = controller.getDoubleTapListener();
setDoubleTapEnabled(true);
mGestureDetector.setOnDoubleTapListener(controller.getDoubleTapListener());
}
/* This function MUST be called on the UI thread */
......@@ -146,6 +145,12 @@ public final class TouchEventHandler {
return true;
}
// if this is a hover event just notify gecko, we don't have any interest in the java layer.
if (isHoverEvent(event)) {
mOnTouchListener.onTouch(mView, event);
return true;
}
if (isDownEvent(event)) {
// this is the start of a new block of events! whee!
mHoldInQueue = mWaitForTouchListeners;
......@@ -159,18 +164,20 @@ public final class TouchEventHandler {
// other blocks waiting in the queue, then we should let the pan/zoom controller
// know we are waiting for the touch listeners to run
if (mEventQueue.isEmpty()) {
mPanZoomController.waitingForTouchListeners(event);
mPanZoomController.startingNewEventBlock(event, true);
}
// if we're holding the events in the queue, set the timeout so that
// we dispatch these events if we don't get a default-prevented notification
mView.postDelayed(mListenerTimeoutProcessor, EVENT_LISTENER_TIMEOUT);
} else {
// if we're not holding these events, then we still need to pretend like
// we did and had a ListenerTimeoutProcessor fire so that when we get
// the default-prevented notification for this block, it doesn't accidentally
// act upon some other block
mProcessingBalance++;
// we're not going to be holding this block of events in the queue, but we need
// a marker of some sort so that the processEventBlock loop deals with the blocks
// in the right order as notifications come in. we use a single null event in
// the queue as a placeholder for a block of events that has already been dispatched.
mEventQueue.add(null);
mPanZoomController.startingNewEventBlock(event, false);
}
// set the timeout so that we dispatch these events and update mProcessingBalance
// if we don't get a default-prevented notification
mView.postDelayed(mListenerTimeoutProcessor, EVENT_LISTENER_TIMEOUT);
}
// if we need to hold the events, add it to the queue. if we need to dispatch
......@@ -212,11 +219,6 @@ public final class TouchEventHandler {
mProcessingBalance--;
}
/* This function MUST be called on the UI thread. */
public void setDoubleTapEnabled(boolean aValue) {
mGestureDetector.setOnDoubleTapListener(aValue ? mDoubleTapListener : null);
}
/* This function MUST be called on the UI thread. */
public void setWaitForTouchListeners(boolean aValue) {
mWaitForTouchListeners = aValue;
......@@ -227,6 +229,11 @@ public final class TouchEventHandler {
mOnTouchListener = onTouchListener;
}
private boolean isHoverEvent(MotionEvent event) {
int action = (event.getAction() & MotionEvent.ACTION_MASK);
return (action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE || action == MotionEvent.ACTION_HOVER_EXIT);
}
private boolean isDownEvent(MotionEvent event) {
int action = (event.getAction() & MotionEvent.ACTION_MASK);
return (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN);
......@@ -242,16 +249,7 @@ public final class TouchEventHandler {
*/
private void dispatchEvent(MotionEvent event) {
if (mGestureDetector.onTouchEvent(event)) {
// An up/cancel event should get passed to both detectors, in
// case it comes from a pointer the scale detector is tracking.
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
break;
default:
return;
}
return;
}
mScaleGestureDetector.onTouchEvent(event);
if (mScaleGestureDetector.isInProgress()) {
......@@ -272,6 +270,11 @@ public final class TouchEventHandler {
dispatchEvent(MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0));
}
if (mEventQueue.isEmpty()) {
Log.e(LOGTAG, "Unexpected empty event queue in processEventBlock!", new Exception());
return;
}
// the odd loop condition is because the first event in the queue will
// always be a DOWN or POINTER_DOWN event, and we want to process all
// the events in the queue starting at that one, up to but not including
......@@ -279,15 +282,19 @@ public final class TouchEventHandler {
MotionEvent event = mEventQueue.poll();
while (true) {
// for each event we process, only dispatch it if the block hasn't been
// default-prevented.
if (allowDefaultAction) {
dispatchEvent(event);
} else if (touchFinished(event)) {
mPanZoomController.preventedTouchFinished();
// event being null here is valid and represents a block of events
// that has already been dispatched.
if (event != null) {
// for each event we process, only dispatch it if the block hasn't been
// default-prevented.
if (allowDefaultAction) {
dispatchEvent(event);
} else if (touchFinished(event)) {
mPanZoomController.preventedTouchFinished();
}
}
event = mEventQueue.peek();
if (event == null) {
if (mEventQueue.isEmpty()) {
// we have processed the backlog of events, and are all caught up.
// now we can set clear the hold flag and set the dispatch flag so
// that the handleEvent() function can do the right thing for all
......@@ -297,10 +304,13 @@ public final class TouchEventHandler {
mDispatchEvents = allowDefaultAction;
break;
}
if (isDownEvent(event)) {
event = mEventQueue.peek();
if (event == null || isDownEvent(event)) {
// we have finished processing the block we were interested in.
// now we wait for the next call to processEventBlock
mPanZoomController.waitingForTouchListeners(event);
if (event != null) {
mPanZoomController.startingNewEventBlock(event, true);
}
break;
}
// pop the event we peeked above, as it is still part of the block and
......
......@@ -14,6 +14,7 @@ import android.view.MotionEvent;
import org.libreoffice.LOKitShell;
import org.libreoffice.LibreOfficeMainActivity;
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
import org.mozilla.gecko.gfx.LayerController;
import org.mozilla.gecko.gfx.ViewportMetrics;
import org.mozilla.gecko.util.FloatUtils;
......@@ -117,7 +118,19 @@ public class PanZoomController
mMainThread = LibreOfficeMainActivity.mAppContext.getMainLooper().getThread();
checkMainThread();
mState = PanZoomState.NOTHING;
setState(PanZoomState.NOTHING);
}
public void destroy() {
mSubscroller.destroy();
}
private void setState(PanZoomState state) {
mState = state;
}
private ImmutableViewportMetrics getMetrics() {
return mController.getViewportMetrics();
}
// for debugging bug 713011; it can be taken out once that is resolved.
......@@ -171,7 +184,7 @@ public class PanZoomController
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;
setState(PanZoomState.NOTHING);
// fall through
case NOTHING:
// Don't do animations here; they're distracting and can cause flashes on page
......@@ -185,14 +198,14 @@ public class PanZoomController
}
/** This function must be called on the UI thread. */
public void waitingForTouchListeners(MotionEvent event) {
public void startingNewEventBlock(MotionEvent event, boolean waitingForTouchListeners) {
checkMainThread();
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
mSubscroller.cancel();
if (waitingForTouchListeners && (event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
// this is the first touch point going down, so we enter the pending state
mSubscroller.cancel();
// seting the state will kill any animations in progress, possibly leaving
// the page in overscroll
mState = PanZoomState.WAITING_LISTENERS;
setState(PanZoomState.WAITING_LISTENERS);
}
}
......@@ -203,7 +216,6 @@ public class PanZoomController
// if we enter here, we just finished a block of events whose default actions
// were prevented by touch listeners. Now there are no touch points left, so
// we need to reset our state and re-bounce because we might be in overscroll
mState = PanZoomState.NOTHING;
bounce();
}
}
......@@ -213,7 +225,7 @@ public class PanZoomController
if (mState == PanZoomState.NOTHING) {
synchronized (mController) {
ViewportMetrics validated = getValidViewportMetrics();
if (! (new ViewportMetrics(mController.getViewportMetrics())).fuzzyEquals(validated)) {
if (! (new ViewportMetrics(getMetrics())).fuzzyEquals(validated)) {
// page size changed such that we are now in overscroll. snap to the
// the nearest valid viewport
mController.setViewportMetrics(validated);
......@@ -231,7 +243,6 @@ public class PanZoomController
// user is taking control of movement, so stop
// any auto-movement we have going
stopAnimationTimer();
mSubscroller.cancel();
switch (mState) {
case ANIMATED_ZOOM:
......@@ -285,14 +296,14 @@ public class PanZoomController
return true;
case PANNING_HOLD_LOCKED:
mState = PanZoomState.PANNING_LOCKED;
setState(PanZoomState.PANNING_LOCKED);
// fall through
case PANNING_LOCKED:
track(event);
return true;
case PANNING_HOLD:
mState = PanZoomState.PANNING;
setState(PanZoomState.PANNING);
// fall through
case PANNING:
track(event);
......@@ -322,7 +333,6 @@ public class PanZoomController
return false;
case TOUCHING:
mState = PanZoomState.NOTHING;
// the switch into TOUCHING might have happened while the page was
// snapping back after overscroll. we need to finish the snap if that
// was the case
......@@ -333,12 +343,12 @@ public class PanZoomController
case PANNING_LOCKED:
case PANNING_HOLD:
case PANNING_HOLD_LOCKED:
mState = PanZoomState.FLING;
setState(PanZoomState.FLING);
fling();
return true;
case PINCHING:
mState = PanZoomState.NOTHING;
setState(PanZoomState.NOTHING);
return true;
}
Log.e(LOGTAG, "Unhandled case " + mState + " in onTouchEnd");
......@@ -357,7 +367,6 @@ public class PanZoomController
}
cancelTouch();
mState = PanZoomState.NOTHING;
// ensure we snap back if we're overscrolled
bounce();
return false;
......@@ -366,7 +375,7 @@ public class PanZoomController
private void startTouch(float x, float y, long time) {
mX.startTouch(x);
mY.startTouch(y);
mState = PanZoomState.TOUCHING;
setState(PanZoomState.TOUCHING);
mLastEventTime = time;
}
......@@ -384,12 +393,12 @@ public class PanZoomController
if (angle < AXIS_LOCK_ANGLE || angle > (Math.PI - AXIS_LOCK_ANGLE)) {
mY.setScrollingDisabled(true);
mState = PanZoomState.PANNING_LOCKED;
setState(PanZoomState.PANNING_LOCKED);
} else if (Math.abs(angle - (Math.PI / 2)) < AXIS_LOCK_ANGLE) {
mX.setScrollingDisabled(true);
mState = PanZoomState.PANNING_LOCKED;
setState(PanZoomState.PANNING_LOCKED);
} else {
mState = PanZoomState.PANNING;
setState(PanZoomState.PANNING);
}
}
......@@ -425,13 +434,13 @@ public class PanZoomController
if (stopped()) {
if (mState == PanZoomState.PANNING) {
mState = PanZoomState.PANNING_HOLD;
setState(PanZoomState.PANNING_HOLD);
} else if (mState == PanZoomState.PANNING_LOCKED) {
mState = PanZoomState.PANNING_HOLD_LOCKED;
setState(PanZoomState.PANNING_HOLD_LOCKED);
} else {
// should never happen, but handle anyway for robustness
Log.e(LOGTAG, "Impossible case " + mState + " when stopped in track");
mState = PanZoomState.PANNING_HOLD_LOCKED;
setState(PanZoomState.PANNING_HOLD_LOCKED);
}
}
......@@ -456,9 +465,9 @@ public class PanZoomController
private void bounce(ViewportMetrics metrics) {
stopAnimationTimer();
ViewportMetrics bounceStartMetrics = new ViewportMetrics(mController.getViewportMetrics());
ViewportMetrics bounceStartMetrics = new ViewportMetrics(getMetrics());
if (bounceStartMetrics.fuzzyEquals(metrics)) {
mState = PanZoomState.NOTHING;
setState(PanZoomState.NOTHING);
return;
}
......@@ -472,7 +481,7 @@ public class PanZoomController
/* Performs a bounce-back animation to the nearest valid viewport metrics. */
private void bounce() {
mState = PanZoomState.BOUNCE;
setState(PanZoomState.BOUNCE);
bounce(getValidViewportMetrics());
}
......@@ -596,7 +605,7 @@ public class PanZoomController
/* Finally, if there's nothing else to do, complete the animation and go to sleep. */
finishBounce();
finishAnimation();
mState = PanZoomState.NOTHING;
setState(PanZoomState.NOTHING);
}
/* Performs one frame of a bounce animation. */
......@@ -664,7 +673,7 @@ public class PanZoomController
bounce();
} else {
finishAnimation();
mState = PanZoomState.NOTHING;
setState(PanZoomState.NOTHING);
}
}
}
......@@ -672,7 +681,6 @@ public class PanZoomController
private void finishAnimation() {
checkMainThread();
Log.d(LOGTAG, "Finishing animation at " + mController.getViewportMetrics());
stopAnimationTimer();
// Force a viewport synchronisation
......@@ -682,12 +690,10 @@ public class PanZoomController
/* Returns the nearest viewport metrics with no overscroll visible. */
private ViewportMetrics getValidViewportMetrics() {
return getValidViewportMetrics(new ViewportMetrics(mController.getViewportMetrics()));
return getValidViewportMetrics(new ViewportMetrics(getMetrics()));
}
private ViewportMetrics getValidViewportMetrics(ViewportMetrics viewportMetrics) {
Log.d(LOGTAG, "generating valid viewport using " + viewportMetrics);
/* First, we adjust the zoom factor so that we can make no overscrolled area visible. */
float zoomFactor = viewportMetrics.getZoomFactor();
RectF pageRect = viewportMetrics.getPageRect();
......@@ -740,7 +746,6 @@ public class PanZoomController
/* Now we pan to the right origin. */
viewportMetrics.setViewport(viewportMetrics.getClampedViewport());
Log.d(LOGTAG, "generated valid viewport as " + viewportMetrics);
return viewportMetrics;
}
......@@ -748,25 +753,25 @@ public class PanZoomController
private class AxisX extends Axis {
AxisX(SubdocumentScrollHelper subscroller) { super(subscroller); }
@Override
public float getOrigin() { return mController.getOrigin().x; }
public float getOrigin() { return getMetrics().viewportRectLeft; }
@Override
protected float getViewportLength() { return mController.getViewportSize().width; }
protected float getViewportLength() { return getMetrics().getWidth(); }
@Override
protected float getPageStart() { return mController.getPageRect().left; }
protected float getPageStart() { return getMetrics().pageRectLeft; }
@Override
protected float getPageLength() { return mController.getPageRect().width(); }
protected float getPageLength() { return getMetrics().getPageWidth(); }
}
private class AxisY extends Axis {
AxisY(SubdocumentScrollHelper subscroller) { super(subscroller); }
@Override
public float getOrigin() { return mController.getOrigin().y; }
public float getOrigin() { return getMetrics().viewportRectTop; }
@Override
protected float getViewportLength() { return mController.getViewportSize().height; }
protected float getViewportLength() { return getMetrics().getHeight(); }
@Override
protected float getPageStart() { return mController.getPageRect().top; }
protected float getPageStart() { return getMetrics().pageRectTop; }
@Override
protected float getPageLength() { return mController.getPageRect().height(); }
protected float getPageLength() { return getMetrics().getPageHeight(); }
}
/*
......@@ -774,15 +779,13 @@ public class PanZoomController
*/
@Override
public boolean onScaleBegin(SimpleScaleGestureDetector detector) {
Log.d(LOGTAG, "onScaleBegin in " + mState);
if (mState == PanZoomState.ANIMATED_ZOOM)
return false;
if (!mController.getAllowZoom())
return false;
mState = PanZoomState.PINCHING;
setState(PanZoomState.PINCHING);
mLastZoomFocus = new PointF(detector.getFocusX(), detector.getFocusY());
cancelTouch();
......@@ -791,9 +794,6 @@ public class PanZoomController
@Override
public boolean onScale(SimpleScaleGestureDetector detector) {
Log.d(LOGTAG, "onScale in state " + mState);
if (mState != PanZoomState.PINCHING)
return false;
......@@ -857,8 +857,6 @@ public class PanZoomController
@Override
public void onScaleEnd(SimpleScaleGestureDetector detector) {
Log.d(LOGTAG, "onScaleEnd in " + mState);
if (mState == PanZoomState.ANIMATED_ZOOM)
return;
......@@ -892,23 +890,17 @@ public class PanZoomController
@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
// When zooming is enabled, wait to see if there's a double-tap.
if (mController.getAllowZoom())
return false;
return true;
return false;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
// When zooming is disabled, we handle this in onSingleTapUp.
if (!mController.getAllowZoom())
return false;
return true;
}
@Override
public boolean onDoubleTap(MotionEvent motionEvent) {
if (!mController.getAllowZoom())
return false;
return true;
}
......@@ -922,7 +914,7 @@ public class PanZoomController
* pixels.
*/
private boolean animatedZoomTo(RectF zoomToRect) {
mState = PanZoomState.ANIMATED_ZOOM;
setState(PanZoomState.ANIMATED_ZOOM);
final float startZoom = mController.getZoomFactor();
RectF viewport = mController.getViewport();
......@@ -948,7 +940,7 @@ public class PanZoomController
float finalZoom = viewport.width() / zoomToRect.width();
ViewportMetrics finalMetrics = new ViewportMetrics(mController.getViewportMetrics());
ViewportMetrics finalMetrics = new ViewportMetrics(getMetrics());
finalMetrics.setOrigin(new PointF(zoomToRect.left * finalMetrics.getZoomFactor(),
zoomToRect.top * finalMetrics.getZoomFactor()));
finalMetrics.scaleTo(finalZoom, new PointF(0.0f, 0.0f));
......@@ -960,4 +952,10 @@ public class PanZoomController
bounce(finalMetrics);
return true;
}
/** This function must be called from the UI thread. */
public void abortPanning() {
checkMainThread();
bounce();
}
}
......@@ -45,6 +45,9 @@ class SubdocumentScrollHelper {
mPendingDisplacement = new PointF();
}
void destroy() {
}
boolean scrollBy(PointF displacement) {
if (! mOverridePanning) {
return false;
......
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