summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jerry Chang <chenghsiuchang@google.com> 2020-12-04 16:11:15 +0800
committer Jerry Chang <chenghsiuchang@google.com> 2020-12-17 07:39:24 +0800
commit2c8ea7b0217ecd50a70c52b3fbd3fa7697d297d7 (patch)
treebf1f8c810f80db1b0e1517c2a3e6f8bf20dfdb38
parent519fb38710e029818bfeea37f46025636386591a (diff)
Fix showing black background when resizing the divider bar.
Reports resizing state to WM core so that app client could apply bigger visible bounds while resizing splits. Also moves DividerHandleView to more generic package. Fix: 172704238 Test: manul check divider behavior Test: atest WMShellUnitTests Change-Id: I1656c86de9a0b5dfe5e6da57ccc9d5f6e467843a
-rw-r--r--libs/WindowManager/Shell/res/layout/docked_stack_divider.xml4
-rw-r--r--libs/WindowManager/Shell/res/layout/split_divider.xml6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java28
-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.java76
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java19
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java7
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java3
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