Index: content/public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java b/content/public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java |
index 820f38e1603d6b0e777da42bd395dd1efdbcd4d4..14e2aff4a213223ea92b37fed13c3611631cd01e 100644 |
--- a/content/public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java |
+++ b/content/public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java |
@@ -5,7 +5,6 @@ |
package org.chromium.content.browser.input; |
import android.annotation.SuppressLint; |
-import android.content.Context; |
import android.graphics.Canvas; |
import android.graphics.drawable.Drawable; |
import android.os.Build; |
@@ -18,10 +17,12 @@ import android.widget.PopupWindow; |
import org.chromium.base.annotations.CalledByNative; |
import org.chromium.base.annotations.JNINamespace; |
+import org.chromium.content.browser.ContainerViewObserver; |
+import org.chromium.content.browser.ContentViewCore; |
import org.chromium.content.browser.PositionObserver; |
+import org.chromium.content.browser.ViewPositionObserver; |
import org.chromium.ui.touch_selection.TouchHandleOrientation; |
-import java.lang.ref.WeakReference; |
import java.lang.reflect.InvocationTargetException; |
import java.lang.reflect.Method; |
@@ -34,18 +35,12 @@ import java.lang.reflect.Method; |
*/ |
@JNINamespace("content") |
public class PopupTouchHandleDrawable extends View { |
- private Drawable mDrawable; |
private final PopupWindow mContainer; |
- private final Context mContext; |
private final PositionObserver.Listener mParentPositionListener; |
- |
- // The weak delegate reference allows the PopupTouchHandleDrawable to be owned by a native |
- // object that might have a different lifetime (or a cyclic lifetime) with respect to the |
- // delegate, allowing garbage collection of any Java references. |
- private final WeakReference<PopupTouchHandleDrawableDelegate> mDelegate; |
- |
- // The observer reference will only be non-null while it is attached to mParentPositionListener. |
+ private final ContainerViewObserver mParentViewObserver; |
+ private ContentViewCore mContentViewCore; |
private PositionObserver mParentPositionObserver; |
+ private Drawable mDrawable; |
// The position of the handle relative to the parent view. |
private int mPositionX; |
@@ -85,39 +80,11 @@ public class PopupTouchHandleDrawable extends View { |
private Runnable mInvalidationRunnable; |
private boolean mHasPendingInvalidate; |
- /** |
- * Provides additional interaction behaviors necessary for handle |
- * manipulation and interaction. |
- */ |
- public interface PopupTouchHandleDrawableDelegate { |
- /** |
- * @return The parent View of the PopupWindow. |
- */ |
- View getParent(); |
- |
- /** |
- * @return A position observer for the parent View, used to keep the |
- * absolutely positioned PopupWindow in-sync with the parent. |
- */ |
- PositionObserver getParentPositionObserver(); |
- |
- /** |
- * Should route MotionEvents to the appropriate logic layer for |
- * performing handle manipulation. |
- */ |
- boolean onTouchHandleEvent(MotionEvent ev); |
- |
- /** |
- * @return Whether the associated content is actively scrolling. |
- */ |
- boolean isScrollInProgress(); |
- } |
- |
- public PopupTouchHandleDrawable(PopupTouchHandleDrawableDelegate delegate) { |
- super(delegate.getParent().getContext()); |
- mContext = delegate.getParent().getContext(); |
- mDelegate = new WeakReference<PopupTouchHandleDrawableDelegate>(delegate); |
- mContainer = new PopupWindow(mContext, null, android.R.attr.textSelectHandleWindowStyle); |
+ public PopupTouchHandleDrawable(ContentViewCore contentViewCore) { |
+ super(contentViewCore.getContainerView().getContext()); |
+ mContentViewCore = contentViewCore; |
+ mContainer = |
+ new PopupWindow(getContext(), null, android.R.attr.textSelectHandleWindowStyle); |
mContainer.setSplitTouchEnabled(true); |
mContainer.setClippingEnabled(false); |
mContainer.setAnimationStyle(0); |
@@ -126,12 +93,26 @@ public class PopupTouchHandleDrawable extends View { |
setWindowLayoutType(mContainer, WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL); |
mAlpha = 1.f; |
mVisible = getVisibility() == VISIBLE; |
+ mParentPositionObserver = new ViewPositionObserver(mContentViewCore.getContainerView()); |
mParentPositionListener = new PositionObserver.Listener() { |
@Override |
public void onPositionChanged(int x, int y) { |
updateParentPosition(x, y); |
} |
}; |
+ mParentViewObserver = new ContainerViewObserver() { |
+ @Override |
+ public void onContainerViewChanged(ViewGroup newContainerView) { |
+ // If the parent View ever changes, the parent position observer |
+ // must be updated accordingly. |
+ mParentPositionObserver.clearListener(); |
+ mParentPositionObserver = new ViewPositionObserver(newContainerView); |
+ if (mContainer.isShowing()) { |
+ mParentPositionObserver.addListener(mParentPositionListener); |
+ } |
+ } |
+ }; |
+ mContentViewCore.addContainerViewObserver(mParentViewObserver); |
} |
private static void setWindowLayoutType(PopupWindow window, int layoutType) { |
@@ -152,22 +133,25 @@ public class PopupTouchHandleDrawable extends View { |
@SuppressLint("ClickableViewAccessibility") |
@Override |
public boolean onTouchEvent(MotionEvent event) { |
- final PopupTouchHandleDrawableDelegate delegate = getDelegateAndHideIfNull(); |
- if (delegate == null) return false; |
- |
+ if (mContentViewCore == null) return false; |
// Convert from PopupWindow local coordinates to |
// parent view local coordinates prior to forwarding. |
- delegate.getParent().getLocationOnScreen(mTempScreenCoords); |
+ mContentViewCore.getContainerView().getLocationOnScreen(mTempScreenCoords); |
final float offsetX = event.getRawX() - event.getX() - mTempScreenCoords[0]; |
final float offsetY = event.getRawY() - event.getY() - mTempScreenCoords[1]; |
final MotionEvent offsetEvent = MotionEvent.obtainNoHistory(event); |
offsetEvent.offsetLocation(offsetX, offsetY); |
- final boolean handled = delegate.onTouchHandleEvent(offsetEvent); |
+ final boolean handled = mContentViewCore.onTouchHandleEvent(offsetEvent); |
offsetEvent.recycle(); |
return handled; |
} |
@CalledByNative |
+ private static PopupTouchHandleDrawable create(ContentViewCore contentViewCore) { |
+ return new PopupTouchHandleDrawable(contentViewCore); |
+ } |
+ |
+ @CalledByNative |
private void setOrientation(int orientation) { |
assert (orientation >= TouchHandleOrientation.LEFT |
&& orientation <= TouchHandleOrientation.UNDEFINED); |
@@ -181,19 +165,19 @@ public class PopupTouchHandleDrawable extends View { |
switch (orientation) { |
case TouchHandleOrientation.LEFT: { |
- mDrawable = HandleViewResources.getLeftHandleDrawable(mContext); |
+ mDrawable = HandleViewResources.getLeftHandleDrawable(getContext()); |
mHotspotX = (mDrawable.getIntrinsicWidth() * 3) / 4f; |
break; |
} |
case TouchHandleOrientation.RIGHT: { |
- mDrawable = HandleViewResources.getRightHandleDrawable(mContext); |
+ mDrawable = HandleViewResources.getRightHandleDrawable(getContext()); |
mHotspotX = mDrawable.getIntrinsicWidth() / 4f; |
break; |
} |
case TouchHandleOrientation.CENTER: { |
- mDrawable = HandleViewResources.getCenterHandleDrawable(mContext); |
+ mDrawable = HandleViewResources.getCenterHandleDrawable(getContext()); |
mHotspotX = mDrawable.getIntrinsicWidth() / 2f; |
break; |
} |
@@ -206,7 +190,7 @@ public class PopupTouchHandleDrawable extends View { |
// Force handle repositioning to accommodate the new orientation's hotspot. |
if (hadValidOrientation) setFocus(oldAdjustedPositionX, oldAdjustedPositionY); |
- mDrawable.setAlpha((int) (255 * mAlpha)); |
+ if (mDrawable != null) mDrawable.setAlpha((int) (255 * mAlpha)); |
scheduleInvalidate(); |
} |
@@ -289,7 +273,7 @@ public class PopupTouchHandleDrawable extends View { |
mDeferredHandleFadeInRunnable = new Runnable() { |
@Override |
public void run() { |
- if (isScrollInProgress()) { |
+ if (mContentViewCore.isScrollInProgress()) { |
rescheduleFadeIn(); |
return; |
} |
@@ -345,36 +329,24 @@ public class PopupTouchHandleDrawable extends View { |
return mPositionY + Math.round(mHotspotY); |
} |
- private PopupTouchHandleDrawableDelegate getDelegateAndHideIfNull() { |
- final PopupTouchHandleDrawableDelegate delegate = mDelegate.get(); |
- // If the delegate is gone, we should immediately dispose of the popup. |
- if (delegate == null) hide(); |
- return delegate; |
- } |
- |
- private boolean isScrollInProgress() { |
- final PopupTouchHandleDrawableDelegate delegate = getDelegateAndHideIfNull(); |
- if (delegate == null) return false; |
- return delegate.isScrollInProgress(); |
+ @CalledByNative |
+ private void destroy() { |
+ hide(); |
+ mContentViewCore.removeContainerViewObserver(mParentViewObserver); |
+ mContentViewCore = null; |
} |
@CalledByNative |
private void show() { |
if (mContainer.isShowing()) return; |
- final PopupTouchHandleDrawableDelegate delegate = getDelegateAndHideIfNull(); |
- if (delegate == null) return; |
- |
- mParentPositionObserver = delegate.getParentPositionObserver(); |
- assert mParentPositionObserver != null; |
- |
// While hidden, the parent position may have become stale. It must be updated before |
// checking isPositionVisible(). |
updateParentPosition(mParentPositionObserver.getPositionX(), |
mParentPositionObserver.getPositionY()); |
mParentPositionObserver.addListener(mParentPositionListener); |
mContainer.setContentView(this); |
- mContainer.showAtLocation(delegate.getParent(), 0, |
+ mContainer.showAtLocation(mContentViewCore.getContainerView(), 0, |
getContainerPositionX(), getContainerPositionY()); |
} |
@@ -384,11 +356,7 @@ public class PopupTouchHandleDrawable extends View { |
mAlpha = 1.0f; |
if (mDeferredHandleFadeInRunnable != null) removeCallbacks(mDeferredHandleFadeInRunnable); |
if (mContainer.isShowing()) mContainer.dismiss(); |
- if (mParentPositionObserver != null) { |
- mParentPositionObserver.removeListener(mParentPositionListener); |
- // Clear the strong reference to allow garbage collection. |
- mParentPositionObserver = null; |
- } |
+ mParentPositionObserver.clearListener(); |
} |
@CalledByNative |
@@ -398,7 +366,7 @@ public class PopupTouchHandleDrawable extends View { |
if (mPositionX == x && mPositionY == y) return; |
mPositionX = x; |
mPositionY = y; |
- if (isScrollInProgress()) { |
+ if (mContentViewCore.isScrollInProgress()) { |
temporarilyHide(); |
} else { |
scheduleInvalidate(); |