From b8eeb41ee0ea4807df13b47cf5433c2773b0a14c Mon Sep 17 00:00:00 2001 From: Jeremy Sim Date: Mon, 21 Mar 2022 19:55:07 -0700 Subject: [PATCH] Fix issue with camera overlapping split staging UI Fixes an issue on some devices where initiating a split in Overview would cause an icon to be placed partly under the camera cutout. Fixed by adding some padding to FloatingTaskView#mSplitPlaceHolderView, so that it always respects the device's insets. Fixes: 220997064 Test: Manual Change-Id: I7270bde3320f562519ea8e36a38e49609e0d6cd7 --- .../quickstep/views/FloatingTaskView.java | 27 ++++++++++---- .../quickstep/views/SplitPlaceholderView.java | 8 +--- .../touch/LandscapePagedViewHandler.java | 16 +++++++- .../touch/PagedOrientationHandler.java | 19 ++++++++++ .../touch/PortraitPagedViewHandler.java | 37 ++++++++++++++++++- 5 files changed, 90 insertions(+), 17 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java index fe5e1d0d57..c13ab02a56 100644 --- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java +++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java @@ -27,6 +27,7 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.touch.PagedOrientationHandler; +import com.android.launcher3.util.SplitConfigurationOptions; import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.TaskCornerRadius; @@ -53,6 +54,8 @@ public class FloatingTaskView extends FrameLayout { private final boolean mIsRtl; private final FullscreenDrawParams mFullscreenParams; private PagedOrientationHandler mOrientationHandler; + @SplitConfigurationOptions.StagePosition + private int mStagePosition; public FloatingTaskView(Context context) { this(context, null); @@ -95,6 +98,7 @@ public class FloatingTaskView extends FrameLayout { RecentsView recentsView = launcher.getOverviewPanel(); mOrientationHandler = recentsView.getPagedOrientationHandler(); + mStagePosition = recentsView.getSplitPlaceholder().getActiveSplitStagePosition(); mSplitPlaceholderView.setIcon(icon, mContext.getResources().getDimensionPixelSize(R.dimen.split_placeholder_icon_size)); mSplitPlaceholderView.getIconView().setRotation(mOrientationHandler.getDegreesRotated()); @@ -215,7 +219,7 @@ public class FloatingTaskView extends FrameLayout { transitionAnimator.addUpdateListener(listener); } - public void drawRoundedRect(Canvas canvas, Paint paint) { + void drawRoundedRect(Canvas canvas, Paint paint) { if (mFullscreenParams == null) { return; } @@ -226,12 +230,21 @@ public class FloatingTaskView extends FrameLayout { paint); } - public float getFullscreenScaleX() { - return mFullscreenParams.mScaleX; - } - - public float getFullscreenScaleY() { - return mFullscreenParams.mScaleY; + /** + * When a split is staged, center the icon in the staging area. Accounts for device insets. + * @param iconView The icon that should be centered. + * @param onScreenRectCenterX The x-center of the on-screen staging area (most of the Rect is + * offscreen). + * @param onScreenRectCenterY The y-center of the on-screen staging area (most of the Rect is + * offscreen). + */ + void centerIconView(IconView iconView, float onScreenRectCenterX, float onScreenRectCenterY) { + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) iconView.getLayoutParams(); + mOrientationHandler.updateStagedSplitIconParams(params, onScreenRectCenterX, + onScreenRectCenterY, mFullscreenParams.mScaleX, mFullscreenParams.mScaleY, + iconView.getDrawableWidth(), iconView.getDrawableHeight(), + mActivity.getDeviceProfile(), mStagePosition); + iconView.setLayoutParams(params); } private static class SplitOverlayProperties { diff --git a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java index 74442177be..28080d477f 100644 --- a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java +++ b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java @@ -68,13 +68,7 @@ public class SplitPlaceholderView extends FrameLayout { // Center the icon view in the visible area. getLocalVisibleRect(mTempRect); FloatingTaskView parent = (FloatingTaskView) getParent(); - FrameLayout.LayoutParams params = - (FrameLayout.LayoutParams) mIconView.getLayoutParams(); - params.leftMargin = Math.round(mTempRect.centerX() / parent.getFullscreenScaleX() - - 1.0f * mIconView.getDrawableWidth() / 2); - params.topMargin = Math.round(mTempRect.centerY() / parent.getFullscreenScaleY() - - 1.0f * mIconView.getDrawableHeight() / 2); - mIconView.setLayoutParams(params); + parent.centerIconView(mIconView, mTempRect.centerX(), mTempRect.centerY()); } } diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index 4fcba18844..88a4d66273 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -399,7 +399,8 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { // In fake land/seascape, the placeholder always needs to go to the "top" of the device, // which is the same bounds as 0 rotation. int width = dp.widthPx; - out.set(0, 0, width, placeholderHeight); + int insetThickness = dp.getInsets().top; + out.set(0, 0, width, placeholderHeight + insetThickness); out.inset(placeholderInset, 0); // Adjust the top to account for content off screen. This will help to animate the view in @@ -411,6 +412,19 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { out.top -= (totalHeight - placeholderHeight); } + @Override + public void updateStagedSplitIconParams(FrameLayout.LayoutParams out, float onScreenRectCenterX, + float onScreenRectCenterY, float fullscreenScaleX, float fullscreenScaleY, + int drawableWidth, int drawableHeight, DeviceProfile dp, + @StagePosition int stagePosition) { + float inset = dp.getInsets().top; + out.leftMargin = Math.round(onScreenRectCenterX / fullscreenScaleX + - 1.0f * drawableWidth / 2); + out.topMargin = Math.round((onScreenRectCenterY + (inset / 2f)) / fullscreenScaleY + - 1.0f * drawableHeight / 2); + + } + @Override public void getFinalSplitPlaceholderBounds(int splitDividerSize, DeviceProfile dp, @StagePosition int stagePosition, Rect out1, Rect out2) { diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index 850eaaf9b4..510a728765 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -115,6 +115,25 @@ public interface PagedOrientationHandler { void getInitialSplitPlaceholderBounds(int placeholderHeight, int placeholderInset, DeviceProfile dp, @StagePosition int stagePosition, Rect out); + /** + * Centers an icon in the split staging area, accounting for insets. + * @param out The LayoutParams of the icon that needs to be centered. + * @param onScreenRectCenterX The x-center of the on-screen staging area (most of the Rect is + * offscreen). + * @param onScreenRectCenterY The y-center of the on-screen staging area (most of the Rect is + * offscreen). + * @param fullscreenScaleX A x-scaling factor used to convert coordinates back into pixels. + * @param fullscreenScaleY A y-scaling factor used to convert coordinates back into pixels. + * @param drawableWidth The icon's drawable (final) width. + * @param drawableHeight The icon's drawable (final) height. + * @param dp The device profile, used to report rotation and hardware insets. + * @param stagePosition 0 if the staging area is pinned to top/left, 1 for bottom/right. + */ + void updateStagedSplitIconParams(FrameLayout.LayoutParams out, float onScreenRectCenterX, + float onScreenRectCenterY, float fullscreenScaleX, float fullscreenScaleY, + int drawableWidth, int drawableHeight, DeviceProfile dp, + @StagePosition int stagePosition); + /** * @param splitDividerSize height of split screen drag handle in portrait, width in landscape * @param stagePosition the split position option (top/left, bottom/right) of the first diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index d132901238..d88656c9f0 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -440,7 +440,14 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { DeviceProfile dp, @StagePosition int stagePosition, Rect out) { int screenWidth = dp.widthPx; int screenHeight = dp.heightPx; - out.set(0, 0, screenWidth, placeholderHeight); + boolean pinToRight = stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT; + int insetThickness; + if (!dp.isLandscape) { + insetThickness = dp.getInsets().top; + } else { + insetThickness = pinToRight ? dp.getInsets().right : dp.getInsets().left; + } + out.set(0, 0, screenWidth, placeholderHeight + insetThickness); if (!dp.isLandscape) { // portrait, phone or tablet - spans width of screen, nothing else to do out.inset(placeholderInset, 0); @@ -454,7 +461,6 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { } // Now we rotate the portrait rect depending on what side we want pinned - boolean pinToRight = stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT; float postRotateScale = (float) screenHeight / screenWidth; mTmpMatrix.reset(); @@ -480,6 +486,33 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { } } + @Override + public void updateStagedSplitIconParams(FrameLayout.LayoutParams out, float onScreenRectCenterX, + float onScreenRectCenterY, float fullscreenScaleX, float fullscreenScaleY, + int drawableWidth, int drawableHeight, DeviceProfile dp, + @StagePosition int stagePosition) { + boolean pinToRight = stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT; + if (!dp.isLandscape) { + float inset = dp.getInsets().top; + out.leftMargin = Math.round(onScreenRectCenterX / fullscreenScaleX + - 1.0f * drawableWidth / 2); + out.topMargin = Math.round((onScreenRectCenterY + (inset / 2f)) / fullscreenScaleY + - 1.0f * drawableHeight / 2); + } else { + if (pinToRight) { + float inset = dp.getInsets().right; + out.leftMargin = Math.round((onScreenRectCenterX - (inset / 2f)) / fullscreenScaleX + - 1.0f * drawableWidth / 2); + } else { + float inset = dp.getInsets().left; + out.leftMargin = Math.round((onScreenRectCenterX + (inset / 2f)) / fullscreenScaleX + - 1.0f * drawableWidth / 2); + } + out.topMargin = Math.round(onScreenRectCenterY / fullscreenScaleY + - 1.0f * drawableHeight / 2); + } + } + @Override public void getFinalSplitPlaceholderBounds(int splitDividerSize, DeviceProfile dp, @StagePosition int stagePosition, Rect out1, Rect out2) {