diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.com> | 2014-11-30 17:18:56 +0100 |
---|---|---|
committer | Tomaž Vajngerl <tomaz.vajngerl@collabora.com> | 2014-12-04 23:04:29 +0100 |
commit | 86aadc8276a69079ee45a128a713f91ae544e02e (patch) | |
tree | 967c8537bf0dac1fb846d3015d5181563ca56fef /android | |
parent | a9c434a284ee9a6a2dda17d0644e6f8972f568b7 (diff) |
android: Fennec PanZoomControler updates..
Change-Id: I277fbf522b16d9b479260df8372a5ee160adcc37
Diffstat (limited to 'android')
7 files changed, 98 insertions, 22 deletions
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java index c6af5e724833..30a8bc965979 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java @@ -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. */ diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/OnInterceptTouchListener.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/OnInterceptTouchListener.java new file mode 100644 index 000000000000..d0cd3d48a943 --- /dev/null +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/OnInterceptTouchListener.java @@ -0,0 +1,14 @@ +/* -*- 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); +} diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java index 7efed043e3b0..aa47aaac93fa 100644 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java @@ -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(); diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java index f0fe21baf0c4..a17e63c93478 100644 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java @@ -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. */ diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/PanZoomController.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/PanZoomController.java index 555c7ebe60fa..65daf76a484f 100644 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/PanZoomController.java +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/PanZoomController.java @@ -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; } diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/PanZoomTarget.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/PanZoomTarget.java index fdac874ee6f9..b4eeb52a7dd7 100644 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/PanZoomTarget.java +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/PanZoomTarget.java @@ -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(); diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SimpleScaleGestureDetector.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SimpleScaleGestureDetector.java index 6f920cafb218..faafad04bfb9 100644 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SimpleScaleGestureDetector.java +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/ui/SimpleScaleGestureDetector.java @@ -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; } } |