diff options
| author | 2025-02-18 11:48:15 -0800 | |
|---|---|---|
| committer | 2025-02-18 11:48:15 -0800 | |
| commit | 57e30ba1eb0723672c202fc73f950ee6ffbe23bf (patch) | |
| tree | ff98ca0a6f29ac42575282b21b54a8c674d5bdce | |
| parent | 1ab6e1ef0ab0072a592827d69e17dc957cd34469 (diff) | |
| parent | 727a2180ed0f4ea477fda5a6c731eb4d27b85db8 (diff) | |
Merge "Fix various issues with offscreen touch zones" into main
3 files changed, 29 insertions, 3 deletions
| diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OffscreenTouchZone.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OffscreenTouchZone.java index 381f0b037023..3211307c6f9b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OffscreenTouchZone.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OffscreenTouchZone.java @@ -56,6 +56,7 @@ public class OffscreenTouchZone {      /** The function that will be run when this zone is tapped. */      private final Runnable mOnClickRunnable;      private SurfaceControlViewHost mViewHost; +    private SurfaceControl mLeash;      /**       * @param isTopLeft Whether the desired touch zone will be on the top/left or the bottom/right @@ -96,6 +97,7 @@ public class OffscreenTouchZone {                  .setCallsite("OffscreenTouchZone::init");          builder.setParent(stageRoot);          SurfaceControl leash = builder.build(); +        mLeash = leash;          // Create a ViewHost that will hold our view.          WindowlessWindowManager wwm = new WindowlessWindowManager(config, leash, null); @@ -117,10 +119,14 @@ public class OffscreenTouchZone {      }      /** Releases the touch zone when it's no longer needed. */ -    void release() { +    void release(SurfaceControl.Transaction t) {          if (mViewHost != null) {              mViewHost.release();          } +        if (mLeash != null) { +            t.remove(mLeash); +            mLeash = null; +        }      }      /** 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 708e26cc5546..720e8e53b218 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 @@ -461,7 +461,14 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange              return;          } -        mOffscreenTouchZones.forEach(OffscreenTouchZone::release); +        // TODO (b/349828130): It would be good to reuse a Transaction from StageCoordinator's +        //  mTransactionPool here, but passing it through SplitLayout and specifically +        //  SplitLayout.release() is complicated because that function is purposely called with a +        //  null value sometimes. When that function is refactored, we should also pass the +        //  Transaction in here. +        SurfaceControl.Transaction t = new SurfaceControl.Transaction(); +        mOffscreenTouchZones.forEach(touchZone -> touchZone.release(t)); +        t.apply();          mOffscreenTouchZones.clear();      } @@ -975,8 +982,16 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange          final boolean shouldVeil =                  insets.left != 0 || insets.top != 0 || insets.right != 0 || insets.bottom != 0; +        // Find the "left/top"-most position of the app surface -- usually 0, but sometimes negative +        // if the left/top app is offscreen. +        int leftTop = 0; +        if (Flags.enableFlexibleTwoAppSplit()) { +            leftTop = mIsLeftRightSplit ? getTopLeftBounds().left : getTopLeftBounds().top; +        } +          final int dividerPos = mDividerSnapAlgorithm.calculateNonDismissingSnapTarget( -                mIsLeftRightSplit ? getBottomRightBounds().width() : getBottomRightBounds().height() +                leftTop + (mIsLeftRightSplit +                        ? getBottomRightBounds().width() : getBottomRightBounds().height())          ).position;          final Rect endBounds1 = new Rect();          final Rect endBounds2 = new Rect(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 73b42d6f007c..77a7c5406a67 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -1317,6 +1317,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,          WindowContainerTransaction noFocus = new WindowContainerTransaction();          noFocus.setFocusable(mRootTaskInfo.token, false);          mSyncQueue.queue(noFocus); +        // Remove touch layers, since offscreen apps coming onscreen will not need their touch +        // layers anymore. populateTouchZones() is called in the end callback to inflate new touch +        // layers in the appropriate places. +        mSplitLayout.removeTouchZones();          mSplitLayout.playSwapAnimation(t, topLeftStage, bottomRightStage,                  insets -> { @@ -1337,6 +1341,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,                      mSyncQueue.runInSync(st -> {                          mSplitLayout.updateStateWithCurrentPosition();                          updateSurfaceBounds(mSplitLayout, st, false /* applyResizingOffset */); +                        mSplitLayout.populateTouchZones();                          // updateSurfaceBounds(), above, officially puts the two apps in their new                          // stages. Starting on the next frame, all calculations are made using the |