| 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..2310726ea8fbb8416459bd91f79b7cb8b6457551 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,27 +24,40 @@ import android.view.ViewGroup.LayoutParams;
|
| import android.widget.PopupWindow;
|
| import android.widget.TextView;
|
|
|
| +import org.chromium.content.browser.PositionObserver;
|
| +
|
| /**
|
| * View that displays a selection or insertion handle for text editing.
|
| + *
|
| + * While a HandleView is logically a child of some other view, it does not exist in that View's
|
| + * hierarchy.
|
| + *
|
| */
|
| public class HandleView extends View {
|
| private static final float FADE_DURATION = 200.f;
|
|
|
| private Drawable mDrawable;
|
| private final PopupWindow mContainer;
|
| +
|
| + // The position of the handle relative to the parent view.
|
| private int mPositionX;
|
| private int mPositionY;
|
| +
|
| + // The position of the parent relative to the application's root view.
|
| + private int mParentPositionX;
|
| + private int mParentPositionY;
|
| +
|
| + // The offset from this handles position to the "tip" of the handle.
|
| + private float mHotspotX;
|
| + private float mHotspotY;
|
| +
|
| private final CursorController mController;
|
| private boolean mIsDragging;
|
| private float mTouchToWindowOffsetX;
|
| private float mTouchToWindowOffsetY;
|
| - 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 +74,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,7 +94,8 @@ 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;
|
| @@ -101,6 +117,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 +176,46 @@ 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 +226,7 @@ public class HandleView extends View {
|
| void hide() {
|
| mIsDragging = false;
|
| mContainer.dismiss();
|
| + mParentPositionObserver.removeListener(mParentPositionListener);
|
| if (mPastePopupWindow != null) {
|
| mPastePopupWindow.hide();
|
| }
|
| @@ -203,10 +253,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 +262,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 +293,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 +305,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();
|
| @@ -347,17 +368,31 @@ public class HandleView extends View {
|
|
|
| // x and y are in physical pixels.
|
| void positionAt(int x, int y) {
|
| - moveTo((int)(x - mHotspotX), (int)(y - mHotspotY));
|
| + moveTo(x - Math.round(mHotspotX), y - Math.round(mHotspotY));
|
| }
|
|
|
| - // Returns the x coordinate of the position that the handle appears to be pointing to.
|
| + // Returns the x coordinate of the position that the handle appears to be pointing to relative
|
| + // to the handles "parent" view.
|
| int getAdjustedPositionX() {
|
| - return (int) (mPositionX + mHotspotX);
|
| + return mPositionX + Math.round(mHotspotX);
|
| }
|
|
|
| - // Returns the y coordinate of the position that the handle appears to be pointing to.
|
| + // Returns the y coordinate of the position that the handle appears to be pointing to relative
|
| + // to the handles "parent" view.
|
| int getAdjustedPositionY() {
|
| - return (int) (mPositionY + mHotspotY);
|
| + return mPositionY + Math.round(mHotspotY);
|
| + }
|
| +
|
| + // Returns the x coordinate of the postion that the handle appears to be pointing to relative to
|
| + // the root view of the application.
|
| + int getRootViewRelativePositionX() {
|
| + return getContainerPositionX() + Math.round(mHotspotX);
|
| + }
|
| +
|
| + // Returns the y coordinate of the postion that the handle appears to be pointing to relative to
|
| + // the root view of the application.
|
| + int getRootViewRelativePositionY() {
|
| + return getContainerPositionY() + Math.round(mHotspotY);
|
| }
|
|
|
| // Returns a suitable y coordinate for the text position corresponding to the handle.
|
|
|