Fix divider rounded corner on specific devices

On large rounded corner devices, Rounded corners around divider
cannot display right corner path because it need more space to
draw corners and divider bounds is fixed.

Fix this by enlarging the divider window bounds. However, if we only
enlarge it, it will cause divider touch region too big to make app
hard to interactive. Therefore, migrate touch region setting logic
in legacy split to here, only set divider handle view size as touch
region.

Fix: 202808282
Test: flash on barbet and active split screen to check
Test: pass existing tests
Change-Id: If292c0d4c598d75672ec821d1fee45a8892b236f
This commit is contained in:
Tony Huang
2021-10-12 16:45:03 +08:00
parent 1679d92eef
commit 70b7b1e2d8
7 changed files with 66 additions and 22 deletions

View File

@@ -23,7 +23,7 @@
</style>
<style name="DockedDividerHandle">
<item name="android:layout_gravity">center_vertical</item>
<item name="android:layout_gravity">center</item>
<item name="android:layout_width">48dp</item>
<item name="android:layout_height">96dp</item>
</style>

View File

@@ -43,7 +43,7 @@
</style>
<style name="DockedDividerHandle">
<item name="android:layout_gravity">center_horizontal</item>
<item name="android:layout_gravity">center</item>
<item name="android:layout_width">96dp</item>
<item name="android:layout_height">48dp</item>
</style>

View File

