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 {
mLayerClient.setPageRect(0, 0, mTileProvider.getPageWidth(), mTileProvider.getPageHeight());
mLayerClient.setViewportMetrics(mLayerClient.getViewportMetrics());
mLayerClient.setForceRedraw();
mLayerClient.forceRedraw();
}
/** 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 {
}
/** Implementation of PanZoomTarget */
public void setForceRedraw() {
public void forceRedraw() {
mForceRedraw = true;
if (mGeckoIsReady) {
geometryChanged();
......
......@@ -6,12 +6,13 @@
package org.mozilla.gecko.gfx;
import android.content.Context;
import android.os.Build;
import android.os.SystemClock;
import android.util.Log;
import android.view.GestureDetector;
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.SimpleScaleGestureDetector;
......@@ -66,7 +67,7 @@ public final class TouchEventHandler {
private final ListenerTimeoutProcessor mListenerTimeoutProcessor;
// 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
// per-tab and is updated when we switch tabs).
......@@ -127,13 +128,16 @@ public final class TouchEventHandler {
mView = view;
mEventQueue = new LinkedList<MotionEvent>();
mGestureDetector = new GestureDetector(context, layerClient.getGestureListener());
mScaleGestureDetector = new SimpleScaleGestureDetector(layerClient.getScaleGestureListener());
mPanZoomController = layerClient.getPanZoomController();
mGestureDetector = new GestureDetector(context, mPanZoomController);
mScaleGestureDetector = new SimpleScaleGestureDetector(mPanZoomController);
mListenerTimeoutProcessor = new ListenerTimeoutProcessor();
mDispatchEvents = true;
mGestureDetector.setOnDoubleTapListener(layerClient.getDoubleTapListener());
mGestureDetector.setOnDoubleTapListener(mPanZoomController);
}
void destroy() {
}
/* This function MUST be called on the UI thread */
......@@ -145,12 +149,21 @@ public final class TouchEventHandler {
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 (isHoverEvent(event)) {
mOnTouchListener.onTouch(mView, event);
return true;
}
if (isScrollEvent(event)) {
dispatchEvent(event);
return true;
}
if (isDownEvent(event)) {
// this is the start of a new block of events! whee!
mHoldInQueue = mWaitForTouchListeners;
......@@ -225,7 +238,7 @@ public final class TouchEventHandler {
}
/* This function MUST be called on the UI thread. */
public void setOnTouchListener(OnTouchListener onTouchListener) {
public void setOnTouchListener(OnInterceptTouchListener onTouchListener) {
mOnTouchListener = onTouchListener;
}
......@@ -244,6 +257,14 @@ public final class TouchEventHandler {
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.
*/
......
......@@ -50,6 +50,9 @@ public class PanZoomController
// The maximum amount we allow you to zoom into a page
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 {
NOTHING, /* no touch-start events received */
FLING, /* all touches removed, but we're still scrolling page */
......@@ -110,7 +113,9 @@ public class PanZoomController
}
private void setState(PanZoomState state) {
mState = state;
if (state != mState) {
mState = state;
}
}
private ImmutableViewportMetrics getMetrics() {
......@@ -131,6 +136,7 @@ public class PanZoomController
case MotionEvent.ACTION_MOVE: return onTouchMove(event);
case MotionEvent.ACTION_UP: return onTouchEnd(event);
case MotionEvent.ACTION_CANCEL: return onTouchCancel(event);
case MotionEvent.ACTION_SCROLL: return onScroll(event);
default: return false;
}
}
......@@ -158,6 +164,7 @@ public class PanZoomController
// transitions.
synchronized (mTarget.getLock()) {
mTarget.setViewportMetrics(getValidViewportMetrics());
mTarget.forceRedraw();
}
break;
}
......@@ -214,7 +221,7 @@ public class PanZoomController
// 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
// a redraw
mTarget.setForceRedraw();
mTarget.forceRedraw();
// fall through
case FLING:
case BOUNCE:
......@@ -337,6 +344,18 @@ public class PanZoomController
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) {
mX.startTouch(x);
mY.startTouch(y);
......@@ -434,7 +453,7 @@ public class PanZoomController
}
/* Performs a bounce-back animation to the given viewport metrics. */
private void bounce(ImmutableViewportMetrics metrics) {
private void bounce(ImmutableViewportMetrics metrics, PanZoomState state) {
stopAnimationTimer();
ImmutableViewportMetrics bounceStartMetrics = getMetrics();
......@@ -443,6 +462,8 @@ public class PanZoomController
return;
}
setState(state);
// At this point we have already set mState to BOUNCE or ANIMATED_ZOOM, so
// getRedrawHint() is returning false. This means we can safely call
// setAnimationTarget to set the new final display port and not have it get
......@@ -453,8 +474,7 @@ public class PanZoomController
/* Performs a bounce-back animation to the nearest valid viewport metrics. */
private void bounce() {
setState(PanZoomState.BOUNCE);
bounce(getValidViewportMetrics());
bounce(getValidViewportMetrics(), PanZoomState.BOUNCE);
}
/* Starts the fling or bounce animation. */
......@@ -654,7 +674,7 @@ public class PanZoomController
stopAnimationTimer();
// Force a viewport synchronisation
mTarget.setForceRedraw();
mTarget.forceRedraw();
}
/* Returns the nearest viewport metrics with no overscroll visible. */
......@@ -837,7 +857,8 @@ public class PanZoomController
startTouch(detector.getFocusX(), detector.getFocusY(), detector.getEventTime());
// Force a viewport synchronisation
mTarget.setForceRedraw();
mTarget.forceRedraw();
}
/**
......@@ -896,7 +917,6 @@ public class PanZoomController
* pixels.
*/
private boolean animatedZoomTo(RectF zoomToRect) {
setState(PanZoomState.ANIMATED_ZOOM);
final float startZoom = getMetrics().zoomFactor;
RectF viewport = getMetrics().getViewport();
......@@ -932,7 +952,7 @@ public class PanZoomController
// clamped down to prevent overscroll, over-zoom, and other bad conditions.
finalMetrics = getValidViewportMetrics(finalMetrics);
bounce(finalMetrics);
bounce(finalMetrics, PanZoomState.ANIMATED_ZOOM);
return true;
}
......
......@@ -16,7 +16,8 @@ public interface PanZoomTarget {
public void setAnimationTarget(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 Object getLock();
......
......@@ -39,6 +39,7 @@ public class SimpleScaleGestureDetector {
private SimpleScaleGestureListener mListener;
private long mLastEventTime;
private boolean mScaleResult;
/* Information about all pointers that are down. */
private LinkedList<PointerInfo> mPointerInfo;
......@@ -53,6 +54,12 @@ public class SimpleScaleGestureDetector {
public void onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
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:
onTouchStart(event);
break;
......@@ -101,7 +108,10 @@ public class SimpleScaleGestureDetector {
private void onTouchEnd(MotionEvent event) {
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));
ListIterator<PointerInfo> iterator = mPointerInfo.listIterator();
while (iterator.hasNext()) {
......@@ -196,9 +206,19 @@ public class SimpleScaleGestureDetector {
/* Sends the requested scale gesture notification to the listener. */
private void sendScaleGesture(EventType eventType) {
switch (eventType) {
case BEGIN: mListener.onScaleBegin(this); break;
case CONTINUE: mListener.onScale(this); break;
case END: mListener.onScaleEnd(this); break;
case BEGIN:
mScaleResult = mListener.onScaleBegin(this);
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