From b0040b03c22c2daa0c3a8cc10aac8a2fa9a73c24 Mon Sep 17 00:00:00 2001 From: Joanne Chung Date: Mon, 17 Jan 2022 22:41:31 +0800 Subject: [PATCH] Handle touch focus when clicking toolbar window transparent area We use a fix size window to hold the toolbar no matter if we show it horizontally or vertically. We should transder the touch focus to the application behid the toolbar when clicking toolbar window transparent area. Bug: 190030331 Bug: 214158202 Test: manual. The toolbar can dismiss when clicking the transparent area in this fix size window. Merged-In: I3915e8165b4d371700cb5fb9e7eb23d46f39bd5c Change-Id: I73bdec96303edab77acc55af3d7871d504614be7 --- .../selectiontoolbar/FloatingToolbarRoot.java | 35 ++++++++++++++----- .../RemoteSelectionToolbar.java | 29 +++++++++++++-- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/core/java/android/service/selectiontoolbar/FloatingToolbarRoot.java b/core/java/android/service/selectiontoolbar/FloatingToolbarRoot.java index 5e4262b970ebf..04491f0cc85df 100644 --- a/core/java/android/service/selectiontoolbar/FloatingToolbarRoot.java +++ b/core/java/android/service/selectiontoolbar/FloatingToolbarRoot.java @@ -18,7 +18,9 @@ package android.service.selectiontoolbar; import android.annotation.SuppressLint; import android.content.Context; +import android.graphics.Rect; import android.os.IBinder; +import android.util.Log; import android.view.MotionEvent; import android.widget.LinearLayout; @@ -31,10 +33,12 @@ import android.widget.LinearLayout; @SuppressLint("ViewConstructor") public class FloatingToolbarRoot extends LinearLayout { + private static final boolean DEBUG = false; + private static final String TAG = "FloatingToolbarRoot"; + private final IBinder mTargetInputToken; private final SelectionToolbarRenderService.TransferTouchListener mTransferTouchListener; - private float mDownX; - private float mDownY; + private Rect mContentRect; public FloatingToolbarRoot(Context context, IBinder targetInputToken, SelectionToolbarRenderService.TransferTouchListener transferTouchListener) { @@ -44,16 +48,29 @@ public class FloatingToolbarRoot extends LinearLayout { setFocusable(false); } + /** + * Sets the Rect that shows the selection toolbar content. + */ + public void setContentRect(Rect contentRect) { + mContentRect = contentRect; + } + @Override @SuppressLint("ClickableViewAccessibility") public boolean dispatchTouchEvent(MotionEvent event) { - switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: { - mDownX = event.getX(); - mDownY = event.getY(); - // TODO: Check x, y if we need to transfer touch focus to application - //mTransferTouchListener.onTransferTouch(getViewRootImpl().getInputToken(), - // mTargetInputToken); + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + int downX = (int) event.getX(); + int downY = (int) event.getY(); + if (DEBUG) { + Log.d(TAG, "downX=" + downX + " downY=" + downY); + } + // TODO(b/215497659): Check FLAG_WINDOW_IS_PARTIALLY_OBSCURED + if (!mContentRect.contains(downX, downY)) { + if (DEBUG) { + Log.d(TAG, "Transfer touch focus to application."); + } + mTransferTouchListener.onTransferTouch(getViewRootImpl().getInputToken(), + mTargetInputToken); } } return super.dispatchTouchEvent(event); diff --git a/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java b/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java index cbe232b7b39aa..179d39de2cfb6 100644 --- a/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java +++ b/core/java/android/service/selectiontoolbar/RemoteSelectionToolbar.java @@ -158,6 +158,8 @@ final class RemoteSelectionToolbar { private final Rect mPreviousContentRect = new Rect(); private final Rect mTempContentRect = new Rect(); + private final Rect mTempContentRectForRoot = new Rect(); + private final int[] mTempCoords = new int[2]; RemoteSelectionToolbar(Context context, long selectionToolbarToken, IBinder hostInputToken, SelectionToolbarRenderService.RemoteCallbackWrapper callbackWrapper, @@ -214,7 +216,13 @@ final class RemoteSelectionToolbar { mOpenOverflowAnimation.setAnimationListener(mOverflowAnimationListener); mCloseOverflowAnimation = new AnimationSet(true); mCloseOverflowAnimation.setAnimationListener(mOverflowAnimationListener); - mShowAnimation = createEnterAnimation(mContentContainer); + mShowAnimation = createEnterAnimation(mContentContainer, + new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + updateFloatingToolbarRootContentRect(); + } + }); mDismissAnimation = createExitAnimation( mContentContainer, 150, // startDelay @@ -241,6 +249,20 @@ final class RemoteSelectionToolbar { }; } + private void updateFloatingToolbarRootContentRect() { + if (mSurfaceControlViewHost == null) { + return; + } + final FloatingToolbarRoot root = (FloatingToolbarRoot) mSurfaceControlViewHost.getView(); + mContentContainer.getLocationOnScreen(mTempCoords); + int contentLeft = mTempCoords[0]; + int contentTop = mTempCoords[1]; + mTempContentRectForRoot.set(contentLeft, contentTop, + contentLeft + mContentContainer.getWidth(), + contentTop + mContentContainer.getHeight()); + root.setContentRect(mTempContentRectForRoot); + } + private WidgetInfo createWidgetInfo() { mTempContentRect.set(mRelativeCoordsForToolbar.x, mRelativeCoordsForToolbar.y, mRelativeCoordsForToolbar.x + mPopupWidth, @@ -514,6 +536,7 @@ final class RemoteSelectionToolbar { isInRTLMode() ? 0 : mContentContainer.getWidth() - startWidth; float actualOverflowButtonX = overflowButtonX + deltaContainerWidth; mOverflowButton.setX(actualOverflowButtonX); + updateFloatingToolbarRootContentRect(); } }; widthAnimation.setInterpolator(mLogAccelerateInterpolator); @@ -589,6 +612,7 @@ final class RemoteSelectionToolbar { isInRTLMode() ? 0 : mContentContainer.getWidth() - startWidth; float actualOverflowButtonX = overflowButtonX + deltaContainerWidth; mOverflowButton.setX(actualOverflowButtonX); + updateFloatingToolbarRootContentRect(); } }; widthAnimation.setInterpolator(mFastOutSlowInInterpolator); @@ -1303,10 +1327,11 @@ final class RemoteSelectionToolbar { * * @param view The view to animate */ - private static AnimatorSet createEnterAnimation(View view) { + private static AnimatorSet createEnterAnimation(View view, Animator.AnimatorListener listener) { AnimatorSet animation = new AnimatorSet(); animation.playTogether( ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1).setDuration(150)); + animation.addListener(listener); return animation; }