Chromium Code Reviews| Index: content/public/android/java/src/org/chromium/content/browser/WebActionMode.java |
| diff --git a/content/public/android/java/src/org/chromium/content/browser/WebActionMode.java b/content/public/android/java/src/org/chromium/content/browser/WebActionMode.java |
| index befbb81b1f5279794a6f65c0b750c90474912206..6c0008954994aea0ef1a6e4c5bb443bef58b7883 100644 |
| --- a/content/public/android/java/src/org/chromium/content/browser/WebActionMode.java |
| +++ b/content/public/android/java/src/org/chromium/content/browser/WebActionMode.java |
| @@ -4,7 +4,10 @@ |
| package org.chromium.content.browser; |
| +import android.annotation.TargetApi; |
| +import android.os.Build; |
| import android.view.ActionMode; |
| +import android.view.View; |
| import org.chromium.base.Log; |
| @@ -12,18 +15,36 @@ import org.chromium.base.Log; |
| * An ActionMode for in-page web content selection. This class wraps an ActionMode created |
| * by the associated View, providing modified interaction with that ActionMode. |
| */ |
| +@TargetApi(Build.VERSION_CODES.M) |
| public class WebActionMode { |
| - private static final String TAG = "cr.SelectActionMode"; |
| + private static final String TAG = "cr.WebActionMode"; |
| protected final ActionMode mActionMode; |
| + private final View mView; |
| + private boolean mHidden; |
| + private boolean mPendingInvalidateContentRect; |
| + |
| + // Self-repeating task that repeatedly hides the ActionMode. This is |
| + // required because ActionMode only exposes a temporary hide routine. |
| + private final Runnable mRepeatingHideRunnable; |
| /** |
| * Constructs a SelectActionMode instance wrapping a concrete ActionMode. |
| * @param actionMode the wrapped ActionMode. |
| */ |
| - public WebActionMode(ActionMode actionMode) { |
| + public WebActionMode(ActionMode actionMode, View view) { |
| assert actionMode != null; |
| + assert view != null; |
| mActionMode = actionMode; |
| + mView = view; |
| + mRepeatingHideRunnable = new Runnable() { |
| + @Override |
| + public void run() { |
| + assert mHidden; |
| + mView.postDelayed(mRepeatingHideRunnable, ActionMode.DEFAULT_HIDE_DURATION - 1); |
| + hideTemporarily(ActionMode.DEFAULT_HIDE_DURATION); |
| + } |
| + }; |
| } |
| /** |
| @@ -35,8 +56,17 @@ public class WebActionMode { |
| /** |
| * @see ActionMode#invalidate() |
| + * Note that invalidation will also reset visibility state. The caller |
| + * should account for this when making subsequent visibility updates. |
| */ |
| public void invalidate() { |
| + if (mHidden) { |
| + assert canHide(); |
| + mHidden = false; |
| + mView.removeCallbacks(mRepeatingHideRunnable); |
| + mPendingInvalidateContentRect = false; |
| + } |
| + |
| // Try/catch necessary for framework bug, crbug.com/446717. |
| try { |
| mActionMode.invalidate(); |
| @@ -48,5 +78,65 @@ public class WebActionMode { |
| /** |
| * @see ActionMode#invalidateContentRect() |
| */ |
| - public void invalidateContentRect() {} |
| + public void invalidateContentRect() { |
| + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
| + if (mHidden) { |
| + mPendingInvalidateContentRect = true; |
| + } else { |
| + mPendingInvalidateContentRect = false; |
| + mActionMode.invalidateContentRect(); |
| + } |
| + } |
| + } |
| + |
| + /** |
| + * @see ActionMode#onWindowFocusChanged() |
| + */ |
| + public void onWindowFocusChanged(boolean hasWindowFocus) { |
| + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
| + mActionMode.onWindowFocusChanged(hasWindowFocus); |
| + } |
| + } |
| + |
| + /** |
| + * Hide or reveal the ActionMode. Note that this only has visible |
| + * side-effects if the underlying ActionMode supports hiding. |
| + * @param hide whether to hide or show the ActionMode. |
| + */ |
| + public void hide(boolean hide) { |
| + if (!canHide()) return; |
| + if (mHidden == hide) return; |
| + mHidden = hide; |
| + if (mHidden) { |
| + mRepeatingHideRunnable.run(); |
| + } else { |
| + mHidden = false; |
| + mView.removeCallbacks(mRepeatingHideRunnable); |
| + // Delay the reveal slightly as there could be trailing content |
| + // rect invalidations soon after showing (which would temporarily |
| + // hide the ActionMode yet again). |
| + hideTemporarily(300); |
|
aurimas (slooooooooow)
2015/08/20 22:20:16
How did we pick this number? Can we pull this cons
jdduke (slow)
2015/08/20 23:13:14
It's somewhat arbitrary, 300 ms should ensure we g
|
| + if (mPendingInvalidateContentRect) { |
| + mPendingInvalidateContentRect = false; |
| + invalidateContentRect(); |
| + } |
| + } |
| + } |
| + |
| + /** |
| + * @see ActionMode#hide(long) |
| + */ |
| + private void hideTemporarily(long duration) { |
| + assert canHide(); |
| + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
| + mActionMode.hide(duration); |
| + } |
| + } |
| + |
| + private boolean canHide() { |
| + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { |
| + return mActionMode.getType() == ActionMode.TYPE_FLOATING; |
| + } |
| + return false; |
| + } |
| } |