diff options
| author | 2020-12-17 06:17:26 +0000 | |
|---|---|---|
| committer | 2020-12-17 06:17:26 +0000 | |
| commit | 39a6d69a5dac71de53326b3f6f3cfeae5ec5d97d (patch) | |
| tree | cc2c0e4d5dbe8335cd43d881229c6ec96778ec5c | |
| parent | 46bdad0bab63783853c727ea9b336d3be3607d05 (diff) | |
| parent | 2c8ea7b0217ecd50a70c52b3fbd3fa7697d297d7 (diff) | |
Merge "Fix showing black background when resizing the divider bar."
| -rw-r--r-- | libs/WindowManager/Shell/res/layout/docked_stack_divider.xml | 4 | ||||
| -rw-r--r-- | libs/WindowManager/Shell/res/layout/split_divider.xml | 6 | ||||
| -rw-r--r-- | libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java | 28 | ||||
| -rw-r--r-- | libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java (renamed from libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java) | 12 | ||||
| -rw-r--r-- | libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java | 76 | ||||
| -rw-r--r-- | libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java | 4 | ||||
| -rw-r--r-- | libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java | 19 | ||||
| -rw-r--r-- | libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java | 7 | ||||
| -rw-r--r-- | libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java | 15 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowState.java | 3 |
10 files changed, 116 insertions, 58 deletions
diff --git a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml index ea21eb97df57..ed5d2e1b49f5 100644 --- a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml +++ b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml @@ -27,9 +27,9 @@ <com.android.wm.shell.legacysplitscreen.MinimizedDockShadow style="@style/DockedDividerMinimizedShadow" android:id="@+id/minimized_dock_shadow" - android:alpha="0"/>"> + android:alpha="0"/> - <com.android.wm.shell.legacysplitscreen.DividerHandleView + <com.android.wm.shell.common.split.DividerHandleView style="@style/DockedDividerHandle" android:id="@+id/docked_divider_handle" android:contentDescription="@string/accessibility_divider" diff --git a/libs/WindowManager/Shell/res/layout/split_divider.xml b/libs/WindowManager/Shell/res/layout/split_divider.xml index 341fe617b2d0..7f583f3e6bac 100644 --- a/libs/WindowManager/Shell/res/layout/split_divider.xml +++ b/libs/WindowManager/Shell/res/layout/split_divider.xml @@ -24,4 +24,10 @@ android:id="@+id/docked_divider_background" android:background="@color/docked_divider_background"/> + <com.android.wm.shell.common.split.DividerHandleView + style="@style/DockedDividerHandle" + android:id="@+id/docked_divider_handle" + android:contentDescription="@string/accessibility_divider" + android:background="@null"/> + </com.android.wm.shell.common.split.DividerView> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java index 9754f5165a1c..563de06fe40c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java @@ -96,7 +96,8 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.LayoutChan mTaskInfo2 = task2; mSplitLayout = new SplitLayout( mDisplayController.getDisplayContext(mRootTaskInfo.displayId), - mRootTaskInfo.configuration, this, b -> b.setParent(mRootTaskLeash)); + mRootTaskInfo.configuration, this /* layoutChangeListener */, + b -> b.setParent(mRootTaskLeash)); final WindowContainerToken token1 = task1.token; final WindowContainerToken token2 = task2.token; @@ -191,22 +192,7 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.LayoutChan if (mSplitLayout != null && mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)) { - // Update bounds when root bounds or its orientation changed. - final WindowContainerTransaction wct = new WindowContainerTransaction(); - final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash(); - final Rect dividerBounds = mSplitLayout.getDividerBounds(); - final Rect bounds1 = mSplitLayout.getBounds1(); - final Rect bounds2 = mSplitLayout.getBounds2(); - - wct.setBounds(mTaskInfo1.token, bounds1) - .setBounds(mTaskInfo2.token, bounds2); - mController.getTaskOrganizer().applyTransaction(wct); - mSyncQueue.runInSync(t -> t - .setPosition(mTaskLeash1, bounds1.left, bounds1.top) - .setPosition(mTaskLeash2, bounds2.left, bounds2.top) - .setPosition(dividerLeash, dividerBounds.left, dividerBounds.top) - // Resets layer to divider bar to make sure it is always on top. - .setLayer(dividerLeash, Integer.MAX_VALUE)); + onBoundsChanged(mSplitLayout); } } else if (taskInfo.taskId == getTaskId1()) { mTaskInfo1 = taskInfo; @@ -262,6 +248,10 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.LayoutChan final Rect bounds1 = layout.getBounds1(); final Rect bounds2 = layout.getBounds2(); mSyncQueue.runInSync(t -> t + // Ignores the original surface bounds so that the app could fill up the gap + // between each surface with corresponding background while resizing. + .setWindowCrop(mTaskLeash1, bounds1.width(), bounds1.height()) + .setWindowCrop(mTaskLeash2, bounds2.width(), bounds2.height()) .setPosition(dividerLeash, dividerBounds.left, dividerBounds.top) .setPosition(mTaskLeash1, bounds1.left, bounds1.top) .setPosition(mTaskLeash2, bounds2.left, bounds2.top)); @@ -279,6 +269,10 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.LayoutChan .setBounds(mTaskInfo2.token, bounds2); mController.getTaskOrganizer().applyTransaction(wct); mSyncQueue.runInSync(t -> t + // Resets layer of divider bar to make sure it is always on top. + .setLayer(dividerLeash, Integer.MAX_VALUE) + .setWindowCrop(mTaskLeash1, bounds1.width(), bounds1.height()) + .setWindowCrop(mTaskLeash2, bounds2.width(), bounds2.height()) .setPosition(dividerLeash, dividerBounds.left, dividerBounds.top) .setPosition(mTaskLeash1, bounds1.left, bounds1.top) .setPosition(mTaskLeash2, bounds2.left, bounds2.top)); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java index 17ca110285bf..218bf47e24aa 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java @@ -14,7 +14,10 @@ * limitations under the License. */ -package com.android.wm.shell.legacysplitscreen; +package com.android.wm.shell.common.split; + +import static com.android.wm.shell.common.split.DividerView.TOUCH_ANIMATION_DURATION; +import static com.android.wm.shell.common.split.DividerView.TOUCH_RELEASE_ANIMATION_DURATION; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -84,7 +87,8 @@ public class DividerHandleView extends View { mCircleDiameter = (mWidth + mHeight) / 3; } - void setTouching(boolean touching, boolean animate) { + /** Sets touching state for this handle view. */ + public void setTouching(boolean touching, boolean animate) { if (touching == mTouching) { return; } @@ -116,8 +120,8 @@ public class DividerHandleView extends View { mAnimator = new AnimatorSet(); mAnimator.playTogether(widthAnimator, heightAnimator); mAnimator.setDuration(touching - ? DividerView.TOUCH_ANIMATION_DURATION - : DividerView.TOUCH_RELEASE_ANIMATION_DURATION); + ? TOUCH_ANIMATION_DURATION + : TOUCH_RELEASE_ANIMATION_DURATION); mAnimator.setInterpolator(touching ? Interpolators.TOUCH_RESPONSE : Interpolators.FAST_OUT_SLOW_IN); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java index e97fe0a9111c..707747b3889b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java @@ -33,17 +33,23 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.policy.DividerSnapAlgorithm; +import com.android.wm.shell.R; +import com.android.wm.shell.animation.Interpolators; /** * Stack divider for app pair. */ -// TODO(b/172704238): add handle view to indicate touching status. public class DividerView extends FrameLayout implements View.OnTouchListener { + public static final long TOUCH_ANIMATION_DURATION = 150; + public static final long TOUCH_RELEASE_ANIMATION_DURATION = 200; + private final int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); private SplitLayout mSplitLayout; private SurfaceControlViewHost mViewHost; - private DragListener mDragListener; + private DividerHandleView mHandle; + private View mBackground; + private int mTouchElevation; private VelocityTracker mVelocityTracker; private boolean mMoving; @@ -70,16 +76,18 @@ public class DividerView extends FrameLayout implements View.OnTouchListener { /** Sets up essential dependencies of the divider bar. */ public void setup( SplitLayout layout, - SurfaceControlViewHost viewHost, - @Nullable DragListener dragListener) { + SurfaceControlViewHost viewHost) { mSplitLayout = layout; mViewHost = viewHost; - mDragListener = dragListener; } @Override protected void onFinishInflate() { super.onFinishInflate(); + mHandle = findViewById(R.id.docked_divider_handle); + mBackground = findViewById(R.id.docked_divider_background); + mTouchElevation = getResources().getDimensionPixelSize( + R.dimen.docked_stack_divider_lift_elevation); setOnTouchListener(this); } @@ -97,7 +105,7 @@ public class DividerView extends FrameLayout implements View.OnTouchListener { case MotionEvent.ACTION_DOWN: mVelocityTracker = VelocityTracker.obtain(); mVelocityTracker.addMovement(event); - setSlippery(false); + setTouching(); mStartPos = touchPos; mMoving = false; break; @@ -106,9 +114,6 @@ public class DividerView extends FrameLayout implements View.OnTouchListener { if (!mMoving && Math.abs(touchPos - mStartPos) > mTouchSlop) { mStartPos = touchPos; mMoving = true; - if (mDragListener != null) { - mDragListener.onDragStart(); - } } if (mMoving) { final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos; @@ -122,11 +127,8 @@ public class DividerView extends FrameLayout implements View.OnTouchListener { final float velocity = isLandscape ? mVelocityTracker.getXVelocity() : mVelocityTracker.getYVelocity(); - setSlippery(true); + releaseTouching(); mMoving = false; - if (mDragListener != null) { - mDragListener.onDragEnd(); - } final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos; final DividerSnapAlgorithm.SnapTarget snapTarget = @@ -137,6 +139,45 @@ public class DividerView extends FrameLayout implements View.OnTouchListener { return true; } + private void setTouching() { + setSlippery(false); + mHandle.setTouching(true, true); + if (isLandscape()) { + mBackground.animate().scaleX(1.4f); + } else { + mBackground.animate().scaleY(1.4f); + } + mBackground.animate() + .setInterpolator(Interpolators.TOUCH_RESPONSE) + .setDuration(TOUCH_ANIMATION_DURATION) + .translationZ(mTouchElevation) + .start(); + // Lift handle as well so it doesn't get behind the background, even though it doesn't + // cast shadow. + mHandle.animate() + .setInterpolator(Interpolators.TOUCH_RESPONSE) + .setDuration(TOUCH_ANIMATION_DURATION) + .translationZ(mTouchElevation) + .start(); + } + + private void releaseTouching() { + setSlippery(true); + mHandle.setTouching(false, true); + mBackground.animate() + .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) + .setDuration(TOUCH_RELEASE_ANIMATION_DURATION) + .translationZ(0) + .scaleX(1f) + .scaleY(1f) + .start(); + mHandle.animate() + .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) + .setDuration(TOUCH_RELEASE_ANIMATION_DURATION) + .translationZ(0) + .start(); + } + private void setSlippery(boolean slippery) { if (mViewHost == null) { return; @@ -159,13 +200,4 @@ public class DividerView extends FrameLayout implements View.OnTouchListener { private boolean isLandscape() { return getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE; } - - /** Monitors dragging action of the divider bar. */ - // TODO(b/172704238): add listeners to deal with resizing state of the app windows. - public interface DragListener { - /** Called when start dragging. */ - void onDragStart(); - /** Called when stop dragging. */ - void onDragEnd(); - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index 6b9bf2d44261..291e9bdad69b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -156,12 +156,14 @@ public class SplitLayout { void updateDivideBounds(int position) { updateBounds(position); mLayoutChangeListener.onBoundsChanging(this); + mSplitWindowManager.setResizingSplits(true); } void setDividePosition(int position) { mDividePosition = position; updateBounds(mDividePosition); mLayoutChangeListener.onBoundsChanged(this); + mSplitWindowManager.setResizingSplits(false); } /** @@ -172,9 +174,11 @@ public class SplitLayout { switch (snapTarget.flag) { case FLAG_DISMISS_START: mLayoutChangeListener.onSnappedToDismiss(false /* snappedToEnd */); + mSplitWindowManager.setResizingSplits(false); break; case FLAG_DISMISS_END: mLayoutChangeListener.onSnappedToDismiss(true /* snappedToEnd */); + mSplitWindowManager.setResizingSplits(false); break; default: flingDividePosition(currentPosition, snapTarget.position); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java index 238caef27547..29116bd6f956 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java @@ -25,6 +25,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMA import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; +import android.app.ActivityTaskManager; import android.content.Context; import android.content.res.Configuration; import android.graphics.PixelFormat; @@ -32,6 +33,8 @@ import android.graphics.Rect; import android.graphics.Region; import android.os.Binder; import android.os.IBinder; +import android.os.RemoteException; +import android.util.Slog; import android.view.IWindow; import android.view.LayoutInflater; import android.view.SurfaceControl; @@ -47,11 +50,13 @@ import com.android.wm.shell.R; * Holds view hierarchy of a root surface and helps to inflate {@link DividerView} for a split. */ public final class SplitWindowManager extends WindowlessWindowManager { + private static final String TAG = SplitWindowManager.class.getSimpleName(); private static final String DIVIDER_WINDOW_TITLE = "SplitDivider"; + private final ParentContainerCallbacks mParentContainerCallbacks; private Context mContext; private SurfaceControlViewHost mViewHost; - final private ParentContainerCallbacks mParentContainerCallbacks; + private boolean mResizingSplits; public interface ParentContainerCallbacks { void attachToParentSurface(SurfaceControl.Builder b); @@ -104,7 +109,7 @@ public final class SplitWindowManager extends WindowlessWindowManager { lp.setTitle(DIVIDER_WINDOW_TITLE); lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY; mViewHost.setView(dividerView, lp); - dividerView.setup(splitLayout, mViewHost, null /* dragListener */); + dividerView.setup(splitLayout, mViewHost); } /** @@ -117,6 +122,16 @@ public final class SplitWindowManager extends WindowlessWindowManager { mViewHost = null; } + void setResizingSplits(boolean resizing) { + if (resizing == mResizingSplits) return; + try { + ActivityTaskManager.getService().setSplitScreenResizing(resizing); + mResizingSplits = resizing; + } catch (RemoteException e) { + Slog.w(TAG, "Error calling setSplitScreenResizing", e); + } + } + /** * Gets {@link SurfaceControl} of the surface holding divider view. @return {@code null} if not * feasible. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java index 16c966fccbf4..c1b6c4fec792 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java @@ -20,6 +20,9 @@ import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW; import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW; import static android.view.WindowManager.DOCKED_RIGHT; +import static com.android.wm.shell.common.split.DividerView.TOUCH_ANIMATION_DURATION; +import static com.android.wm.shell.common.split.DividerView.TOUCH_RELEASE_ANIMATION_DURATION; + import android.animation.AnimationHandler; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -66,6 +69,7 @@ import com.android.internal.policy.DockedDividerUtils; import com.android.wm.shell.R; import com.android.wm.shell.animation.FlingAnimationUtils; import com.android.wm.shell.animation.Interpolators; +import com.android.wm.shell.common.split.DividerHandleView; import java.util.function.Consumer; @@ -82,9 +86,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, void onDraggingEnd(); } - static final long TOUCH_ANIMATION_DURATION = 150; - static final long TOUCH_RELEASE_ANIMATION_DURATION = 200; - public static final int INVALID_RECENTS_GROW_TARGET = -1; private static final int LOG_VALUE_RESIZE_50_50 = 0; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java index 708a6c56a3f5..cd468167e372 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java @@ -75,15 +75,16 @@ public class SplitLayoutTests extends ShellTestCase { } @Test - @UiThreadTest - public void testSnapToTarget() { - DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */, - DividerSnapAlgorithm.SnapTarget.FLAG_NONE); - mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget); - verify(mLayoutChangeListener).onBoundsChanging(any(SplitLayout.class)); + public void testSetDividePosition() { + mSplitLayout.setDividePosition(anyInt()); + verify(mLayoutChangeListener).onBoundsChanged(any(SplitLayout.class)); + } + @Test + @UiThreadTest + public void testSnapToDismissTarget() { // verify it callbacks properly when the snap target indicates dismissing split. - snapTarget = getSnapTarget(0 /* position */, + DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */, DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START); mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget); verify(mLayoutChangeListener).onSnappedToDismiss(eq(false)); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 32b84a8d0a2c..d3102600092f 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -3843,7 +3843,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (task == null) { return false; } - if (!inSplitScreenWindowingMode() && !inFreeformWindowingMode()) { + if (!inSplitScreenWindowingMode() && !inFreeformWindowingMode() + && !task.getRootTask().mCreatedByOrganizer) { return false; } // TODO(157912944): formalize drag-resizing so that exceptions aren't hardcoded like this |