From 5916e506ddf2e7448f329870ce5786d18f7305a2 Mon Sep 17 00:00:00 2001 From: Chavi Weingarten Date: Tue, 24 Jan 2023 20:30:15 +0000 Subject: [PATCH] Revert "Remove WindowlessWindowLayout" This reverts commit 6b2045872fa7ab5dfe1187ff9650c88ebdf46750. Reason for revert: Breaks bounds computation for windowless windows by computing inset values Change-Id: I11a4b8a16a905ab46b26b783f67bd1b3f2939e43 --- .../android/view/SurfaceControlViewHost.java | 4 +- core/java/android/view/ViewRootImpl.java | 7 +- .../android/view/WindowManagerGlobal.java | 3 +- .../android/view/WindowlessWindowLayout.java | 71 +++++++++++++++++++ .../android/view/WindowlessWindowManager.java | 32 ++++----- 5 files changed, 91 insertions(+), 26 deletions(-) create mode 100644 core/java/android/view/WindowlessWindowLayout.java diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java index 3efbb75f281e4..c9eee6a5c9f84 100644 --- a/core/java/android/view/SurfaceControlViewHost.java +++ b/core/java/android/view/SurfaceControlViewHost.java @@ -292,7 +292,7 @@ public class SurfaceControlViewHost { public SurfaceControlViewHost(@NonNull Context c, @NonNull Display d, @NonNull WindowlessWindowManager wwm) { mWm = wwm; - mViewRoot = new ViewRootImpl(c, d, mWm); + mViewRoot = new ViewRootImpl(c, d, mWm, new WindowlessWindowLayout()); addConfigCallback(c, d); WindowManagerGlobal.getInstance().addWindowlessRoot(mViewRoot); @@ -322,7 +322,7 @@ public class SurfaceControlViewHost { mWm = new WindowlessWindowManager(context.getResources().getConfiguration(), mSurfaceControl, hostToken); - mViewRoot = new ViewRootImpl(context, display, mWm); + mViewRoot = new ViewRootImpl(context, display, mWm, new WindowlessWindowLayout()); addConfigCallback(context, display); WindowManagerGlobal.getInstance().addWindowlessRoot(mViewRoot); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 898e46e4003ae..f8182839e454f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -922,13 +922,14 @@ public final class ViewRootImpl implements ViewParent, private String mTag = TAG; public ViewRootImpl(Context context, Display display) { - this(context, display, WindowManagerGlobal.getWindowSession()); + this(context, display, WindowManagerGlobal.getWindowSession(), new WindowLayout()); } - public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session) { + public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session, + WindowLayout windowLayout) { mContext = context; mWindowSession = session; - mWindowLayout = new WindowLayout(); + mWindowLayout = windowLayout; mDisplay = display; mBasePackageName = context.getBasePackageName(); mThread = Thread.currentThread(); diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index acc0c0bad1f8d..4a9dc5b14a710 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -388,7 +388,8 @@ public final class WindowManagerGlobal { if (windowlessSession == null) { root = new ViewRootImpl(view.getContext(), display); } else { - root = new ViewRootImpl(view.getContext(), display, windowlessSession); + root = new ViewRootImpl(view.getContext(), display, + windowlessSession, new WindowlessWindowLayout()); } view.setLayoutParams(wparams); diff --git a/core/java/android/view/WindowlessWindowLayout.java b/core/java/android/view/WindowlessWindowLayout.java new file mode 100644 index 0000000000000..e2afaa5c38855 --- /dev/null +++ b/core/java/android/view/WindowlessWindowLayout.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; + +import android.app.WindowConfiguration.WindowingMode; +import android.graphics.Rect; +import android.view.WindowInsets.Type.InsetsType; +import android.window.ClientWindowFrames; + +/** + * Computes window frames for the windowless window. + * + * This can't be replaced with the regular WindowLayout because WindowLayout computes bounds + * with insets and cutout values. Since windowless windows aren't affected by insets and + * instead are bound by their parent, it will compute incorrect bounds for them if insets are used. + * + * @hide + */ +public class WindowlessWindowLayout extends WindowLayout { + + @Override + public void computeFrames(WindowManager.LayoutParams attrs, InsetsState state, + Rect displayCutoutSafe, Rect windowBounds, @WindowingMode int windowingMode, + int requestedWidth, int requestedHeight, @InsetsType int requestedVisibleTypes, + float compatScale, ClientWindowFrames frames) { + if (frames.attachedFrame == null) { + frames.frame.set(0, 0, attrs.width, attrs.height); + frames.parentFrame.set(frames.frame); + frames.displayFrame.set(frames.frame); + return; + } + + final int height = calculateLength(attrs.height, requestedHeight, + frames.attachedFrame.height()); + final int width = calculateLength(attrs.width, requestedWidth, + frames.attachedFrame.width()); + Gravity.apply(attrs.gravity, width, height, frames.attachedFrame, + (int) (attrs.x + attrs.horizontalMargin), + (int) (attrs.y + attrs.verticalMargin), + frames.frame); + frames.displayFrame.set(frames.frame); + frames.parentFrame.set(frames.attachedFrame); + } + + private static int calculateLength(int attrLength, int requestedLength, int parentLength) { + if (attrLength == MATCH_PARENT) { + return parentLength; + } + if (attrLength == WRAP_CONTENT) { + return requestedLength; + } + return attrLength; + } +} diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index 4ddd4858785e0..021193e8d9184 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -94,10 +94,7 @@ public class WindowlessWindowManager implements IWindowSession { private InsetsState mInsetsState; private final ClientWindowFrames mTmpFrames = new ClientWindowFrames(); private final MergedConfiguration mTmpConfig = new MergedConfiguration(); - private final InsetsState mTmpInsetsState = new InsetsState(); - private final Rect mTmpDisplayCutoutSafe = new Rect(); - private final Rect mTmpWindowBounds = new Rect(); - private final WindowLayout mLayout = new WindowLayout(); + private final WindowlessWindowLayout mLayout = new WindowlessWindowLayout(); public WindowlessWindowManager(Configuration c, SurfaceControl rootSurface, IBinder hostInputToken) { @@ -349,27 +346,22 @@ public class WindowlessWindowManager implements IWindowSession { } WindowManager.LayoutParams attrs = state.mParams; - mTmpFrames.attachedFrame = state.mAttachedFrame; + ClientWindowFrames frames = new ClientWindowFrames(); + frames.attachedFrame = state.mAttachedFrame; - if (state.mAttachedFrame == null) { - mTmpWindowBounds.set(0, 0, requestedWidth, requestedHeight); - } else { - mTmpWindowBounds.set(state.mAttachedFrame); - } + mLayout.computeFrames(attrs, null, null, null, WindowConfiguration.WINDOWING_MODE_UNDEFINED, + requestedWidth, requestedHeight, 0, 0, + frames); - mLayout.computeFrames(attrs, mTmpInsetsState, mTmpDisplayCutoutSafe, mTmpWindowBounds, - WindowConfiguration.WINDOWING_MODE_UNDEFINED, requestedWidth, requestedHeight, 0, - 1f, mTmpFrames); - - state.mFrame.set(mTmpFrames.frame); + state.mFrame.set(frames.frame); if (outFrames != null) { - outFrames.frame.set(mTmpFrames.frame); - outFrames.parentFrame.set(mTmpFrames.parentFrame); - outFrames.displayFrame.set(mTmpFrames.displayFrame); + outFrames.frame.set(frames.frame); + outFrames.parentFrame.set(frames.parentFrame); + outFrames.displayFrame.set(frames.displayFrame); } - t.setPosition(leash, mTmpFrames.frame.left, mTmpFrames.frame.top); - t.setWindowCrop(leash, mTmpFrames.frame.width(), mTmpFrames.frame.height()); + t.setPosition(leash, frames.frame.left, frames.frame.top); + t.setWindowCrop(leash, frames.frame.width(), frames.frame.height()); if (viewFlags == View.VISIBLE) { // TODO(b/262892794) ViewRootImpl modifies the app's rendering SurfaceControl