Merge "WindowlessWindowManager floating window support"
This commit is contained in:
committed by
Android (Google) Code Review
commit
776e0adcf3
@@ -16,13 +16,19 @@
|
||||
|
||||
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;
|
||||
|
||||
// TODO(b/262891212) use the real WindowLayout and remove WindowlessWindowLayout
|
||||
|
||||
/**
|
||||
* Computes window frames for the windowless window.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class WindowlessWindowLayout extends WindowLayout {
|
||||
@@ -32,9 +38,32 @@ public class WindowlessWindowLayout extends WindowLayout {
|
||||
Rect displayCutoutSafe, Rect windowBounds, @WindowingMode int windowingMode,
|
||||
int requestedWidth, int requestedHeight, @InsetsType int requestedVisibleTypes,
|
||||
float compatScale, ClientWindowFrames frames) {
|
||||
frames.frame.set(0, 0, attrs.width, attrs.height);
|
||||
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.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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.view;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
@@ -53,13 +54,21 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
IBinder mInputChannelToken;
|
||||
Region mInputRegion;
|
||||
IWindow mClient;
|
||||
State(SurfaceControl sc, WindowManager.LayoutParams p, int displayId,
|
||||
IBinder inputChannelToken, IWindow client) {
|
||||
SurfaceControl mLeash;
|
||||
Rect mFrame;
|
||||
Rect mAttachedFrame;
|
||||
|
||||
State(SurfaceControl sc, WindowManager.LayoutParams p,
|
||||
int displayId, IBinder inputChannelToken, IWindow client, SurfaceControl leash,
|
||||
Rect frame, Rect attachedFrame) {
|
||||
mSurfaceControl = sc;
|
||||
mParams.copyFrom(p);
|
||||
mDisplayId = displayId;
|
||||
mInputChannelToken = inputChannelToken;
|
||||
mClient = client;
|
||||
mLeash = leash;
|
||||
mFrame = frame;
|
||||
mAttachedFrame = attachedFrame;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -85,6 +94,7 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
private InsetsState mInsetsState;
|
||||
private final ClientWindowFrames mTmpFrames = new ClientWindowFrames();
|
||||
private final MergedConfiguration mTmpConfig = new MergedConfiguration();
|
||||
private final WindowlessWindowLayout mLayout = new WindowlessWindowLayout();
|
||||
|
||||
public WindowlessWindowManager(Configuration c, SurfaceControl rootSurface,
|
||||
IBinder hostInputToken) {
|
||||
@@ -137,8 +147,15 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
}
|
||||
}
|
||||
|
||||
protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
|
||||
b.setParent(mRootSurface);
|
||||
protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
|
||||
// If this is the first window, the state map is empty and the parent surface is the
|
||||
// root. Otherwise, the parent surface is in the state map.
|
||||
synchronized (this) {
|
||||
if (mStateForWindow.isEmpty()) {
|
||||
return mRootSurface;
|
||||
}
|
||||
return mStateForWindow.get(attrs.token).mLeash;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,13 +167,20 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
InputChannel outInputChannel, InsetsState outInsetsState,
|
||||
InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
|
||||
float[] outSizeCompatScale) {
|
||||
final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
|
||||
final SurfaceControl leash = new SurfaceControl.Builder(mSurfaceSession)
|
||||
.setName(attrs.getTitle().toString() + "Leash")
|
||||
.setCallsite("WindowlessWindowManager.addToDisplay")
|
||||
.setParent(getParentSurface(window, attrs))
|
||||
.build();
|
||||
|
||||
final SurfaceControl sc = new SurfaceControl.Builder(mSurfaceSession)
|
||||
.setFormat(attrs.format)
|
||||
.setBLASTLayer()
|
||||
.setName(attrs.getTitle().toString())
|
||||
.setCallsite("WindowlessWindowManager.addToDisplay");
|
||||
attachToParentSurface(window, b);
|
||||
final SurfaceControl sc = b.build();
|
||||
.setCallsite("WindowlessWindowManager.addToDisplay")
|
||||
.setHidden(false)
|
||||
.setParent(leash)
|
||||
.build();
|
||||
|
||||
if (((attrs.inputFeatures &
|
||||
WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0)) {
|
||||
@@ -178,11 +202,22 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
}
|
||||
|
||||
final State state = new State(sc, attrs, displayId,
|
||||
outInputChannel != null ? outInputChannel.getToken() : null, window);
|
||||
outInputChannel != null ? outInputChannel.getToken() : null, window,
|
||||
leash, /* frame= */ new Rect(), /* attachedFrame= */ null);
|
||||
Rect parentFrame = null;
|
||||
synchronized (this) {
|
||||
State parentState = mStateForWindow.get(attrs.token);
|
||||
if (parentState != null) {
|
||||
parentFrame = parentState.mFrame;
|
||||
}
|
||||
mStateForWindow.put(window.asBinder(), state);
|
||||
}
|
||||
outAttachedFrame.set(0, 0, -1, -1);
|
||||
state.mAttachedFrame = parentFrame;
|
||||
if (parentFrame == null) {
|
||||
outAttachedFrame.set(0, 0, -1, -1);
|
||||
} else {
|
||||
outAttachedFrame.set(parentFrame);
|
||||
}
|
||||
outSizeCompatScale[0] = 1f;
|
||||
|
||||
final int res = WindowManagerGlobal.ADD_OKAY | WindowManagerGlobal.ADD_FLAG_APP_VISIBLE |
|
||||
@@ -227,6 +262,7 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
"Invalid window token (never added or removed already)");
|
||||
}
|
||||
removeSurface(state.mSurfaceControl);
|
||||
removeSurface(state.mLeash);
|
||||
}
|
||||
|
||||
/** Separate from {@link #remove} so that subclasses can put removal on a sync transaction. */
|
||||
@@ -301,6 +337,7 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
"Invalid window token (never added or removed already)");
|
||||
}
|
||||
SurfaceControl sc = state.mSurfaceControl;
|
||||
SurfaceControl leash = state.mLeash;
|
||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
|
||||
int attrChanges = 0;
|
||||
@@ -309,21 +346,37 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
}
|
||||
WindowManager.LayoutParams attrs = state.mParams;
|
||||
|
||||
ClientWindowFrames frames = new ClientWindowFrames();
|
||||
frames.attachedFrame = state.mAttachedFrame;
|
||||
|
||||
mLayout.computeFrames(attrs, null, null, null, WindowConfiguration.WINDOWING_MODE_UNDEFINED,
|
||||
requestedWidth, requestedHeight, 0, 0,
|
||||
frames);
|
||||
|
||||
state.mFrame.set(frames.frame);
|
||||
if (outFrames != null) {
|
||||
outFrames.frame.set(frames.frame);
|
||||
outFrames.parentFrame.set(frames.parentFrame);
|
||||
outFrames.displayFrame.set(frames.displayFrame);
|
||||
}
|
||||
|
||||
t.setPosition(leash, frames.frame.left, frames.frame.top);
|
||||
t.setWindowCrop(leash, frames.frame.width(), frames.frame.height());
|
||||
|
||||
if (viewFlags == View.VISIBLE) {
|
||||
t.setOpaque(sc, isOpaque(attrs)).show(sc).apply();
|
||||
// TODO(b/262892794) ViewRootImpl modifies the app's rendering SurfaceControl
|
||||
// opaqueness. We shouldn't need to modify opaqueness for this SurfaceControl here or
|
||||
// in the real WindowManager.
|
||||
t.setOpaque(sc, isOpaque(attrs)).show(leash).apply();
|
||||
if (outSurfaceControl != null) {
|
||||
outSurfaceControl.copyFrom(sc, "WindowlessWindowManager.relayout");
|
||||
}
|
||||
} else {
|
||||
t.hide(sc).apply();
|
||||
t.hide(leash).apply();
|
||||
if (outSurfaceControl != null) {
|
||||
outSurfaceControl.release();
|
||||
}
|
||||
}
|
||||
if (outFrames != null) {
|
||||
outFrames.frame.set(0, 0, attrs.width, attrs.height);
|
||||
outFrames.displayFrame.set(outFrames.frame);
|
||||
}
|
||||
|
||||
if (outMergedConfiguration != null) {
|
||||
outMergedConfiguration.setConfiguration(mConfiguration, mConfiguration);
|
||||
|
||||
@@ -306,7 +306,9 @@ public class SystemWindows {
|
||||
}
|
||||
}
|
||||
|
||||
protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
|
||||
@Override
|
||||
protected SurfaceControl getParentSurface(IWindow window,
|
||||
WindowManager.LayoutParams attrs) {
|
||||
SurfaceControl leash = new SurfaceControl.Builder(new SurfaceSession())
|
||||
.setContainerLayer()
|
||||
.setName("SystemWindowLeash")
|
||||
@@ -316,7 +318,7 @@ public class SystemWindows {
|
||||
synchronized (this) {
|
||||
mLeashForWindow.put(window.asBinder(), leash);
|
||||
}
|
||||
b.setParent(leash);
|
||||
return leash;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -92,7 +92,7 @@ public class SplitDecorManager extends WindowlessWindowManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
|
||||
protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
|
||||
// Can't set position for the ViewRootImpl SC directly. Create a leash to manipulate later.
|
||||
final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
|
||||
.setContainerLayer()
|
||||
@@ -101,7 +101,7 @@ public class SplitDecorManager extends WindowlessWindowManager {
|
||||
.setParent(mHostLeash)
|
||||
.setCallsite("SplitDecorManager#attachToParentSurface");
|
||||
mIconLeash = builder.build();
|
||||
b.setParent(mIconLeash);
|
||||
return mIconLeash;
|
||||
}
|
||||
|
||||
/** Inflates split decor surface on the root surface. */
|
||||
|
||||
@@ -93,7 +93,7 @@ public final class SplitWindowManager extends WindowlessWindowManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
|
||||
protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
|
||||
// Can't set position for the ViewRootImpl SC directly. Create a leash to manipulate later.
|
||||
final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
|
||||
.setContainerLayer()
|
||||
@@ -103,7 +103,7 @@ public final class SplitWindowManager extends WindowlessWindowManager {
|
||||
mParentContainerCallbacks.attachToParentSurface(builder);
|
||||
mLeash = builder.build();
|
||||
mParentContainerCallbacks.onLeashReady(mLeash);
|
||||
b.setParent(mLeash);
|
||||
return mLeash;
|
||||
}
|
||||
|
||||
/** Inflates {@link DividerView} on to the root surface. */
|
||||
|
||||
@@ -155,7 +155,7 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
|
||||
protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
|
||||
String className = getClass().getSimpleName();
|
||||
final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
|
||||
.setContainerLayer()
|
||||
@@ -164,9 +164,8 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
|
||||
.setCallsite(className + "#attachToParentSurface");
|
||||
attachToParentSurface(builder);
|
||||
mLeash = builder.build();
|
||||
b.setParent(mLeash);
|
||||
|
||||
initSurface(mLeash);
|
||||
return mLeash;
|
||||
}
|
||||
|
||||
/** Inits the z-order of the surface. */
|
||||
|
||||
@@ -104,7 +104,7 @@ public final class BackgroundWindowManager extends WindowlessWindowManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
|
||||
protected SurfaceControl getParentSurface(IWindow window, WindowManager.LayoutParams attrs) {
|
||||
final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
|
||||
.setColorLayer()
|
||||
.setBufferSize(mDisplayBounds.width(), mDisplayBounds.height())
|
||||
@@ -113,7 +113,7 @@ public final class BackgroundWindowManager extends WindowlessWindowManager {
|
||||
.setName(TAG)
|
||||
.setCallsite("BackgroundWindowManager#attachToParentSurface");
|
||||
mLeash = builder.build();
|
||||
b.setParent(mLeash);
|
||||
return mLeash;
|
||||
}
|
||||
|
||||
/** Inflates background view on to the root surface. */
|
||||
|
||||
Reference in New Issue
Block a user