Loading core/java/android/widget/PopupWindow.java +1 −1 Original line number Diff line number Diff line Loading @@ -1039,7 +1039,7 @@ public class PopupWindow { * * @return true if the popup is translated upwards to fit on screen */ boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, int xoff, int yoff) { anchor.getLocationInWindow(mDrawingLocation); Loading core/java/android/widget/TextView.java +98 −128 Original line number Diff line number Diff line Loading @@ -4498,8 +4498,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ canvas.restore(); updateCursorControllerPositions(); } private void updateCursorsPositions() { Loading Loading @@ -4557,15 +4555,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @hide */ protected void updateCursorControllerPositions() { // No need to create the controllers if they were not already if (mInsertionPointCursorController != null && mInsertionPointCursorController.isShowing()) { mInsertionPointCursorController.updatePosition(); } if (mSelectionModifierCursorController != null && mSelectionModifierCursorController.isShowing()) { mSelectionModifierCursorController.updatePosition(); } // TODO remove } @Override Loading Loading @@ -7356,14 +7346,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (isTextEditable() || mTextIsSelectable) { if (mScrollX != oldScrollX || mScrollY != oldScrollY) { if (mScrollX != oldScrollX || mScrollY != oldScrollY) { // TODO remove // Hide insertion anchor while scrolling. Leave selection. hideInsertionPointCursorController(); // No need to create the controller, since there is nothing to update. if (mSelectionModifierCursorController != null && mSelectionModifierCursorController.isShowing()) { mSelectionModifierCursorController.updatePosition(); } hideInsertionPointCursorController(); // TODO any motion should hide it } if (touchIsFinished) { Loading @@ -7373,7 +7358,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener handled |= imm != null && imm.showSoftInput(this, 0); } boolean selectAllGotFocus = mSelectAllOnFocus && didTouchFocusSelect(); if (!selectAllGotFocus && hasSelection()) { startSelectionActionMode(); Loading Loading @@ -8653,26 +8637,31 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } private class HandleView extends View implements ViewTreeObserver.OnScrollChangedListener { private class HandleView extends View implements ViewTreeObserver.OnPreDrawListener { private Drawable mDrawable; private final ScrollingPopupWindow mContainer; private int mPositionX; private int mPositionY; private final PopupWindow mContainer; // Position with respect to the parent TextView private int mPositionX, mPositionY; private final CursorController mController; private boolean mIsDragging; private float mTouchToWindowOffsetX; private float mTouchToWindowOffsetY; // Offset from touch position to mPosition private float mTouchToWindowOffsetX, mTouchToWindowOffsetY; private float mHotspotX; // Offsets the hotspot point up, so that cursor is not hidden by the finger when moving up private float mTouchOffsetY; // Where the touch position should be on the handle to ensure a maximum cursor visibility private float mIdealVerticalOffset; private int mLastParentX; private int mLastParentY; // Parent's (TextView) position in window private int mLastParentX, mLastParentY; private float mDownPositionX, mDownPositionY; // PopupWindow container absolute position with respect to the enclosing window private int mContainerPositionX, mContainerPositionY; private long mTouchTimer; // Visible or not (scrolled off screen), whether or not this handle should be visible private boolean mIsActive = false; // The insertion handle can have an associated PastePopupMenu private boolean mIsInsertionHandle = false; // Used to detect taps on the insertion handle, which will affect the PastePopupMenu private long mTouchTimer; private PastePopupMenu mPastePopupWindow; // Touch-up filter: number of previous positions remembered Loading @@ -8684,12 +8673,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private int mPreviousOffsetIndex = 0; private int mNumberPreviousOffsets = 0; public void startTouchUpFilter(int offset) { private void startTouchUpFilter(int offset) { mNumberPreviousOffsets = 0; addPositionToTouchUpFilter(offset); } public void addPositionToTouchUpFilter(int offset) { private void addPositionToTouchUpFilter(int offset) { if (mNumberPreviousOffsets > 0 && mPreviousOffsets[mPreviousOffsetIndex] == offset) { // Make sure only actual changes of position are recorded. Loading @@ -8702,7 +8691,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mNumberPreviousOffsets++; } public void filterOnTouchUp() { private void filterOnTouchUp() { final long now = SystemClock.uptimeMillis(); int i = 0; int index = mPreviousOffsetIndex; Loading @@ -8725,16 +8714,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public HandleView(CursorController controller, int pos) { super(TextView.this.mContext); mController = controller; mContainer = new ScrollingPopupWindow(TextView.this.mContext, null, mContainer = new PopupWindow(TextView.this.mContext, null, com.android.internal.R.attr.textSelectHandleWindowStyle); mContainer.setSplitTouchEnabled(true); mContainer.setClippingEnabled(false); mContainer.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL); mContainer.setContentView(this); setOrientation(pos); setPosition(pos); } public void setOrientation(int pos) { private void setPosition(int pos) { int handleWidth; switch (pos) { case LEFT: { Loading Loading @@ -8774,38 +8764,48 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } final int handleHeight = mDrawable.getIntrinsicHeight(); mTouchOffsetY = -0.3f * handleHeight; mIdealVerticalOffset = 0.7f * handleHeight; invalidate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()); setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()); } public void show() { if (!isPositionVisible()) { hide(); return; } mContainer.setContentView(this); mContainerPositionX = mPositionX; mContainerPositionY = mPositionY - TextView.this.getHeight(); mContainer.showAsDropDown(TextView.this, mContainerPositionX, mContainerPositionY); updateContainerPosition(); if (isShowing()) { mContainer.update(mContainerPositionX, mContainerPositionY, mRight - mLeft, mBottom - mTop); // Hide paste view when handle is moved on screen. hidePastePopupWindow(); } else { mContainer.showAtLocation(TextView.this, 0, mContainerPositionX, mContainerPositionY); mIsActive = true; ViewTreeObserver vto = TextView.this.getViewTreeObserver(); vto.addOnPreDrawListener(this); } } public void hide() { private void dismiss() { mIsDragging = false; mContainer.dismiss(); hidePastePopupWindow(); } public void hide() { dismiss(); mIsActive = false; ViewTreeObserver vto = TextView.this.getViewTreeObserver(); vto.removeOnScrollChangedListener(this); vto.removeOnPreDrawListener(this); } public boolean isShowing() { Loading Loading @@ -8856,44 +8856,59 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private void moveTo(int x, int y) { mPositionX = x - TextView.this.mScrollX; mPositionY = y - TextView.this.mScrollY; if (isPositionVisible()) { int[] coords = null; if (mContainer.isShowing()) { final int containerPositionX = mPositionX; final int containerPositionY = mPositionY - TextView.this.getHeight(); if (mIsDragging) { TextView.this.getLocationInWindow(mTempCoords); if (mTempCoords[0] != mLastParentX || mTempCoords[1] != mLastParentY) { mTouchToWindowOffsetX += mTempCoords[0] - mLastParentX; mTouchToWindowOffsetY += mTempCoords[1] - mLastParentY; mLastParentX = mTempCoords[0]; mLastParentY = mTempCoords[1]; } // Hide paste popup window as soon as the handle is dragged. hidePastePopupWindow(); } } /** * Updates the global container's position. * @return whether or not the position has actually changed */ private boolean updateContainerPosition() { // TODO Prevent this using different HandleView subclasses mController.updateOffset(this, mController.getCurrentOffset(this)); TextView.this.getLocationInWindow(mTempCoords); final int containerPositionX = mTempCoords[0] + mPositionX; final int containerPositionY = mTempCoords[1] + mPositionY; if (containerPositionX != mContainerPositionX || containerPositionY != mContainerPositionY) { mContainerPositionX = containerPositionX; mContainerPositionY = containerPositionY; return true; } return false; } mContainer.update(TextView.this, mContainerPositionX, mContainerPositionY, public boolean onPreDraw() { if (updateContainerPosition()) { if (isPositionVisible()) { mContainer.update(mContainerPositionX, mContainerPositionY, mRight - mLeft, mBottom - mTop); // Hide paste popup window as soon as a scroll occurs. hidePastePopupWindow(); } } else { if (mIsActive && !isShowing()) { show(); } if (mIsDragging) { if (coords == null) { coords = mTempCoords; TextView.this.getLocationInWindow(coords); } else { if (isShowing()) { dismiss(); } 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. // Hide paste popup as soon as the view is scrolled or moved hidePastePopupWindow(); } } else { hide(); } return true; } @Override Loading Loading @@ -8979,7 +8994,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mIsDragging; } void positionAtCursor(final int offset) { void positionAtCursor(int offset) { addPositionToTouchUpFilter(offset); final int width = mDrawable.getIntrinsicWidth(); final int height = mDrawable.getIntrinsicHeight(); Loading Loading @@ -9013,50 +9028,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mPastePopupWindow.hide(); } } /** * A popup window, attached to a view, and that listens to scroll events in its anchors' * view hierarchy, so that it is automatically moved on such events. */ private class ScrollingPopupWindow extends PopupWindow { private int[] mDrawingLocations = new int[2]; public ScrollingPopupWindow(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, int xoff, int yoff) { anchor.getLocationInWindow(mDrawingLocations); p.x = mDrawingLocations[0] + xoff; p.y = mDrawingLocations[1] + anchor.getHeight() + yoff; // Hide paste popup as soon as the view is scrolled. hidePastePopupWindow(); if (!isPositionVisible()) { dismiss(); onHandleBecomeInvisible(); } return false; } } public void onScrollChanged() { if (isPositionVisible()) { show(); ViewTreeObserver vto = TextView.this.getViewTreeObserver(); vto.removeOnScrollChangedListener(this); } } public void onHandleBecomeInvisible() { ViewTreeObserver vto = TextView.this.getViewTreeObserver(); vto.addOnScrollChangedListener(this); } } private class InsertionPointCursorController implements CursorController { Loading @@ -9074,7 +9045,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } public void show(int delayBeforePaste) { updatePosition(); getHandle().show(); hideDelayed(); removePastePopupCallback(); final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime; Loading Loading @@ -9213,7 +9184,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mEndHandle == null) mEndHandle = new HandleView(this, HandleView.RIGHT); mIsShowing = true; updatePosition(); mStartHandle.show(); mEndHandle.show(); Loading Loading
core/java/android/widget/PopupWindow.java +1 −1 Original line number Diff line number Diff line Loading @@ -1039,7 +1039,7 @@ public class PopupWindow { * * @return true if the popup is translated upwards to fit on screen */ boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, int xoff, int yoff) { anchor.getLocationInWindow(mDrawingLocation); Loading
core/java/android/widget/TextView.java +98 −128 Original line number Diff line number Diff line Loading @@ -4498,8 +4498,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ canvas.restore(); updateCursorControllerPositions(); } private void updateCursorsPositions() { Loading Loading @@ -4557,15 +4555,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @hide */ protected void updateCursorControllerPositions() { // No need to create the controllers if they were not already if (mInsertionPointCursorController != null && mInsertionPointCursorController.isShowing()) { mInsertionPointCursorController.updatePosition(); } if (mSelectionModifierCursorController != null && mSelectionModifierCursorController.isShowing()) { mSelectionModifierCursorController.updatePosition(); } // TODO remove } @Override Loading Loading @@ -7356,14 +7346,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (isTextEditable() || mTextIsSelectable) { if (mScrollX != oldScrollX || mScrollY != oldScrollY) { if (mScrollX != oldScrollX || mScrollY != oldScrollY) { // TODO remove // Hide insertion anchor while scrolling. Leave selection. hideInsertionPointCursorController(); // No need to create the controller, since there is nothing to update. if (mSelectionModifierCursorController != null && mSelectionModifierCursorController.isShowing()) { mSelectionModifierCursorController.updatePosition(); } hideInsertionPointCursorController(); // TODO any motion should hide it } if (touchIsFinished) { Loading @@ -7373,7 +7358,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener handled |= imm != null && imm.showSoftInput(this, 0); } boolean selectAllGotFocus = mSelectAllOnFocus && didTouchFocusSelect(); if (!selectAllGotFocus && hasSelection()) { startSelectionActionMode(); Loading Loading @@ -8653,26 +8637,31 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } private class HandleView extends View implements ViewTreeObserver.OnScrollChangedListener { private class HandleView extends View implements ViewTreeObserver.OnPreDrawListener { private Drawable mDrawable; private final ScrollingPopupWindow mContainer; private int mPositionX; private int mPositionY; private final PopupWindow mContainer; // Position with respect to the parent TextView private int mPositionX, mPositionY; private final CursorController mController; private boolean mIsDragging; private float mTouchToWindowOffsetX; private float mTouchToWindowOffsetY; // Offset from touch position to mPosition private float mTouchToWindowOffsetX, mTouchToWindowOffsetY; private float mHotspotX; // Offsets the hotspot point up, so that cursor is not hidden by the finger when moving up private float mTouchOffsetY; // Where the touch position should be on the handle to ensure a maximum cursor visibility private float mIdealVerticalOffset; private int mLastParentX; private int mLastParentY; // Parent's (TextView) position in window private int mLastParentX, mLastParentY; private float mDownPositionX, mDownPositionY; // PopupWindow container absolute position with respect to the enclosing window private int mContainerPositionX, mContainerPositionY; private long mTouchTimer; // Visible or not (scrolled off screen), whether or not this handle should be visible private boolean mIsActive = false; // The insertion handle can have an associated PastePopupMenu private boolean mIsInsertionHandle = false; // Used to detect taps on the insertion handle, which will affect the PastePopupMenu private long mTouchTimer; private PastePopupMenu mPastePopupWindow; // Touch-up filter: number of previous positions remembered Loading @@ -8684,12 +8673,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private int mPreviousOffsetIndex = 0; private int mNumberPreviousOffsets = 0; public void startTouchUpFilter(int offset) { private void startTouchUpFilter(int offset) { mNumberPreviousOffsets = 0; addPositionToTouchUpFilter(offset); } public void addPositionToTouchUpFilter(int offset) { private void addPositionToTouchUpFilter(int offset) { if (mNumberPreviousOffsets > 0 && mPreviousOffsets[mPreviousOffsetIndex] == offset) { // Make sure only actual changes of position are recorded. Loading @@ -8702,7 +8691,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mNumberPreviousOffsets++; } public void filterOnTouchUp() { private void filterOnTouchUp() { final long now = SystemClock.uptimeMillis(); int i = 0; int index = mPreviousOffsetIndex; Loading @@ -8725,16 +8714,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public HandleView(CursorController controller, int pos) { super(TextView.this.mContext); mController = controller; mContainer = new ScrollingPopupWindow(TextView.this.mContext, null, mContainer = new PopupWindow(TextView.this.mContext, null, com.android.internal.R.attr.textSelectHandleWindowStyle); mContainer.setSplitTouchEnabled(true); mContainer.setClippingEnabled(false); mContainer.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL); mContainer.setContentView(this); setOrientation(pos); setPosition(pos); } public void setOrientation(int pos) { private void setPosition(int pos) { int handleWidth; switch (pos) { case LEFT: { Loading Loading @@ -8774,38 +8764,48 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } final int handleHeight = mDrawable.getIntrinsicHeight(); mTouchOffsetY = -0.3f * handleHeight; mIdealVerticalOffset = 0.7f * handleHeight; invalidate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()); setMeasuredDimension(mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()); } public void show() { if (!isPositionVisible()) { hide(); return; } mContainer.setContentView(this); mContainerPositionX = mPositionX; mContainerPositionY = mPositionY - TextView.this.getHeight(); mContainer.showAsDropDown(TextView.this, mContainerPositionX, mContainerPositionY); updateContainerPosition(); if (isShowing()) { mContainer.update(mContainerPositionX, mContainerPositionY, mRight - mLeft, mBottom - mTop); // Hide paste view when handle is moved on screen. hidePastePopupWindow(); } else { mContainer.showAtLocation(TextView.this, 0, mContainerPositionX, mContainerPositionY); mIsActive = true; ViewTreeObserver vto = TextView.this.getViewTreeObserver(); vto.addOnPreDrawListener(this); } } public void hide() { private void dismiss() { mIsDragging = false; mContainer.dismiss(); hidePastePopupWindow(); } public void hide() { dismiss(); mIsActive = false; ViewTreeObserver vto = TextView.this.getViewTreeObserver(); vto.removeOnScrollChangedListener(this); vto.removeOnPreDrawListener(this); } public boolean isShowing() { Loading Loading @@ -8856,44 +8856,59 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private void moveTo(int x, int y) { mPositionX = x - TextView.this.mScrollX; mPositionY = y - TextView.this.mScrollY; if (isPositionVisible()) { int[] coords = null; if (mContainer.isShowing()) { final int containerPositionX = mPositionX; final int containerPositionY = mPositionY - TextView.this.getHeight(); if (mIsDragging) { TextView.this.getLocationInWindow(mTempCoords); if (mTempCoords[0] != mLastParentX || mTempCoords[1] != mLastParentY) { mTouchToWindowOffsetX += mTempCoords[0] - mLastParentX; mTouchToWindowOffsetY += mTempCoords[1] - mLastParentY; mLastParentX = mTempCoords[0]; mLastParentY = mTempCoords[1]; } // Hide paste popup window as soon as the handle is dragged. hidePastePopupWindow(); } } /** * Updates the global container's position. * @return whether or not the position has actually changed */ private boolean updateContainerPosition() { // TODO Prevent this using different HandleView subclasses mController.updateOffset(this, mController.getCurrentOffset(this)); TextView.this.getLocationInWindow(mTempCoords); final int containerPositionX = mTempCoords[0] + mPositionX; final int containerPositionY = mTempCoords[1] + mPositionY; if (containerPositionX != mContainerPositionX || containerPositionY != mContainerPositionY) { mContainerPositionX = containerPositionX; mContainerPositionY = containerPositionY; return true; } return false; } mContainer.update(TextView.this, mContainerPositionX, mContainerPositionY, public boolean onPreDraw() { if (updateContainerPosition()) { if (isPositionVisible()) { mContainer.update(mContainerPositionX, mContainerPositionY, mRight - mLeft, mBottom - mTop); // Hide paste popup window as soon as a scroll occurs. hidePastePopupWindow(); } } else { if (mIsActive && !isShowing()) { show(); } if (mIsDragging) { if (coords == null) { coords = mTempCoords; TextView.this.getLocationInWindow(coords); } else { if (isShowing()) { dismiss(); } 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. // Hide paste popup as soon as the view is scrolled or moved hidePastePopupWindow(); } } else { hide(); } return true; } @Override Loading Loading @@ -8979,7 +8994,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mIsDragging; } void positionAtCursor(final int offset) { void positionAtCursor(int offset) { addPositionToTouchUpFilter(offset); final int width = mDrawable.getIntrinsicWidth(); final int height = mDrawable.getIntrinsicHeight(); Loading Loading @@ -9013,50 +9028,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mPastePopupWindow.hide(); } } /** * A popup window, attached to a view, and that listens to scroll events in its anchors' * view hierarchy, so that it is automatically moved on such events. */ private class ScrollingPopupWindow extends PopupWindow { private int[] mDrawingLocations = new int[2]; public ScrollingPopupWindow(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, int xoff, int yoff) { anchor.getLocationInWindow(mDrawingLocations); p.x = mDrawingLocations[0] + xoff; p.y = mDrawingLocations[1] + anchor.getHeight() + yoff; // Hide paste popup as soon as the view is scrolled. hidePastePopupWindow(); if (!isPositionVisible()) { dismiss(); onHandleBecomeInvisible(); } return false; } } public void onScrollChanged() { if (isPositionVisible()) { show(); ViewTreeObserver vto = TextView.this.getViewTreeObserver(); vto.removeOnScrollChangedListener(this); } } public void onHandleBecomeInvisible() { ViewTreeObserver vto = TextView.this.getViewTreeObserver(); vto.addOnScrollChangedListener(this); } } private class InsertionPointCursorController implements CursorController { Loading @@ -9074,7 +9045,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } public void show(int delayBeforePaste) { updatePosition(); getHandle().show(); hideDelayed(); removePastePopupCallback(); final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime; Loading Loading @@ -9213,7 +9184,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mEndHandle == null) mEndHandle = new HandleView(this, HandleView.RIGHT); mIsShowing = true; updatePosition(); mStartHandle.show(); mEndHandle.show(); Loading