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; |
+ } |
} |