Kaydet (Commit) 86aadc82 authored tarafından Tomaž Vajngerl's avatar Tomaž Vajngerl

android: Fennec PanZoomControler updates..

Change-Id: I277fbf522b16d9b479260df8372a5ee160adcc37
üst a9c434a2
...@@ -55,7 +55,7 @@ public class LOKitThread extends Thread { ...@@ -55,7 +55,7 @@ public class LOKitThread extends Thread {
mLayerClient.setPageRect(0, 0, mTileProvider.getPageWidth(), mTileProvider.getPageHeight()); mLayerClient.setPageRect(0, 0, mTileProvider.getPageWidth(), mTileProvider.getPageHeight());
mLayerClient.setViewportMetrics(mLayerClient.getViewportMetrics()); mLayerClient.setViewportMetrics(mLayerClient.getViewportMetrics());
mLayerClient.setForceRedraw(); mLayerClient.forceRedraw();
} }
/** Invalidate everything + handle the geometry change + draw. */ /** Invalidate everything + handle the geometry change + draw. */
......
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko;
import android.view.MotionEvent;
import android.view.View;
public interface OnInterceptTouchListener extends View.OnTouchListener {
/** Override this method for a chance to consume events before the view or its children */
public boolean onInterceptTouchEvent(View view, MotionEvent event);
}
...@@ -400,7 +400,7 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { ...@@ -400,7 +400,7 @@ public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener {
} }
/** Implementation of PanZoomTarget */ /** Implementation of PanZoomTarget */
public void setForceRedraw() { public void forceRedraw() {
mForceRedraw = true; mForceRedraw = true;
if (mGeckoIsReady) { if (mGeckoIsReady) {
geometryChanged(); geometryChanged();
......
...@@ -6,12 +6,13 @@ ...@@ -6,12 +6,13 @@
package org.mozilla.gecko.gfx; package org.mozilla.gecko.gfx;
import android.content.Context; import android.content.Context;
import android.os.Build;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Log; import android.util.Log;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View.OnTouchListener;
import org.mozilla.gecko.OnInterceptTouchListener;
import org.mozilla.gecko.ui.PanZoomController; import org.mozilla.gecko.ui.PanZoomController;
import org.mozilla.gecko.ui.SimpleScaleGestureDetector; import org.mozilla.gecko.ui.SimpleScaleGestureDetector;
...@@ -66,7 +67,7 @@ public final class TouchEventHandler { ...@@ -66,7 +67,7 @@ public final class TouchEventHandler {
private final ListenerTimeoutProcessor mListenerTimeoutProcessor; private final ListenerTimeoutProcessor mListenerTimeoutProcessor;
// the listener we use to notify gecko of touch events // the listener we use to notify gecko of touch events
private OnTouchListener mOnTouchListener; private OnInterceptTouchListener mOnTouchListener;
// whether or not we should wait for touch listeners to respond (this state is // whether or not we should wait for touch listeners to respond (this state is
// per-tab and is updated when we switch tabs). // per-tab and is updated when we switch tabs).
...@@ -127,13 +128,16 @@ public final class TouchEventHandler { ...@@ -127,13 +128,16 @@ public final class TouchEventHandler {
mView = view; mView = view;
mEventQueue = new LinkedList<MotionEvent>(); mEventQueue = new LinkedList<MotionEvent>();
mGestureDetector = new GestureDetector(context, layerClient.getGestureListener());
mScaleGestureDetector = new SimpleScaleGestureDetector(layerClient.getScaleGestureListener());
mPanZoomController = layerClient.getPanZoomController(); mPanZoomController = layerClient.getPanZoomController();
mGestureDetector = new GestureDetector(context, mPanZoomController);
mScaleGestureDetector = new SimpleScaleGestureDetector(mPanZoomController);
mListenerTimeoutProcessor = new ListenerTimeoutProcessor(); mListenerTimeoutProcessor = new ListenerTimeoutProcessor();
mDispatchEvents = true; mDispatchEvents = true;
mGestureDetector.setOnDoubleTapListener(layerClient.getDoubleTapListener()); mGestureDetector.setOnDoubleTapListener(mPanZoomController);
}
void destroy() {
} }
/* This function MUST be called on the UI thread */ /* This function MUST be called on the UI thread */
...@@ -145,12 +149,21 @@ public final class TouchEventHandler { ...@@ -145,12 +149,21 @@ public final class TouchEventHandler {
return true; return true;
} }
if (mOnTouchListener.onInterceptTouchEvent(mView, event)) {
return true;
}
// if this is a hover event just notify gecko, we don't have any interest in the java layer. // if this is a hover event just notify gecko, we don't have any interest in the java layer.
if (isHoverEvent(event)) { if (isHoverEvent(event)) {
mOnTouchListener.onTouch(mView, event); mOnTouchListener.onTouch(mView, event);
return true; return true;
} }
if (isScrollEvent(event)) {
dispatchEvent(event);
return true;
}
if (isDownEvent(event)) { if (isDownEvent(event)) {
// this is the start of a new block of events! whee! // this is the start of a new block of events! whee!
mHoldInQueue = mWaitForTouchListeners; mHoldInQueue = mWaitForTouchListeners;
...@@ -225,7 +238,7 @@ public final class TouchEventHandler { ...@@ -225,7 +238,7 @@ public final class TouchEventHandler {
} }
/* This function MUST be called on the UI thread. */ /* This function MUST be called on the UI thread. */
public void setOnTouchListener(OnTouchListener onTouchListener) { public void setOnTouchListener(OnInterceptTouchListener onTouchListener) {
mOnTouchListener = onTouchListener; mOnTouchListener = onTouchListener;
} }
...@@ -244,6 +257,14 @@ public final class TouchEventHandler { ...@@ -244,6 +257,14 @@ public final class TouchEventHandler {
return (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL); return (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL);
} }
private boolean isScrollEvent(MotionEvent event) {
if (Build.VERSION.SDK_INT <= 11) {
return false;
}
int action = (event.getAction() & MotionEvent.ACTION_MASK);
return (action == MotionEvent.ACTION_SCROLL);
}
/** /**
* Dispatch the event to the gesture detectors and the pan/zoom controller. * Dispatch the event to the gesture detectors and the pan/zoom controller.
*/ */
......
...@@ -50,6 +50,9 @@ public class PanZoomController ...@@ -50,6 +50,9 @@ public class PanZoomController
// The maximum amount we allow you to zoom into a page // The maximum amount we allow you to zoom into a page
private static final float MAX_ZOOM = 4.0f; private static final float MAX_ZOOM = 4.0f;
// The maximum amount we would like to scroll with the mouse
private static final float MAX_SCROLL = 0.075f * LOKitShell.getDpi();
private enum PanZoomState { private enum PanZoomState {
NOTHING, /* no touch-start events received */ NOTHING, /* no touch-start events received */
FLING, /* all touches removed, but we're still scrolling page */ FLING, /* all touches removed, but we're still scrolling page */
...@@ -110,7 +113,9 @@ public class PanZoomController ...@@ -110,7 +113,9 @@ public class PanZoomController
} }
private void setState(PanZoomState state) { private void setState(PanZoomState state) {
mState = state; if (state != mState) {
mState = state;
}
} }
private ImmutableViewportMetrics getMetrics() { private ImmutableViewportMetrics getMetrics() {
...@@ -131,6 +136,7 @@ public class PanZoomController ...@@ -131,6 +136,7 @@ public class PanZoomController
case MotionEvent.ACTION_MOVE: return onTouchMove(event); case MotionEvent.ACTION_MOVE: return onTouchMove(event);
case MotionEvent.ACTION_UP: return onTouchEnd(event); case MotionEvent.ACTION_UP: return onTouchEnd(event);
case MotionEvent.ACTION_CANCEL: return onTouchCancel(event); case MotionEvent.ACTION_CANCEL: return onTouchCancel(event);
case MotionEvent.ACTION_SCROLL: return onScroll(event);
default: return false; default: return false;
} }
} }
...@@ -158,6 +164,7 @@ public class PanZoomController ...@@ -158,6 +164,7 @@ public class PanZoomController
// transitions. // transitions.
synchronized (mTarget.getLock()) { synchronized (mTarget.getLock()) {
mTarget.setViewportMetrics(getValidViewportMetrics()); mTarget.setViewportMetrics(getValidViewportMetrics());
mTarget.forceRedraw();
} }
break; break;
} }
...@@ -214,7 +221,7 @@ public class PanZoomController ...@@ -214,7 +221,7 @@ public class PanZoomController
// We just interrupted a double-tap animation, so force a redraw in // We just interrupted a double-tap animation, so force a redraw in
// case this touchstart is just a tap that doesn't end up triggering // case this touchstart is just a tap that doesn't end up triggering
// a redraw // a redraw
mTarget.setForceRedraw(); mTarget.forceRedraw();
// fall through // fall through
case FLING: case FLING:
case BOUNCE: case BOUNCE:
...@@ -337,6 +344,18 @@ public class PanZoomController ...@@ -337,6 +344,18 @@ public class PanZoomController
return false; return false;
} }
private boolean onScroll(MotionEvent event) {
if (mState == PanZoomState.NOTHING || mState == PanZoomState.FLING) {
float scrollX = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
float scrollY = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
scrollBy(scrollX * MAX_SCROLL, scrollY * MAX_SCROLL);
bounce();
return true;
}
return false;
}
private void startTouch(float x, float y, long time) { private void startTouch(float x, float y, long time) {
mX.startTouch(x); mX.startTouch(x);
mY.startTouch(y); mY.startTouch(y);
...@@ -434,7 +453,7 @@ public class PanZoomController ...@@ -434,7 +453,7 @@ public class PanZoomController
} }
/* Performs a bounce-back animation to the given viewport metrics. */ /* Performs a bounce-back animation to the given viewport metrics. */
private void bounce(ImmutableViewportMetrics metrics) { private void bounce(ImmutableViewportMetrics metrics, PanZoomState state) {
stopAnimationTimer(); stopAnimationTimer();
ImmutableViewportMetrics bounceStartMetrics = getMetrics(); ImmutableViewportMetrics bounceStartMetrics = getMetrics();
...@@ -443,6 +462,8 @@ public class PanZoomController ...@@ -443,6 +462,8 @@ public class PanZoomController
return; return;
} }
setState(state);
// At this point we have already set mState to BOUNCE or ANIMATED_ZOOM, so // At this point we have already set mState to BOUNCE or ANIMATED_ZOOM, so
// getRedrawHint() is returning false. This means we can safely call // getRedrawHint() is returning false. This means we can safely call
// setAnimationTarget to set the new final display port and not have it get // setAnimationTarget to set the new final display port and not have it get
...@@ -453,8 +474,7 @@ public class PanZoomController ...@@ -453,8 +474,7 @@ public class PanZoomController
/* Performs a bounce-back animation to the nearest valid viewport metrics. */ /* Performs a bounce-back animation to the nearest valid viewport metrics. */
private void bounce() { private void bounce() {
setState(PanZoomState.BOUNCE); bounce(getValidViewportMetrics(), PanZoomState.BOUNCE);
bounce(getValidViewportMetrics());
} }
/* Starts the fling or bounce animation. */ /* Starts the fling or bounce animation. */
...@@ -654,7 +674,7 @@ public class PanZoomController ...@@ -654,7 +674,7 @@ public class PanZoomController
stopAnimationTimer(); stopAnimationTimer();
// Force a viewport synchronisation // Force a viewport synchronisation
mTarget.setForceRedraw(); mTarget.forceRedraw();
} }
/* Returns the nearest viewport metrics with no overscroll visible. */ /* Returns the nearest viewport metrics with no overscroll visible. */
...@@ -837,7 +857,8 @@ public class PanZoomController ...@@ -837,7 +857,8 @@ public class PanZoomController
startTouch(detector.getFocusX(), detector.getFocusY(), detector.getEventTime()); startTouch(detector.getFocusX(), detector.getFocusY(), detector.getEventTime());
// Force a viewport synchronisation // Force a viewport synchronisation
mTarget.setForceRedraw(); mTarget.forceRedraw();
} }
/** /**
...@@ -896,7 +917,6 @@ public class PanZoomController ...@@ -896,7 +917,6 @@ public class PanZoomController
* pixels. * pixels.
*/ */
private boolean animatedZoomTo(RectF zoomToRect) { private boolean animatedZoomTo(RectF zoomToRect) {
setState(PanZoomState.ANIMATED_ZOOM);
final float startZoom = getMetrics().zoomFactor; final float startZoom = getMetrics().zoomFactor;
RectF viewport = getMetrics().getViewport(); RectF viewport = getMetrics().getViewport();
...@@ -932,7 +952,7 @@ public class PanZoomController ...@@ -932,7 +952,7 @@ public class PanZoomController
// clamped down to prevent overscroll, over-zoom, and other bad conditions. // clamped down to prevent overscroll, over-zoom, and other bad conditions.
finalMetrics = getValidViewportMetrics(finalMetrics); finalMetrics = getValidViewportMetrics(finalMetrics);
bounce(finalMetrics); bounce(finalMetrics, PanZoomState.ANIMATED_ZOOM);
return true; return true;
} }
......
...@@ -16,7 +16,8 @@ public interface PanZoomTarget { ...@@ -16,7 +16,8 @@ public interface PanZoomTarget {
public void setAnimationTarget(ImmutableViewportMetrics viewport); public void setAnimationTarget(ImmutableViewportMetrics viewport);
public void setViewportMetrics(ImmutableViewportMetrics viewport); public void setViewportMetrics(ImmutableViewportMetrics viewport);
public void setForceRedraw(); /** This triggers an (asynchronous) viewport update/redraw. */
public void forceRedraw();
public boolean post(Runnable action); public boolean post(Runnable action);
public Object getLock(); public Object getLock();
......
...@@ -39,6 +39,7 @@ public class SimpleScaleGestureDetector { ...@@ -39,6 +39,7 @@ public class SimpleScaleGestureDetector {
private SimpleScaleGestureListener mListener; private SimpleScaleGestureListener mListener;
private long mLastEventTime; private long mLastEventTime;
private boolean mScaleResult;
/* Information about all pointers that are down. */ /* Information about all pointers that are down. */
private LinkedList<PointerInfo> mPointerInfo; private LinkedList<PointerInfo> mPointerInfo;
...@@ -53,6 +54,12 @@ public class SimpleScaleGestureDetector { ...@@ -53,6 +54,12 @@ public class SimpleScaleGestureDetector {
public void onTouchEvent(MotionEvent event) { public void onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) { switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
// If we get ACTION_DOWN while still tracking any pointers,
// something is wrong. Cancel the current gesture and start over.
if (getPointersDown() > 0)
onTouchEnd(event);
onTouchStart(event);
break;
case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_DOWN:
onTouchStart(event); onTouchStart(event);
break; break;
...@@ -101,7 +108,10 @@ public class SimpleScaleGestureDetector { ...@@ -101,7 +108,10 @@ public class SimpleScaleGestureDetector {
private void onTouchEnd(MotionEvent event) { private void onTouchEnd(MotionEvent event) {
mLastEventTime = event.getEventTime(); mLastEventTime = event.getEventTime();
boolean isCancel = (event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_CANCEL; int action = event.getAction() & MotionEvent.ACTION_MASK;
boolean isCancel = (action == MotionEvent.ACTION_CANCEL ||
action == MotionEvent.ACTION_DOWN);
int id = event.getPointerId(getActionIndex(event)); int id = event.getPointerId(getActionIndex(event));
ListIterator<PointerInfo> iterator = mPointerInfo.listIterator(); ListIterator<PointerInfo> iterator = mPointerInfo.listIterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
...@@ -196,9 +206,19 @@ public class SimpleScaleGestureDetector { ...@@ -196,9 +206,19 @@ public class SimpleScaleGestureDetector {
/* Sends the requested scale gesture notification to the listener. */ /* Sends the requested scale gesture notification to the listener. */
private void sendScaleGesture(EventType eventType) { private void sendScaleGesture(EventType eventType) {
switch (eventType) { switch (eventType) {
case BEGIN: mListener.onScaleBegin(this); break; case BEGIN:
case CONTINUE: mListener.onScale(this); break; mScaleResult = mListener.onScaleBegin(this);
case END: mListener.onScaleEnd(this); break; break;
case CONTINUE:
if (mScaleResult) {
mListener.onScale(this);
}
break;
case END:
if (mScaleResult) {
mListener.onScaleEnd(this);
}
break;
} }
} }
......
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