Merge "Add PiP Resize drag handle." into rvc-dev am: f51818a054

Change-Id: I58987ca97d5aa5482db17c7ed588d46b90a4ab4c
This commit is contained in:
Ben Lin
2020-05-21 22:28:59 +00:00
committed by Automerger Merge Worker
6 changed files with 96 additions and 22 deletions

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="12.0dp"
android:height="12.0dp"
android:viewportWidth="12"
android:viewportHeight="12">
<group
android:translateX="12"
android:rotation="90">
<path
android:fillColor="#FFFFFF"
android:pathData="M3.41421 0L2 1.41422L10.4853 9.8995L11.8995 8.48528L3.41421 0ZM2.41421 4.24268L1 5.65689L6.65685 11.3137L8.07107 9.89953L2.41421 4.24268Z" />
</group>
</vector>

View File

@@ -81,4 +81,13 @@
android:src="@drawable/ic_close_white" android:src="@drawable/ic_close_white"
android:background="?android:selectableItemBackgroundBorderless" /> android:background="?android:selectableItemBackgroundBorderless" />
<!--TODO (b/156917828): Add content description for a11y purposes?-->
<ImageButton
android:id="@+id/resize_handle"
android:layout_width="@dimen/pip_action_size"
android:layout_height="@dimen/pip_action_size"
android:layout_gravity="top|start"
android:padding="@dimen/pip_action_padding"
android:src="@drawable/pip_resize_handle"
android:background="?android:selectableItemBackgroundBorderless" />
</FrameLayout> </FrameLayout>

View File

@@ -194,6 +194,14 @@ public class PipBoundsHandler {
mLastPipComponentName = null; mLastPipComponentName = null;
} }
/**
* Returns ture if there's a valid snap fraction. This is used with {@link EXTRA_IS_FIRST_ENTRY}
* to see if this is the first time user has entered PIP for the component.
*/
public boolean hasSaveReentryBounds() {
return mReentrySnapFraction != INVALID_SNAP_FRACTION;
}
public Rect getDisplayBounds() { public Rect getDisplayBounds() {
return new Rect(0, 0, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); return new Rect(0, 0, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
} }

View File

@@ -29,6 +29,7 @@ import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_CON
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_DISMISS_FRACTION; import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_DISMISS_FRACTION;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MENU_STATE; import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MENU_STATE;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_MENU_WITH_DELAY; import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_MENU_WITH_DELAY;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_SHOW_RESIZE_HANDLE;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS; import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU; import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU;
import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE; import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
@@ -119,6 +120,7 @@ public class PipMenuActivity extends Activity {
private LinearLayout mActionsGroup; private LinearLayout mActionsGroup;
private View mSettingsButton; private View mSettingsButton;
private View mDismissButton; private View mDismissButton;
private View mResizeHandle;
private int mBetweenActionPaddingLand; private int mBetweenActionPaddingLand;
private AnimatorSet mMenuContainerAnimator; private AnimatorSet mMenuContainerAnimator;
@@ -142,7 +144,8 @@ public class PipMenuActivity extends Activity {
data.getParcelable(EXTRA_STACK_BOUNDS), data.getParcelable(EXTRA_STACK_BOUNDS),
data.getBoolean(EXTRA_ALLOW_TIMEOUT), data.getBoolean(EXTRA_ALLOW_TIMEOUT),
data.getBoolean(EXTRA_WILL_RESIZE_MENU), data.getBoolean(EXTRA_WILL_RESIZE_MENU),
data.getBoolean(EXTRA_SHOW_MENU_WITH_DELAY)); data.getBoolean(EXTRA_SHOW_MENU_WITH_DELAY),
data.getBoolean(EXTRA_SHOW_RESIZE_HANDLE));
break; break;
} }
case MESSAGE_POKE_MENU: case MESSAGE_POKE_MENU:
@@ -212,6 +215,8 @@ public class PipMenuActivity extends Activity {
expandPip(); expandPip();
} }
}); });
mResizeHandle = findViewById(R.id.resize_handle);
mResizeHandle.setAlpha(0);
mActionsGroup = findViewById(R.id.actions_group); mActionsGroup = findViewById(R.id.actions_group);
mBetweenActionPaddingLand = getResources().getDimensionPixelSize( mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
R.dimen.pip_between_action_padding_land); R.dimen.pip_between_action_padding_land);
@@ -342,7 +347,7 @@ public class PipMenuActivity extends Activity {
} }
private void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout, private void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout,
boolean resizeMenuOnShow, boolean withDelay) { boolean resizeMenuOnShow, boolean withDelay, boolean showResizeHandle) {
mAllowMenuTimeout = allowMenuTimeout; mAllowMenuTimeout = allowMenuTimeout;
if (mMenuState != menuState) { if (mMenuState != menuState) {
// Disallow touches if the menu needs to resize while showing, and we are transitioning // Disallow touches if the menu needs to resize while showing, and we are transitioning
@@ -363,10 +368,14 @@ public class PipMenuActivity extends Activity {
mSettingsButton.getAlpha(), 1f); mSettingsButton.getAlpha(), 1f);
ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA, ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
mDismissButton.getAlpha(), 1f); mDismissButton.getAlpha(), 1f);
ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA,
mResizeHandle.getAlpha(), menuState == MENU_STATE_CLOSE && showResizeHandle
? 1f : 0f);
if (menuState == MENU_STATE_FULL) { if (menuState == MENU_STATE_FULL) {
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim); mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
resizeAnim);
} else { } else {
mMenuContainerAnimator.playTogether(dismissAnim); mMenuContainerAnimator.playTogether(dismissAnim, resizeAnim);
} }
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN); mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_IN);
mMenuContainerAnimator.setDuration(MENU_FADE_DURATION); mMenuContainerAnimator.setDuration(MENU_FADE_DURATION);
@@ -418,7 +427,9 @@ public class PipMenuActivity extends Activity {
mSettingsButton.getAlpha(), 0f); mSettingsButton.getAlpha(), 0f);
ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA, ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
mDismissButton.getAlpha(), 0f); mDismissButton.getAlpha(), 0f);
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim); ObjectAnimator resizeAnim = ObjectAnimator.ofFloat(mResizeHandle, View.ALPHA,
mResizeHandle.getAlpha(), 0f);
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, resizeAnim);
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT); mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
mMenuContainerAnimator.setDuration(animate ? MENU_FADE_DURATION : 0); mMenuContainerAnimator.setDuration(animate ? MENU_FADE_DURATION : 0);
mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() { mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
@@ -463,7 +474,9 @@ public class PipMenuActivity extends Activity {
boolean allowMenuTimeout = intent.getBooleanExtra(EXTRA_ALLOW_TIMEOUT, true); boolean allowMenuTimeout = intent.getBooleanExtra(EXTRA_ALLOW_TIMEOUT, true);
boolean willResizeMenu = intent.getBooleanExtra(EXTRA_WILL_RESIZE_MENU, false); boolean willResizeMenu = intent.getBooleanExtra(EXTRA_WILL_RESIZE_MENU, false);
boolean withDelay = intent.getBooleanExtra(EXTRA_SHOW_MENU_WITH_DELAY, false); boolean withDelay = intent.getBooleanExtra(EXTRA_SHOW_MENU_WITH_DELAY, false);
showMenu(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay); boolean showResizeHandle = intent.getBooleanExtra(EXTRA_SHOW_RESIZE_HANDLE, false);
showMenu(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
showResizeHandle);
} }
} }

