From 157d3b950d66118c0a76785edf815741ca532ef3 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Fri, 13 Aug 2021 17:03:55 -0700 Subject: [PATCH 1/2] Draw rounded corners above the taskbar - Increase height of taskbar window, but not contentInsets - Draw the inverted corners as part of TaskbarDragLayer#dispatchDraw() (which handles the background already) Test: visual Bug: 196257194 Change-Id: I51d992078579e877c85a1d71ee4c00d85fd9db2e --- .../taskbar/TaskbarActivityContext.java | 28 ++++++++++++- .../launcher3/taskbar/TaskbarDragLayer.java | 42 ++++++++++++++++++- .../taskbar/TaskbarDragLayerController.java | 6 ++- .../taskbar/TaskbarViewController.java | 5 ++- 4 files changed, 73 insertions(+), 8 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index ec0355b133..a90f17d227 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -36,6 +36,7 @@ import android.view.ContextThemeWrapper; import android.view.Display; import android.view.Gravity; import android.view.LayoutInflater; +import android.view.RoundedCorner; import android.view.View; import android.view.WindowManager; import android.widget.FrameLayout; @@ -83,6 +84,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ private final TaskbarControllers mControllers; private final WindowManager mWindowManager; + private final RoundedCorner mLeftCorner, mRightCorner; private WindowManager.LayoutParams mWindowLayoutParams; private boolean mIsFullscreen; // The size we should return to when we call setTaskbarWindowFullscreen(false) @@ -136,10 +138,12 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ ? windowContext.getApplicationContext() : windowContext.getApplicationContext().createDisplayContext(display); mWindowManager = c.getSystemService(WindowManager.class); + mLeftCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT); + mRightCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT); } public void init() { - mLastRequestedNonFullscreenHeight = mDeviceProfile.taskbarSize; + mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight(); mWindowLayoutParams = new WindowManager.LayoutParams( MATCH_PARENT, mLastRequestedNonFullscreenHeight, @@ -169,6 +173,14 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ return mNavMode == Mode.THREE_BUTTONS; } + public RoundedCorner getLeftCorner() { + return mLeftCorner; + } + + public RoundedCorner getRightCorner() { + return mRightCorner; + } + @Override public LayoutInflater getLayoutInflater() { return mLayoutInflater; @@ -250,8 +262,12 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ setTaskbarWindowHeight(fullscreen ? MATCH_PARENT : mLastRequestedNonFullscreenHeight); } + public boolean isTaskbarWindowFullscreen() { + return mIsFullscreen; + } + /** - * Updates the TaskbarContainer height (pass deviceProfile.taskbarSize to reset). + * Updates the TaskbarContainer height (pass {@link #getDefaultTaskbarWindowHeight()} to reset). */ public void setTaskbarWindowHeight(int height) { if (mWindowLayoutParams.height == height || mIsDestroyed) { @@ -271,6 +287,14 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams); } + /** + * Returns the default height of the window, including the static corner radii above taskbar. + */ + public int getDefaultTaskbarWindowHeight() { + return mDeviceProfile.taskbarSize + + Math.max(mLeftCorner.getRadius(), mRightCorner.getRadius()); + } + protected void onTaskbarIconClicked(View view) { Object tag = view.getTag(); if (tag instanceof Task) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java index cd1baf726d..0848c35bf2 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java @@ -18,6 +18,7 @@ package com.android.launcher3.taskbar; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.Path; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; @@ -40,9 +41,12 @@ import com.android.systemui.shared.system.ViewTreeObserverWrapper.OnComputeInset public class TaskbarDragLayer extends BaseDragLayer { private final Paint mTaskbarBackgroundPaint; + private final Path mInvertedLeftCornerPath, mInvertedRightCornerPath; private final OnComputeInsetsListener mTaskbarInsetsComputer = this::onComputeTaskbarInsets; + // Initialized in init. private TaskbarDragLayerController.TaskbarDragLayerCallbacks mControllerCallbacks; + private float mLeftCornerRadius, mRightCornerRadius; private float mTaskbarBackgroundOffset; @@ -65,10 +69,32 @@ public class TaskbarDragLayer extends BaseDragLayer { mTaskbarBackgroundPaint = new Paint(); mTaskbarBackgroundPaint.setColor(getResources().getColor(R.color.taskbar_background)); mTaskbarBackgroundPaint.setAlpha(0); + mTaskbarBackgroundPaint.setFlags(Paint.ANTI_ALIAS_FLAG); + mTaskbarBackgroundPaint.setStyle(Paint.Style.FILL); + + // Will be set in init(), but this ensures they are always non-null. + mInvertedLeftCornerPath = new Path(); + mInvertedRightCornerPath = new Path(); } public void init(TaskbarDragLayerController.TaskbarDragLayerCallbacks callbacks) { mControllerCallbacks = callbacks; + + // Create the paths for the inverted rounded corners above the taskbar. Start with a filled + // square, and then subtracting out a circle from the appropriate corner. + mLeftCornerRadius = mActivity.getLeftCorner().getRadius(); + mRightCornerRadius = mActivity.getRightCorner().getRadius(); + Path square = new Path(); + square.addRect(0, 0, mLeftCornerRadius, mLeftCornerRadius, Path.Direction.CW); + Path circle = new Path(); + circle.addCircle(mLeftCornerRadius, 0, mLeftCornerRadius, Path.Direction.CW); + mInvertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE); + square.reset(); + square.addRect(0, 0, mRightCornerRadius, mRightCornerRadius, Path.Direction.CW); + circle.reset(); + circle.addCircle(0, 0, mRightCornerRadius, Path.Direction.CW); + mInvertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE); + recreateControllers(); } @@ -121,8 +147,20 @@ public class TaskbarDragLayer extends BaseDragLayer { protected void dispatchDraw(Canvas canvas) { float backgroundHeight = mControllerCallbacks.getTaskbarBackgroundHeight() * (1f - mTaskbarBackgroundOffset); - canvas.drawRect(0, canvas.getHeight() - backgroundHeight, canvas.getWidth(), - canvas.getHeight(), mTaskbarBackgroundPaint); + canvas.save(); + canvas.translate(0, canvas.getHeight() - backgroundHeight); + + // Draw the background behind taskbar content. + canvas.drawRect(0, 0, canvas.getWidth(), backgroundHeight, mTaskbarBackgroundPaint); + + // Draw the inverted rounded corners above the taskbar. + canvas.translate(0, -mLeftCornerRadius); + canvas.drawPath(mInvertedLeftCornerPath, mTaskbarBackgroundPaint); + canvas.translate(0, mLeftCornerRadius); + canvas.translate(canvas.getWidth() - mRightCornerRadius, -mRightCornerRadius); + canvas.drawPath(mInvertedRightCornerPath, mTaskbarBackgroundPaint); + + canvas.restore(); super.dispatchDraw(canvas); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java index 14150b9e25..0afa480667 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java @@ -16,6 +16,7 @@ package com.android.launcher3.taskbar; import static com.android.launcher3.AbstractFloatingView.TYPE_ALL; +import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_CONTENT; import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_FRAME; import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION; @@ -132,13 +133,14 @@ public class TaskbarDragLayerController { // Let touches pass through us. insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); } else if (mControllers.navbarButtonsViewController.isImeVisible()) { - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME); + insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_CONTENT); } else if (!mControllers.uiController.isTaskbarTouchable()) { // Let touches pass through us. insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); } else if (mControllers.taskbarViewController.areIconsVisible()) { // Buttons are visible, take over the full taskbar area - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME); + insetsInfo.setTouchableInsets(mActivity.isTaskbarWindowFullscreen() + ? TOUCHABLE_INSETS_FRAME : TOUCHABLE_INSETS_CONTENT); } else { insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 6b95f08090..1882762a67 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -165,8 +165,9 @@ public class TaskbarViewController { int offsetY = launcherDp.getTaskbarOffsetY(); setter.setFloat(mTaskbarIconTranslationYForHome, VALUE, -offsetY, LINEAR); - int collapsedHeight = mActivity.getDeviceProfile().taskbarSize; - int expandedHeight = collapsedHeight + offsetY; + int collapsedHeight = mActivity.getDefaultTaskbarWindowHeight(); + int expandedHeight = Math.max(collapsedHeight, + mActivity.getDeviceProfile().taskbarSize + offsetY); setter.addOnFrameListener(anim -> mActivity.setTaskbarWindowHeight( anim.getAnimatedFraction() > 0 ? expandedHeight : collapsedHeight)); From 3974edc46a7f6c027f051e03e8e998b2e23c8a3d Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 16 Aug 2021 17:39:12 -0700 Subject: [PATCH 2/2] Don't draw taskbar background during gestures In this case, the ScrimView for BackgroundAppState will handle drawing behind the whole screen, and prevents taskbar from drawing the rounded corners on top of TaskViews. Added a hack to defer resuming last task by a frame to ensure taskbar is drawing first. Test: Quick switch to an app, ensure it isn't covered by the taskbar's rounded corner Bug: 196257194 Change-Id: Ibc81d80bc3bf1d908e6912b179cbcafbdcc56c0f --- .../taskbar/LauncherTaskbarUIController.java | 7 ++++- .../android/quickstep/AbsSwipeUpHandler.java | 20 +++++++++++--- .../quickstep/BaseActivityInterface.java | 10 +++++++ .../quickstep/LauncherActivityInterface.java | 26 +++++++++++++++++++ 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 4c96fbae9d..da10bfb0fa 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -23,6 +23,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.graphics.Rect; import android.view.MotionEvent; +import android.view.View; import androidx.annotation.NonNull; @@ -241,7 +242,11 @@ public class LauncherTaskbarUIController extends TaskbarUIController { return mContext.getDragController().isDragging(); } - void setTaskbarViewVisible(boolean isVisible) { + public View getRootView() { + return mTaskbarDragLayer; + } + + private void setTaskbarViewVisible(boolean isVisible) { mIconAlphaForHome.setValue(isVisible ? 1 : 0); mLauncher.getHotseat().setIconsAlpha(isVisible ? 0f : 1f); } diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 42c89fd006..6797fbb032 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -655,8 +655,13 @@ public abstract class AbsSwipeUpHandler, private void onAnimatorPlaybackControllerCreated(AnimatorControllerWithResistance anim) { mLauncherTransitionController = anim; - mLauncherTransitionController.getNormalController().dispatchOnStart(); - updateLauncherTransitionProgress(); + mStateCallback.runOnceAtState(STATE_GESTURE_STARTED, () -> { + // Wait until the gesture is started (touch slop was passed) to start in sync with + // mWindowTransitionController. This ensures we don't hide the taskbar background when + // long pressing to stash it, for instance. + mLauncherTransitionController.getNormalController().dispatchOnStart(); + updateLauncherTransitionProgress(); + }); } public Intent getLaunchIntent() { @@ -885,6 +890,9 @@ public abstract class AbsSwipeUpHandler, // Fast-finish the attaching animation if it's still running. maybeUpdateRecentsAttachedState(false); final GestureEndTarget endTarget = mGestureState.getEndTarget(); + // Wait until the given View (if supplied) draws before resuming the last task. + View postResumeLastTask = mActivityInterface.onSettledOnEndTarget(endTarget); + if (endTarget != NEW_TASK) { InteractionJankMonitorWrapper.cancel( InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH); @@ -893,6 +901,7 @@ public abstract class AbsSwipeUpHandler, InteractionJankMonitorWrapper.cancel( InteractionJankMonitorWrapper.CUJ_APP_CLOSE_TO_HOME); } + switch (endTarget) { case HOME: mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT); @@ -907,7 +916,12 @@ public abstract class AbsSwipeUpHandler, mStateCallback.setState(STATE_START_NEW_TASK | STATE_CAPTURE_SCREENSHOT); break; case LAST_TASK: - mStateCallback.setState(STATE_RESUME_LAST_TASK); + if (postResumeLastTask != null) { + ViewUtils.postFrameDrawn(postResumeLastTask, + () -> mStateCallback.setState(STATE_RESUME_LAST_TASK)); + } else { + mStateCallback.setState(STATE_RESUME_LAST_TASK); + } TaskViewUtils.setDividerBarShown(mRecentsAnimationTargets.nonApps, true); break; } diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index 571ffc23e5..29a069c354 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -40,6 +40,7 @@ import android.graphics.Rect; import android.os.Build; import android.view.Gravity; import android.view.MotionEvent; +import android.view.View; import androidx.annotation.Nullable; import androidx.annotation.UiThread; @@ -385,6 +386,15 @@ public abstract class BaseActivityInterface