diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 4099c8aa67104..e36243cc7948e 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -4116,6 +4116,8 @@ public class Editor { private final boolean mHasSelection; private final int mHandleHeight; private final Map mAssistClickHandlers = new HashMap<>(); + @Nullable + private TextClassification mPrevTextClassification; TextActionModeCallback(@TextActionMode int mode) { mHasSelection = mode == TextActionMode.SELECTION @@ -4266,15 +4268,19 @@ public class Editor { } private void updateAssistMenuItems(Menu menu) { - clearAssistMenuItems(menu); - if (!shouldEnableAssistMenuItems()) { - return; - } final TextClassification textClassification = getSelectionActionModeHelper().getTextClassification(); + if (mPrevTextClassification == textClassification) { + // Already handled. + return; + } + clearAssistMenuItems(menu); if (textClassification == null) { return; } + if (!shouldEnableAssistMenuItems()) { + return; + } if (!textClassification.getActions().isEmpty()) { // Primary assist action (Always shown). final MenuItem item = addAssistMenuItem(menu, @@ -4301,6 +4307,7 @@ public class Editor { MENU_ITEM_ORDER_SECONDARY_ASSIST_ACTIONS_START + i - 1, MenuItem.SHOW_AS_ACTION_NEVER); } + mPrevTextClassification = textClassification; } private MenuItem addAssistMenuItem(Menu menu, RemoteAction action, int itemId, int order, diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index 32c68bdd04910..e74ce53306c18 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -296,12 +296,12 @@ public final class SelectionActionModeHelper { } else { mTextClassification = null; } + final SelectionModifierCursorController controller = mEditor.getSelectionController(); + if (controller != null + && (mTextView.isTextSelectable() || mTextView.isTextEditable())) { + controller.show(); + } if (mEditor.startActionModeInternal(actionMode)) { - final SelectionModifierCursorController controller = mEditor.getSelectionController(); - if (controller != null - && (mTextView.isTextSelectable() || mTextView.isTextEditable())) { - controller.show(); - } if (result != null) { switch (actionMode) { case Editor.TextActionMode.SELECTION: diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java index 633d6848030e6..36913b729f1ba 100644 --- a/core/java/com/android/internal/view/FloatingActionMode.java +++ b/core/java/com/android/internal/view/FloatingActionMode.java @@ -29,8 +29,8 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; - import android.widget.PopupWindow; + import com.android.internal.R; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.widget.FloatingToolbar; @@ -148,16 +148,21 @@ public final class FloatingActionMode extends ActionMode { @Override public void invalidateContentRect() { mCallback.onGetContentRect(this, mOriginatingView, mContentRect); - repositionToolbar(); + updateViewLocationInWindow(/* forceRepositionToolbar= */ true); } public void updateViewLocationInWindow() { + updateViewLocationInWindow(/* forceRepositionToolbar= */ false); + } + + private void updateViewLocationInWindow(boolean forceRepositionToolbar) { mOriginatingView.getLocationOnScreen(mViewPositionOnScreen); mOriginatingView.getRootView().getLocationOnScreen(mRootViewPositionOnScreen); mOriginatingView.getGlobalVisibleRect(mViewRectOnScreen); mViewRectOnScreen.offset(mRootViewPositionOnScreen[0], mRootViewPositionOnScreen[1]); - if (!Arrays.equals(mViewPositionOnScreen, mPreviousViewPositionOnScreen) + if (forceRepositionToolbar + || !Arrays.equals(mViewPositionOnScreen, mPreviousViewPositionOnScreen) || !mViewRectOnScreen.equals(mPreviousViewRectOnScreen)) { repositionToolbar(); mPreviousViewPositionOnScreen[0] = mViewPositionOnScreen[0]; @@ -192,10 +197,15 @@ public final class FloatingActionMode extends ActionMode { mViewRectOnScreen.bottom + mBottomAllowance)); if (!mContentRectOnScreen.equals(mPreviousContentRectOnScreen)) { - // Content rect is moving. - mOriginatingView.removeCallbacks(mMovingOff); - mFloatingToolbarVisibilityHelper.setMoving(true); - mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY); + // Content rect is moving + if (!mPreviousContentRectOnScreen.isEmpty()) { + mOriginatingView.removeCallbacks(mMovingOff); + mFloatingToolbarVisibilityHelper.setMoving(true); + mOriginatingView.postDelayed(mMovingOff, MOVING_HIDE_DELAY); + } else { + // mPreviousContentRectOnScreen is empty. That means we are are showing the + // toolbar rather than moving it. And we should show it right away. + } mFloatingToolbar.setContentRect(mContentRectOnScreen); mFloatingToolbar.updateLayout(); diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index d7611dcd0aa07..58817a8a48a90 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -261,18 +261,14 @@ public final class FloatingToolbar { /** * If this is set to true, the action mode view will dismiss itself on touch events outside of - * its window. If the toolbar is already showing, it will be re-shown so that this setting takes - * effect immediately. + * its window. The setting takes effect immediately. * * @param outsideTouchable whether or not this action mode is "outside touchable" * @param onDismiss optional. Sets a callback for when this action mode popup dismisses itself */ public void setOutsideTouchable( boolean outsideTouchable, @Nullable PopupWindow.OnDismissListener onDismiss) { - if (mPopup.setOutsideTouchable(outsideTouchable, onDismiss) && isShowing()) { - dismiss(); - doShow(); - } + mPopup.setOutsideTouchable(outsideTouchable, onDismiss); } private void doShow() { @@ -530,7 +526,6 @@ public final class FloatingToolbar { /** * Makes this toolbar "outside touchable" and sets the onDismissListener. - * This will take effect the next time the toolbar is re-shown. * * @param outsideTouchable if true, the popup will be made "outside touchable" and * "non focusable". The reverse will happen if false. @@ -548,6 +543,7 @@ public final class FloatingToolbar { if (mPopupWindow.isOutsideTouchable() ^ outsideTouchable) { mPopupWindow.setOutsideTouchable(outsideTouchable); mPopupWindow.setFocusable(!outsideTouchable); + mPopupWindow.update(); ret = true; } mPopupWindow.setOnDismissListener(onDismiss);