Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/input/HandleView.java

Issue 335943002: [Android] Composited selection handle rendering (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@input_native_handles_final
Patch Set: Fix animation tests Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
deleted file mode 100644
index a633aeae6563600018756ecb75905fe577cf6572..0000000000000000000000000000000000000000
--- a/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.browser.input;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.SystemClock;
-import android.util.TypedValue;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewParent;
-import android.view.animation.AnimationUtils;
-import android.widget.PopupWindow;
-
-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 final int mLineOffsetY;
- private float mDownPositionX, mDownPositionY;
- private long mTouchTimer;
- private boolean mIsInsertionHandle = false;
- private float mAlpha;
- private long mFadeStartTime;
-
- private final View mParent;
- private InsertionHandleController.PastePopupMenu mPastePopupWindow;
-
- private final Rect mTempRect = new Rect();
-
- static final int LEFT = 0;
- static final int CENTER = 1;
- static final int RIGHT = 2;
-
- private final PositionObserver mParentPositionObserver;
- private final 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.
- private static final float LINE_OFFSET_Y_DIP = 5.0f;
-
- private static final int[] TEXT_VIEW_HANDLE_ATTRS = {
- android.R.attr.textSelectHandleLeft,
- android.R.attr.textSelectHandle,
- android.R.attr.textSelectHandleRight,
- };
-
- HandleView(CursorController controller, int pos, View parent,
- PositionObserver parentPositionObserver) {
- super(parent.getContext());
- mParent = parent;
- Context context = mParent.getContext();
- mController = controller;
- mContainer = new PopupWindow(context, null, android.R.attr.textSelectHandleWindowStyle);
- mContainer.setSplitTouchEnabled(true);
- mContainer.setClippingEnabled(false);
- mContainer.setAnimationStyle(0);
-
- setOrientation(pos);
-
- // Convert line offset dips to pixels.
- mLineOffsetY = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- 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) {
- Context context = mParent.getContext();
- TypedArray a = context.getTheme().obtainStyledAttributes(TEXT_VIEW_HANDLE_ATTRS);
- mDrawable = a.getDrawable(pos);
- a.recycle();
-
- mIsInsertionHandle = (pos == CENTER);
-
- int handleWidth = mDrawable.getIntrinsicWidth();
- switch (pos) {
- case LEFT: {
- mHotspotX = (handleWidth * 3) / 4f;
- break;
- }
-
- case RIGHT: {
- mHotspotX = handleWidth / 4f;
- break;
- }
-
- case CENTER:
- default: {
- mHotspotX = handleWidth / 2f;
- break;
- }
- }
- mHotspotY = 0;
-
- invalidate();
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- setMeasuredDimension(mDrawable.getIntrinsicWidth(),
- mDrawable.getIntrinsicHeight());
- }
-
- 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() {
- // Deferring View invalidation while the handles are hidden prevents
- // scheduling conflicts with the compositor.
- if (getVisibility() != VISIBLE) return;
- 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);
- showContainer();
-
- // Hide paste view when handle is moved on screen.
- if (mPastePopupWindow != null) {
- mPastePopupWindow.hide();
- }
- }
-
- void hide() {
- mIsDragging = false;
- mContainer.dismiss();
- mParentPositionObserver.removeListener(mParentPositionListener);
- if (mPastePopupWindow != null) {
- mPastePopupWindow.hide();
- }
- }
-
- boolean isShowing() {
- return mContainer.isShowing();
- }
-
- private boolean isPositionVisible() {
- // Always show a dragging handle.
- if (mIsDragging) {
- return true;
- }
-
- final Rect clip = mTempRect;
- clip.left = 0;
- clip.top = 0;
- clip.right = mParent.getWidth();
- clip.bottom = mParent.getHeight();
-
- final ViewParent parent = mParent.getParent();
- if (parent == null || !parent.getChildVisibleRect(mParent, clip, null)) {
- return false;
- }
-
- 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;
- }
-
- // 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()) {
- if (mContainer.isShowing()) {
- 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) {
- // Hide paste popup window as soon as the handle is dragged.
- if (mPastePopupWindow != null) {
- mPastePopupWindow.hide();
- }
- }
- } else {
- hide();
- }
- }
-
- @Override
- protected void onDraw(Canvas c) {
- updateAlpha();
- mDrawable.setBounds(0, 0, getRight() - getLeft(), getBottom() - getTop());
- mDrawable.draw(c);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- switch (ev.getActionMasked()) {
- case MotionEvent.ACTION_DOWN: {
- mDownPositionX = ev.getRawX();
- mDownPositionY = ev.getRawY();
- mTouchToWindowOffsetX = mDownPositionX - mPositionX;
- mTouchToWindowOffsetY = mDownPositionY - mPositionY;
- mIsDragging = true;
- mController.beforeStartUpdatingPosition(this);
- mTouchTimer = SystemClock.uptimeMillis();
- break;
- }
-
- case MotionEvent.ACTION_MOVE: {
- updatePosition(ev.getRawX(), ev.getRawY());
- break;
- }
-
- case MotionEvent.ACTION_UP:
- if (mIsInsertionHandle) {
- long delay = SystemClock.uptimeMillis() - mTouchTimer;
- if (delay < ViewConfiguration.getTapTimeout()) {
- if (mPastePopupWindow != null && mPastePopupWindow.isShowing()) {
- // Tapping on the handle dismisses the displayed paste view,
- mPastePopupWindow.hide();
- } else {
- showPastePopupWindow();
- }
- }
- }
- mIsDragging = false;
- break;
-
- case MotionEvent.ACTION_CANCEL:
- mIsDragging = false;
- break;
-
- default:
- return false;
- }
- return true;
- }
-
- boolean isDragging() {
- return mIsDragging;
- }
-
- /**
- * @return Returns the x position of the handle
- */
- int getPositionX() {
- return mPositionX;
- }
-
- /**
- * @return Returns the y position of the handle
- */
- int getPositionY() {
- return mPositionY;
- }
-
- private void updatePosition(float rawX, float rawY) {
- final float newPosX = rawX - mTouchToWindowOffsetX + mHotspotX;
- final float newPosY = rawY - mTouchToWindowOffsetY + mHotspotY - mLineOffsetY;
-
- mController.updatePosition(this, Math.round(newPosX), Math.round(newPosY));
- }
-
- // x and y are in physical pixels.
- void positionAt(int x, int y) {
- moveTo(x - Math.round(mHotspotX), y - Math.round(mHotspotY));
- }
-
- // Returns the x coordinate of the position that the handle appears to be pointing to relative
- // to the handles "parent" view.
- int getAdjustedPositionX() {
- return mPositionX + Math.round(mHotspotX);
- }
-
- // Returns the y coordinate of the position that the handle appears to be pointing to relative
- // to the handles "parent" view.
- int getAdjustedPositionY() {
- 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.
- // As the handle points to a position on the base of the line of text, this method
- // returns a coordinate a small number of pixels higher (i.e. a slightly smaller number)
- // than getAdjustedPositionY.
- int getLineAdjustedPositionY() {
- return (int) (mPositionY + mHotspotY - mLineOffsetY);
- }
-
- Drawable getDrawable() {
- return mDrawable;
- }
-
- private void updateAlpha() {
- if (mAlpha == 1.f) return;
- mAlpha = Math.min(1.f,
- (AnimationUtils.currentAnimationTimeMillis() - mFadeStartTime) / FADE_DURATION);
- mDrawable.setAlpha((int) (255 * mAlpha));
- invalidate();
- }
-
- /**
- * If the handle is not visible, sets its visibility to View.VISIBLE and begins fading it in.
- */
- void beginFadeIn() {
- if (getVisibility() == VISIBLE) return;
- mAlpha = 0.f;
- mFadeStartTime = AnimationUtils.currentAnimationTimeMillis();
- setVisibility(VISIBLE);
- // Position updates may have been deferred while the handle was hidden.
- onPositionChanged();
- }
-
- void showPastePopupWindow() {
- InsertionHandleController ihc = (InsertionHandleController) mController;
- if (mIsInsertionHandle && ihc.canPaste()) {
- if (mPastePopupWindow == null) {
- // Lazy initialization: create when actually shown only.
- mPastePopupWindow = ihc.new PastePopupMenu();
- }
- mPastePopupWindow.show();
- }
- }
-}

Powered by Google App Engine
This is Rietveld 408576698