View File

@@ -65,6 +65,7 @@ public class PipMenuActivityController {
public static final String EXTRA_DISMISS_FRACTION = "dismiss_fraction"; public static final String EXTRA_DISMISS_FRACTION = "dismiss_fraction";
public static final String EXTRA_MENU_STATE = "menu_state"; public static final String EXTRA_MENU_STATE = "menu_state";
public static final String EXTRA_SHOW_MENU_WITH_DELAY = "show_menu_with_delay"; public static final String EXTRA_SHOW_MENU_WITH_DELAY = "show_menu_with_delay";
public static final String EXTRA_SHOW_RESIZE_HANDLE = "show_resize_handle";
public static final int MESSAGE_MENU_STATE_CHANGED = 100; public static final int MESSAGE_MENU_STATE_CHANGED = 100;
public static final int MESSAGE_EXPAND_PIP = 101; public static final int MESSAGE_EXPAND_PIP = 101;
@@ -248,7 +249,7 @@ public class PipMenuActivityController {
// start, then start it // start, then start it
startMenuActivity(MENU_STATE_NONE, null /* stackBounds */, startMenuActivity(MENU_STATE_NONE, null /* stackBounds */,
false /* allowMenuTimeout */, false /* resizeMenuOnShow */, false /* allowMenuTimeout */, false /* resizeMenuOnShow */,
false /* withDelay */); false /* withDelay */, false /* showResizeHandle */);
} }
} }
@@ -257,28 +258,29 @@ public class PipMenuActivityController {
* PiP window transition is finished. * PiP window transition is finished.
*/ */
public void showMenuWithDelay(int menuState, Rect stackBounds, boolean allowMenuTimeout, public void showMenuWithDelay(int menuState, Rect stackBounds, boolean allowMenuTimeout,
boolean willResizeMenu) { boolean willResizeMenu, boolean showResizeHandle) {
showMenuInternal(menuState, stackBounds, allowMenuTimeout, willResizeMenu, showMenuInternal(menuState, stackBounds, allowMenuTimeout, willResizeMenu,
true /* withDelay */); true /* withDelay */, showResizeHandle);
} }
/** /**
* Shows the menu activity immediately. * Shows the menu activity immediately.
*/ */
public void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout, public void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout,
boolean willResizeMenu) { boolean willResizeMenu, boolean showResizeHandle) {
showMenuInternal(menuState, stackBounds, allowMenuTimeout, willResizeMenu, showMenuInternal(menuState, stackBounds, allowMenuTimeout, willResizeMenu,
false /* withDelay */); false /* withDelay */, showResizeHandle);
} }
private void showMenuInternal(int menuState, Rect stackBounds, boolean allowMenuTimeout, private void showMenuInternal(int menuState, Rect stackBounds, boolean allowMenuTimeout,
boolean willResizeMenu, boolean withDelay) { boolean willResizeMenu, boolean withDelay, boolean showResizeHandle) {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "showMenu() state=" + menuState Log.d(TAG, "showMenu() state=" + menuState
+ " hasActivity=" + (mToActivityMessenger != null) + " hasActivity=" + (mToActivityMessenger != null)
+ " allowMenuTimeout=" + allowMenuTimeout + " allowMenuTimeout=" + allowMenuTimeout
+ " willResizeMenu=" + willResizeMenu + " willResizeMenu=" + willResizeMenu
+ " withDelay=" + withDelay + " withDelay=" + withDelay
+ " showResizeHandle=" + showResizeHandle
+ " callers=\n" + Debug.getCallers(5, " ")); + " callers=\n" + Debug.getCallers(5, " "));
} }
@@ -291,6 +293,7 @@ public class PipMenuActivityController {
data.putBoolean(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout); data.putBoolean(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
data.putBoolean(EXTRA_WILL_RESIZE_MENU, willResizeMenu); data.putBoolean(EXTRA_WILL_RESIZE_MENU, willResizeMenu);
data.putBoolean(EXTRA_SHOW_MENU_WITH_DELAY, withDelay); data.putBoolean(EXTRA_SHOW_MENU_WITH_DELAY, withDelay);
data.putBoolean(EXTRA_SHOW_RESIZE_HANDLE, showResizeHandle);
Message m = Message.obtain(); Message m = Message.obtain();
m.what = PipMenuActivity.MESSAGE_SHOW_MENU; m.what = PipMenuActivity.MESSAGE_SHOW_MENU;
m.obj = data; m.obj = data;
@@ -302,7 +305,8 @@ public class PipMenuActivityController {
} else if (!mStartActivityRequested || isStartActivityRequestedElapsed()) { } else if (!mStartActivityRequested || isStartActivityRequestedElapsed()) {
// If we haven't requested the start activity, or if it previously took too long to // If we haven't requested the start activity, or if it previously took too long to
// start, then start it // start, then start it
startMenuActivity(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay); startMenuActivity(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
showResizeHandle);
} }
} }
@@ -405,7 +409,7 @@ public class PipMenuActivityController {
* Starts the menu activity on the top task of the pinned stack. * Starts the menu activity on the top task of the pinned stack.
*/ */
private void startMenuActivity(int menuState, Rect stackBounds, boolean allowMenuTimeout, private void startMenuActivity(int menuState, Rect stackBounds, boolean allowMenuTimeout,
boolean willResizeMenu, boolean withDelay) { boolean willResizeMenu, boolean withDelay, boolean showResizeHandle) {
try { try {
StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo( StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
@@ -422,6 +426,7 @@ public class PipMenuActivityController {
intent.putExtra(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout); intent.putExtra(EXTRA_ALLOW_TIMEOUT, allowMenuTimeout);
intent.putExtra(EXTRA_WILL_RESIZE_MENU, willResizeMenu); intent.putExtra(EXTRA_WILL_RESIZE_MENU, willResizeMenu);
intent.putExtra(EXTRA_SHOW_MENU_WITH_DELAY, withDelay); intent.putExtra(EXTRA_SHOW_MENU_WITH_DELAY, withDelay);
intent.putExtra(EXTRA_SHOW_RESIZE_HANDLE, showResizeHandle);
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0); ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
options.setLaunchTaskId( options.setLaunchTaskId(
pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]); pinnedStackInfo.taskIds[pinnedStackInfo.taskIds.length - 1]);

View File

@@ -204,7 +204,7 @@ public class PipTouchHandler {
@Override @Override
public void onPipShowMenu() { public void onPipShowMenu() {
mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
true /* allowMenuTimeout */, willResizeMenu()); true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle());
} }
} }
@@ -236,7 +236,7 @@ public class PipTouchHandler {
this::updateMovementBounds); this::updateMovementBounds);
mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler, mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler,
() -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(), () -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(),
true /* allowMenuTimeout */, willResizeMenu())); true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle()));
Resources res = context.getResources(); Resources res = context.getResources();
mExpandedShortestEdgeSize = res.getDimensionPixelSize( mExpandedShortestEdgeSize = res.getDimensionPixelSize(
@@ -311,6 +311,10 @@ public class PipTouchHandler {
mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView); mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView);
} }
private boolean shouldShowResizeHandle() {
return !mPipBoundsHandler.hasSaveReentryBounds();
}
public void setTouchGesture(PipTouchGesture gesture) { public void setTouchGesture(PipTouchGesture gesture) {
mGesture = gesture; mGesture = gesture;
} }
@@ -323,7 +327,8 @@ public class PipTouchHandler {
// Only show the menu if the user isn't currently interacting with the PiP // Only show the menu if the user isn't currently interacting with the PiP
if (!mTouchState.isUserInteracting()) { if (!mTouchState.isUserInteracting()) {
mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
false /* allowMenuTimeout */, willResizeMenu()); false /* allowMenuTimeout */, willResizeMenu(),
shouldShowResizeHandle());
} }
} }
@@ -359,7 +364,8 @@ public class PipTouchHandler {
if (mShowPipMenuOnAnimationEnd) { if (mShowPipMenuOnAnimationEnd) {
mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(), mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(),
true /* allowMenuTimeout */, false /* willResizeMenu */); true /* allowMenuTimeout */, false /* willResizeMenu */,
shouldShowResizeHandle());
mShowPipMenuOnAnimationEnd = false; mShowPipMenuOnAnimationEnd = false;
} }
} }
@@ -566,7 +572,8 @@ public class PipTouchHandler {
private void onAccessibilityShowMenu() { private void onAccessibilityShowMenu() {
mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
true /* allowMenuTimeout */, willResizeMenu()); true /* allowMenuTimeout */, willResizeMenu(),
shouldShowResizeHandle());
} }
private boolean handleTouchEvent(InputEvent inputEvent) { private boolean handleTouchEvent(InputEvent inputEvent) {
@@ -642,7 +649,8 @@ public class PipTouchHandler {
// Let's not enable menu show/hide for a11y services. // Let's not enable menu show/hide for a11y services.
if (!mAccessibilityManager.isTouchExplorationEnabled()) { if (!mAccessibilityManager.isTouchExplorationEnabled()) {
mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
false /* allowMenuTimeout */, false /* willResizeMenu */); false /* allowMenuTimeout */, false /* willResizeMenu */,
shouldShowResizeHandle());
} }
case MotionEvent.ACTION_HOVER_MOVE: { case MotionEvent.ACTION_HOVER_MOVE: {
if (!shouldDeliverToMenu && !mSendingHoverAccessibilityEvents) { if (!shouldDeliverToMenu && !mSendingHoverAccessibilityEvents) {
@@ -905,7 +913,8 @@ public class PipTouchHandler {
// If the menu is still visible, then just poke the menu so that // If the menu is still visible, then just poke the menu so that
// it will timeout after the user stops touching it // it will timeout after the user stops touching it
mMenuController.showMenu(mMenuState, mMotionHelper.getBounds(), mMenuController.showMenu(mMenuState, mMotionHelper.getBounds(),
true /* allowMenuTimeout */, willResizeMenu()); true /* allowMenuTimeout */, willResizeMenu(),
shouldShowResizeHandle());
} }
mShouldHideMenuAfterFling = mMenuState == MENU_STATE_NONE; mShouldHideMenuAfterFling = mMenuState == MENU_STATE_NONE;
@@ -922,7 +931,8 @@ public class PipTouchHandler {
// User has stalled long enough for this not to be a drag or a double tap, just // User has stalled long enough for this not to be a drag or a double tap, just
// expand the menu // expand the menu
mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
true /* allowMenuTimeout */, willResizeMenu()); true /* allowMenuTimeout */, willResizeMenu(),
shouldShowResizeHandle());
} else { } else {
// Next touch event _may_ be the second tap for the double-tap, schedule a // Next touch event _may_ be the second tap for the double-tap, schedule a
// fallback runnable to trigger the menu if no touch event occurs before the // fallback runnable to trigger the menu if no touch event occurs before the