@@ -19,6 +19,8 @@ package com.android.wm.shell.common.split;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Rect;
@@ -57,6 +59,7 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
private final int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
private SplitLayout mSplitLayout;
private SplitWindowManager mSplitWindowManager;
private SurfaceControlViewHost mViewHost;
private DividerHandleView mHandle;
private View mBackground;
@@ -67,6 +70,7 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
private int mStartPos;
private GestureDetector mDoubleTapDetector;
private boolean mInteractive;
private boolean mSetTouchRegion = true;
/**
* Tracks divider bar visible bounds in screen-based coordination. Used to calculate with
@@ -93,6 +97,18 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
}
};
private AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mSetTouchRegion = true;
}
@Override
public void onAnimationCancel(Animator animation) {
mSetTouchRegion = true;
}
};
public DividerView(@NonNull Context context) {
super(context);
}
@@ -114,9 +130,11 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
/** Sets up essential dependencies of the divider bar. */
public void setup(
SplitLayout layout,
SplitWindowManager splitWindowManager,
SurfaceControlViewHost viewHost,
InsetsState insetsState) {
mSplitLayout = layout;
mSplitWindowManager = splitWindowManager;
mViewHost = viewHost;
mDividerBounds.set(layout.getDividerBounds());
onInsetsChanged(insetsState, false /* animate */);
@@ -138,9 +156,11 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
DIVIDER_HEIGHT_PROPERTY, mDividerBounds.height(), mTempRect.height());
animator.setInterpolator(InsetsController.RESIZE_INTERPOLATOR);
animator.setDuration(InsetsController.ANIMATION_DURATION_RESIZE);
animator.addListener(mAnimatorListener);
animator.start();
} else {
DIVIDER_HEIGHT_PROPERTY.set(this, mTempRect.height());
mSetTouchRegion = true;
}
mDividerBounds.set(mTempRect);
}
@@ -161,6 +181,17 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
setOnTouchListener(this);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (mSetTouchRegion) {
mTempRect.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(),
mHandle.getBottom());
mSplitWindowManager.setTouchRegion(mTempRect);
mSetTouchRegion = false;
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mSplitLayout == null || !mInteractive) {

View File

@@ -40,8 +40,10 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.view.Display;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.RoundedCorner;
import android.view.SurfaceControl;
import android.view.WindowInsets;
import android.view.WindowManager;
@@ -53,6 +55,7 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DockedDividerUtils;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.DisplayImeController;
@@ -133,17 +136,32 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
mDismissingEffectPolicy = new DismissingEffectPolicy(applyDismissingParallax);
final Resources resources = context.getResources();
mDividerWindowWidth = resources.getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_thickness);
mDividerInsets = resources.getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_insets);
mDividerSize = mDividerWindowWidth - mDividerInsets * 2;
mDividerSize = resources.getDimensionPixelSize(R.dimen.split_divider_bar_width);
mDividerInsets = getDividerInsets(resources, context.getDisplay());
mDividerWindowWidth = mDividerSize + 2 * mDividerInsets;
mRootBounds.set(configuration.windowConfiguration.getBounds());
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
resetDividerPosition();
}
private int getDividerInsets(Resources resources, Display display) {
final int dividerInset = resources.getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_insets);
int radius = 0;
RoundedCorner corner = display.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT);
radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
corner = display.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT);
radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
corner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
corner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
return Math.max(dividerInset, radius);
}
/** Gets bounds of the primary split. */
public Rect getBounds1() {
return new Rect(mBounds1);

View File

@@ -31,7 +31,6 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
import android.os.IBinder;
import android.view.IWindow;
import android.view.InsetsState;
import android.view.LayoutInflater;
@@ -41,6 +40,7 @@ import android.view.SurfaceSession;
import android.view.WindowManager;
import android.view.WindowlessWindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.wm.shell.R;
@@ -71,9 +71,10 @@ public final class SplitWindowManager extends WindowlessWindowManager {
mWindowName = windowName;
}
@Override
public void setTouchRegion(IBinder window, Region region) {
super.setTouchRegion(window, region);
void setTouchRegion(@NonNull Rect region) {
if (mViewHost != null) {
setTouchRegion(mViewHost.getWindowToken().asBinder(), new Region(region));
}
}
@Override
@@ -122,7 +123,7 @@ public final class SplitWindowManager extends WindowlessWindowManager {
lp.setTitle(mWindowName);
lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
mViewHost.setView(mDividerView, lp);
mDividerView.setup(splitLayout, mViewHost, insetsState);
mDividerView.setup(splitLayout, this, mViewHost, insetsState);
}
/**

View File

@@ -78,7 +78,7 @@ fun FlickerTestParameter.appPairsPrimaryBoundsIsVisibleAtEnd(
assertLayersEnd {
val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(primaryComponent)
.coversExactly(getPrimaryRegion(dividerRegion, rotation))
.overlaps(getPrimaryRegion(dividerRegion, rotation))
}
}
@@ -89,7 +89,7 @@ fun FlickerTestParameter.dockedStackPrimaryBoundsIsVisibleAtEnd(
assertLayersEnd {
val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(primaryComponent)
.coversExactly(getPrimaryRegion(dividerRegion, rotation))
.overlaps(getPrimaryRegion(dividerRegion, rotation))
}
}
@@ -100,7 +100,7 @@ fun FlickerTestParameter.appPairsSecondaryBoundsIsVisibleAtEnd(
assertLayersEnd {
val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(secondaryComponent)
.coversExactly(getSecondaryRegion(dividerRegion, rotation))
.overlaps(getSecondaryRegion(dividerRegion, rotation))
}
}
@@ -111,7 +111,7 @@ fun FlickerTestParameter.dockedStackSecondaryBoundsIsVisibleAtEnd(
assertLayersEnd {
val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
visibleRegion(secondaryComponent)
.coversExactly(getSecondaryRegion(dividerRegion, rotation))
.overlaps(getSecondaryRegion(dividerRegion, rotation))
}
}

View File

@@ -25,12 +25,6 @@
<item name="android:layout_gravity">center_horizontal</item>
</style>
<style name="DockedDividerHandle">
<item name="android:layout_gravity">center_vertical</item>
<item name="android:layout_width">48dp</item>
<item name="android:layout_height">96dp</item>
</style>
<style name="DockedDividerMinimizedShadow">
<item name="android:layout_width">8dp</item>
<item name="android:layout_height">match_parent</item>