Index: content/public/android/java/src/org/chromium/content/browser/input/HandleView.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java b/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java |
index 88a6deaefea4fe0c835e75c433730ccf3a24636d..c37ff358aadcddba7c6769d49d2fc79d5af9bcb6 100644 |
--- a/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java |
+++ b/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java |
@@ -24,6 +24,8 @@ import android.view.ViewGroup.LayoutParams; |
import android.widget.PopupWindow; |
import android.widget.TextView; |
+import org.chromium.base.PositionObserver; |
+ |
/** |
* View that displays a selection or insertion handle for text editing. |
*/ |
@@ -34,6 +36,8 @@ public class HandleView extends View { |
private final PopupWindow mContainer; |
private int mPositionX; |
private int mPositionY; |
+ private int mParentPositionX; |
+ private int mParentPositionY; |
private final CursorController mController; |
private boolean mIsDragging; |
private float mTouchToWindowOffsetX; |
@@ -41,10 +45,7 @@ public class HandleView extends View { |
private float mHotspotX; |
private float mHotspotY; |
private int mLineOffsetY; |
- private int mLastParentX; |
- private int mLastParentY; |
private float mDownPositionX, mDownPositionY; |
- private int mContainerPositionX, mContainerPositionY; |
private long mTouchTimer; |
private boolean mIsInsertionHandle = false; |
private float mAlpha; |
@@ -61,13 +62,15 @@ public class HandleView extends View { |
private Drawable mSelectHandleRight; |
private Drawable mSelectHandleCenter; |
- private final int[] mTempCoords = new int[2]; |
private final Rect mTempRect = new Rect(); |
static final int LEFT = 0; |
static final int CENTER = 1; |
static final int RIGHT = 2; |
+ private PositionObserver mParentPositionObserver; |
+ private PositionObserver.Listener mParentPositionListener; |
+ |
// Number of dips to subtract from the handle's y position to give a suitable |
// y coordinate for the corresponding text position. This is to compensate for the fact |
// that the handle position is at the base of the line of text. |
@@ -79,11 +82,13 @@ public class HandleView extends View { |
android.R.attr.textSelectHandleRight, |
}; |
- HandleView(CursorController controller, int pos, View parent) { |
+ HandleView(CursorController controller, int pos, View parent, |
+ PositionObserver parentPositionObserver) { |
super(parent.getContext()); |
Context context = parent.getContext(); |
mParent = parent; |
mController = controller; |
+ |
mContainer = new PopupWindow(context, null, android.R.attr.textSelectHandleWindowStyle); |
mContainer.setSplitTouchEnabled(true); |
mContainer.setClippingEnabled(false); |
@@ -101,6 +106,14 @@ public class HandleView extends View { |
LINE_OFFSET_Y_DIP, context.getResources().getDisplayMetrics()); |
mAlpha = 1.f; |
+ |
+ mParentPositionListener = new PositionObserver.Listener() { |
+ @Override |
+ public void onPositionChanged(int x, int y) { |
+ updateParentPosition(x, y); |
+ } |
+ }; |
+ mParentPositionObserver = parentPositionObserver; |
} |
void setOrientation(int pos) { |
@@ -152,21 +165,48 @@ public class HandleView extends View { |
mDrawable.getIntrinsicHeight()); |
} |
- private void updateContainerPosition() { |
- final int[] coords = mTempCoords; |
- mParent.getLocationInWindow(coords); |
- mContainerPositionX = coords[0] + mPositionX; |
- mContainerPositionY = coords[1] + mPositionY; |
+ private void updateParentPosition(int parentPositionX, int parentPositionY) { |
+ // Hide paste popup window as soon as a scroll occurs. |
+ if (mPastePopupWindow != null) { |
+ mPastePopupWindow.hide(); |
+ } |
+ |
+ mTouchToWindowOffsetX += parentPositionX - mParentPositionX; |
+ mTouchToWindowOffsetY += parentPositionY - mParentPositionY; |
+ mParentPositionX = parentPositionX; |
+ mParentPositionY = parentPositionY; |
+ onPositionChanged(); |
+ } |
+ |
+ private int getContainerPositionX() { |
+ return mParentPositionX + mPositionX; |
+ } |
+ |
+ private int getContainerPositionY() { |
+ return mParentPositionY + mPositionY; |
+ } |
+ |
+ private void onPositionChanged() { |
+ mContainer.update(getContainerPositionX(), getContainerPositionY(), |
+ getRight() - getLeft(), getBottom() - getTop()); |
+ } |
+ |
+ private void showContainer() { |
+ mContainer.showAtLocation(mParent, 0, getContainerPositionX(), getContainerPositionY()); |
} |
void show() { |
+ // While hidden, the parent position may have become stale. It must be updated before |
+ // checking isPositionVisible(). |
+ updateParentPosition(mParentPositionObserver.getPositionX(), |
+ mParentPositionObserver.getPositionY()); |
if (!isPositionVisible()) { |
hide(); |
return; |
} |
+ mParentPositionObserver.addListener(mParentPositionListener); |
mContainer.setContentView(this); |
- updateContainerPosition(); |
- mContainer.showAtLocation(mParent, 0, mContainerPositionX, mContainerPositionY); |
+ showContainer(); |
// Hide paste view when handle is moved on screen. |
if (mPastePopupWindow != null) { |
@@ -177,6 +217,7 @@ public class HandleView extends View { |
void hide() { |
mIsDragging = false; |
mContainer.dismiss(); |
+ mParentPositionObserver.removeListener(mParentPositionListener); |
if (mPastePopupWindow != null) { |
mPastePopupWindow.hide(); |
} |
@@ -203,10 +244,8 @@ public class HandleView extends View { |
return false; |
} |
- final int[] coords = mTempCoords; |
- mParent.getLocationInWindow(coords); |
- final int posX = coords[0] + mPositionX + (int) mHotspotX; |
- final int posY = coords[1] + mPositionY + (int) mHotspotY; |
+ final int posX = getContainerPositionX() + (int) mHotspotX; |
+ final int posY = getContainerPositionY() + (int) mHotspotY; |
return posX >= clip.left && posX <= clip.right && |
posY >= clip.top && posY <= clip.bottom; |
@@ -214,44 +253,24 @@ public class HandleView extends View { |
// x and y are in physical pixels. |
void moveTo(int x, int y) { |
+ int previousPositionX = mPositionX; |
+ int previousPositionY = mPositionY; |
+ |
mPositionX = x; |
mPositionY = y; |
if (isPositionVisible()) { |
- int[] coords = null; |
if (mContainer.isShowing()) { |
- coords = mTempCoords; |
- mParent.getLocationInWindow(coords); |
- final int containerPositionX = coords[0] + mPositionX; |
- final int containerPositionY = coords[1] + mPositionY; |
- |
- if (containerPositionX != mContainerPositionX || |
- containerPositionY != mContainerPositionY) { |
- mContainerPositionX = containerPositionX; |
- mContainerPositionY = containerPositionY; |
- |
- mContainer.update(mContainerPositionX, mContainerPositionY, |
- getRight() - getLeft(), getBottom() - getTop()); |
- |
- // Hide paste popup window as soon as a scroll occurs. |
- if (mPastePopupWindow != null) { |
- mPastePopupWindow.hide(); |
- } |
+ onPositionChanged(); |
+ // Hide paste popup window as soon as the handle is dragged. |
+ if (mPastePopupWindow != null && |
+ (previousPositionX != mPositionX || previousPositionY != mPositionY)) { |
+ mPastePopupWindow.hide(); |
} |
} else { |
show(); |
} |
if (mIsDragging) { |
- if (coords == null) { |
- coords = mTempCoords; |
- mParent.getLocationInWindow(coords); |
- } |
- if (coords[0] != mLastParentX || coords[1] != mLastParentY) { |
- mTouchToWindowOffsetX += coords[0] - mLastParentX; |
- mTouchToWindowOffsetY += coords[1] - mLastParentY; |
- mLastParentX = coords[0]; |
- mLastParentY = coords[1]; |
- } |
// Hide paste popup window as soon as the handle is dragged. |
if (mPastePopupWindow != null) { |
mPastePopupWindow.hide(); |
@@ -265,9 +284,6 @@ public class HandleView extends View { |
@Override |
protected void onDraw(Canvas c) { |
updateAlpha(); |
- updateContainerPosition(); |
- mContainer.update(mContainerPositionX, mContainerPositionY, |
- getRight() - getLeft(), getBottom() - getTop()); |
mDrawable.setBounds(0, 0, getRight() - getLeft(), getBottom() - getTop()); |
mDrawable.draw(c); |
} |
@@ -280,10 +296,6 @@ public class HandleView extends View { |
mDownPositionY = ev.getRawY(); |
mTouchToWindowOffsetX = mDownPositionX - mPositionX; |
mTouchToWindowOffsetY = mDownPositionY - mPositionY; |
- final int[] coords = mTempCoords; |
- mParent.getLocationInWindow(coords); |
- mLastParentX = coords[0]; |
- mLastParentY = coords[1]; |
mIsDragging = true; |
mController.beforeStartUpdatingPosition(this); |
mTouchTimer = SystemClock.uptimeMillis(); |