Merge "Make caption a insets source" into rvc-dev
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package android.view;
|
package android.view;
|
||||||
|
|
||||||
|
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
|
||||||
import static android.view.InsetsState.ITYPE_IME;
|
import static android.view.InsetsState.ITYPE_IME;
|
||||||
import static android.view.InsetsState.toInternalType;
|
import static android.view.InsetsState.toInternalType;
|
||||||
import static android.view.InsetsState.toPublicType;
|
import static android.view.InsetsState.toPublicType;
|
||||||
@@ -367,6 +368,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
private int mLastLegacySystemUiFlags;
|
private int mLastLegacySystemUiFlags;
|
||||||
private DisplayCutout mLastDisplayCutout;
|
private DisplayCutout mLastDisplayCutout;
|
||||||
private boolean mStartingAnimation;
|
private boolean mStartingAnimation;
|
||||||
|
private int mCaptionInsetsHeight = 0;
|
||||||
|
|
||||||
private SyncRtSurfaceTransactionApplier mApplier;
|
private SyncRtSurfaceTransactionApplier mApplier;
|
||||||
|
|
||||||
@@ -460,7 +462,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public boolean onStateChanged(InsetsState state) {
|
public boolean onStateChanged(InsetsState state) {
|
||||||
boolean localStateChanged = !mState.equals(state);
|
boolean localStateChanged = !mState.equals(state, true /* excludingCaptionInsets */)
|
||||||
|
|| !captionInsetsUnchanged();
|
||||||
if (!localStateChanged && mLastDispachedState.equals(state)) {
|
if (!localStateChanged && mLastDispachedState.equals(state)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -470,7 +473,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
if (localStateChanged) {
|
if (localStateChanged) {
|
||||||
mViewRoot.notifyInsetsChanged();
|
mViewRoot.notifyInsetsChanged();
|
||||||
}
|
}
|
||||||
if (!mState.equals(mLastDispachedState)) {
|
if (!mState.equals(mLastDispachedState, true /* excludingCaptionInsets */)) {
|
||||||
sendStateToWindowManager();
|
sendStateToWindowManager();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -488,6 +491,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
mState.removeSource(source.getType());
|
mState.removeSource(source.getType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mCaptionInsetsHeight != 0) {
|
||||||
|
mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top,
|
||||||
|
mFrame.right, mFrame.top + mCaptionInsetsHeight));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean captionInsetsUnchanged() {
|
||||||
|
if (mState.peekSource(ITYPE_CAPTION_BAR) == null
|
||||||
|
&& mCaptionInsetsHeight == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (mState.peekSource(ITYPE_CAPTION_BAR) != null
|
||||||
|
&& mCaptionInsetsHeight
|
||||||
|
== mState.peekSource(ITYPE_CAPTION_BAR).getFrame().height()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -964,6 +984,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
InsetsState tmpState = new InsetsState();
|
InsetsState tmpState = new InsetsState();
|
||||||
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
|
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
|
||||||
final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
|
final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
|
||||||
|
if (consumer.getType() == ITYPE_CAPTION_BAR) continue;
|
||||||
if (consumer.getControl() != null) {
|
if (consumer.getControl() != null) {
|
||||||
tmpState.addSource(mState.getSource(consumer.getType()));
|
tmpState.addSource(mState.getSource(consumer.getType()));
|
||||||
}
|
}
|
||||||
@@ -1104,6 +1125,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
|||||||
return mViewRoot.mWindowAttributes.insetsFlags.appearance;
|
return mViewRoot.mWindowAttributes.insetsFlags.appearance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCaptionInsetsHeight(int height) {
|
||||||
|
mCaptionInsetsHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSystemBarsBehavior(@Behavior int behavior) {
|
public void setSystemBarsBehavior(@Behavior int behavior) {
|
||||||
mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
|
mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package android.view;
|
package android.view;
|
||||||
|
|
||||||
|
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
|
||||||
import static android.view.InsetsState.ITYPE_IME;
|
import static android.view.InsetsState.ITYPE_IME;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
@@ -118,6 +119,12 @@ public class InsetsSource implements Parcelable {
|
|||||||
if (!getIntersection(frame, relativeFrame, mTmpFrame)) {
|
if (!getIntersection(frame, relativeFrame, mTmpFrame)) {
|
||||||
return Insets.NONE;
|
return Insets.NONE;
|
||||||
}
|
}
|
||||||
|
// During drag-move and drag-resizing, the caption insets position may not get updated
|
||||||
|
// before the app frame get updated. To layout the app content correctly during drag events,
|
||||||
|
// we always return the insets with the corresponding height covering the top.
|
||||||
|
if (getType() == ITYPE_CAPTION_BAR) {
|
||||||
|
return Insets.of(0, frame.height(), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Currently, non-floating IME always intersects at bottom due to issues with cutout.
|
// TODO: Currently, non-floating IME always intersects at bottom due to issues with cutout.
|
||||||
// However, we should let the policy decide from the server.
|
// However, we should let the policy decide from the server.
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ import android.view.WindowInsets.Type;
|
|||||||
import android.view.WindowInsets.Type.InsetsType;
|
import android.view.WindowInsets.Type.InsetsType;
|
||||||
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
|
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
@@ -498,6 +500,19 @@ public class InsetsState implements Parcelable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
|
return equals(o, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An equals method can exclude the caption insets. This is useful because we assemble the
|
||||||
|
* caption insets information on the client side, and when we communicate with server, it's
|
||||||
|
* excluded.
|
||||||
|
* @param excludingCaptionInsets {@code true} if we want to compare two InsetsState objects but
|
||||||
|
* ignore the caption insets source value.
|
||||||
|
* @return {@code true} if the two InsetsState objects are equal, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public boolean equals(Object o, boolean excludingCaptionInsets) {
|
||||||
if (this == o) { return true; }
|
if (this == o) { return true; }
|
||||||
if (o == null || getClass() != o.getClass()) { return false; }
|
if (o == null || getClass() != o.getClass()) { return false; }
|
||||||
|
|
||||||
@@ -506,11 +521,24 @@ public class InsetsState implements Parcelable {
|
|||||||
if (!mDisplayFrame.equals(state.mDisplayFrame)) {
|
if (!mDisplayFrame.equals(state.mDisplayFrame)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (mSources.size() != state.mSources.size()) {
|
int size = mSources.size();
|
||||||
|
int otherSize = state.mSources.size();
|
||||||
|
if (excludingCaptionInsets) {
|
||||||
|
if (mSources.get(ITYPE_CAPTION_BAR) != null) {
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
if (state.mSources.get(ITYPE_CAPTION_BAR) != null) {
|
||||||
|
otherSize--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (size != otherSize) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (int i = mSources.size() - 1; i >= 0; i--) {
|
for (int i = mSources.size() - 1; i >= 0; i--) {
|
||||||
InsetsSource source = mSources.valueAt(i);
|
InsetsSource source = mSources.valueAt(i);
|
||||||
|
if (excludingCaptionInsets) {
|
||||||
|
if (source.getType() == ITYPE_CAPTION_BAR) continue;
|
||||||
|
}
|
||||||
InsetsSource otherSource = state.mSources.get(source.getType());
|
InsetsSource otherSource = state.mSources.get(source.getType());
|
||||||
if (otherSource == null) {
|
if (otherSource == null) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public class PendingInsetsController implements WindowInsetsController {
|
|||||||
private InsetsController mReplayedInsetsController;
|
private InsetsController mReplayedInsetsController;
|
||||||
private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
|
private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
|
||||||
= new ArrayList<>();
|
= new ArrayList<>();
|
||||||
|
private int mCaptionInsetsHeight = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void show(int types) {
|
public void show(int types) {
|
||||||
@@ -79,6 +80,11 @@ public class PendingInsetsController implements WindowInsetsController {
|
|||||||
return mAppearance;
|
return mAppearance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCaptionInsetsHeight(int height) {
|
||||||
|
mCaptionInsetsHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSystemBarsBehavior(int behavior) {
|
public void setSystemBarsBehavior(int behavior) {
|
||||||
if (mReplayedInsetsController != null) {
|
if (mReplayedInsetsController != null) {
|
||||||
@@ -134,6 +140,9 @@ public class PendingInsetsController implements WindowInsetsController {
|
|||||||
if (mAppearanceMask != 0) {
|
if (mAppearanceMask != 0) {
|
||||||
controller.setSystemBarsAppearance(mAppearance, mAppearanceMask);
|
controller.setSystemBarsAppearance(mAppearance, mAppearanceMask);
|
||||||
}
|
}
|
||||||
|
if (mCaptionInsetsHeight != 0) {
|
||||||
|
controller.setCaptionInsetsHeight(mCaptionInsetsHeight);
|
||||||
|
}
|
||||||
int size = mRequests.size();
|
int size = mRequests.size();
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
mRequests.get(i).replay(controller);
|
mRequests.get(i).replay(controller);
|
||||||
|
|||||||
@@ -28768,6 +28768,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
|
|||||||
publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
|
publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
|
||||||
final Rect mStableInsets = new Rect();
|
final Rect mStableInsets = new Rect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current caption insets to the display coordinate.
|
||||||
|
*/
|
||||||
|
final Rect mCaptionInsets = new Rect();
|
||||||
|
|
||||||
final DisplayCutout.ParcelableWrapper mDisplayCutout =
|
final DisplayCutout.ParcelableWrapper mDisplayCutout =
|
||||||
new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
|
new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
|
||||||
|
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ import com.android.internal.annotations.GuardedBy;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.os.IResultReceiver;
|
import com.android.internal.os.IResultReceiver;
|
||||||
import com.android.internal.os.SomeArgs;
|
import com.android.internal.os.SomeArgs;
|
||||||
|
import com.android.internal.policy.DecorView;
|
||||||
import com.android.internal.policy.PhoneFallbackEventHandler;
|
import com.android.internal.policy.PhoneFallbackEventHandler;
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.internal.view.BaseSurfaceHolder;
|
import com.android.internal.view.BaseSurfaceHolder;
|
||||||
@@ -2221,6 +2222,19 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
|
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean updateCaptionInsets() {
|
||||||
|
if (!(mView instanceof DecorView)) return false;
|
||||||
|
final int captionInsetsHeight = ((DecorView) mView).getCaptionInsetsHeight();
|
||||||
|
final Rect captionFrame = new Rect();
|
||||||
|
if (captionInsetsHeight != 0) {
|
||||||
|
captionFrame.set(mWinFrame.left, mWinFrame.top, mWinFrame.right,
|
||||||
|
mWinFrame.top + captionInsetsHeight);
|
||||||
|
}
|
||||||
|
if (mAttachInfo.mCaptionInsets.equals(captionFrame)) return false;
|
||||||
|
mAttachInfo.mCaptionInsets.set(captionFrame);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean shouldDispatchCutout() {
|
private boolean shouldDispatchCutout() {
|
||||||
return mWindowAttributes.layoutInDisplayCutoutMode
|
return mWindowAttributes.layoutInDisplayCutoutMode
|
||||||
== LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
|
== LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
|
||||||
@@ -2592,6 +2606,9 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
mAttachInfo.mAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars;
|
mAttachInfo.mAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars;
|
||||||
dispatchApplyInsets = true;
|
dispatchApplyInsets = true;
|
||||||
}
|
}
|
||||||
|
if (updateCaptionInsets()) {
|
||||||
|
dispatchApplyInsets = true;
|
||||||
|
}
|
||||||
if (dispatchApplyInsets || mLastSystemUiVisibility !=
|
if (dispatchApplyInsets || mLastSystemUiVisibility !=
|
||||||
mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested) {
|
mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested) {
|
||||||
mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
|
mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
|
||||||
|
|||||||
@@ -49,9 +49,6 @@ import android.transition.Transition;
|
|||||||
import android.transition.TransitionManager;
|
import android.transition.TransitionManager;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.View.OnApplyWindowInsetsListener;
|
import android.view.View.OnApplyWindowInsetsListener;
|
||||||
import android.view.ViewGroup.LayoutParams;
|
|
||||||
import android.view.WindowInsets.Side.InsetsSide;
|
|
||||||
import android.view.WindowInsets.Type.InsetsType;
|
|
||||||
import android.view.accessibility.AccessibilityEvent;
|
import android.view.accessibility.AccessibilityEvent;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -323,7 +320,7 @@ public abstract class Window {
|
|||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
private boolean mDestroyed;
|
private boolean mDestroyed;
|
||||||
|
|
||||||
private boolean mOverlayWithDecorCaptionEnabled = false;
|
private boolean mOverlayWithDecorCaptionEnabled = true;
|
||||||
private boolean mCloseOnSwipeEnabled = false;
|
private boolean mCloseOnSwipeEnabled = false;
|
||||||
|
|
||||||
// The current window attributes.
|
// The current window attributes.
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package android.view;
|
package android.view;
|
||||||
|
|
||||||
|
import static android.view.WindowInsets.Type.CAPTION_BAR;
|
||||||
import static android.view.WindowInsets.Type.DISPLAY_CUTOUT;
|
import static android.view.WindowInsets.Type.DISPLAY_CUTOUT;
|
||||||
import static android.view.WindowInsets.Type.FIRST;
|
import static android.view.WindowInsets.Type.FIRST;
|
||||||
import static android.view.WindowInsets.Type.IME;
|
import static android.view.WindowInsets.Type.IME;
|
||||||
|
|||||||
@@ -195,6 +195,15 @@ public interface WindowInsetsController {
|
|||||||
*/
|
*/
|
||||||
@Appearance int getSystemBarsAppearance();
|
@Appearance int getSystemBarsAppearance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the caption insets height change. The information will be used on the client side to,
|
||||||
|
* make sure the InsetsState has the correct caption insets.
|
||||||
|
*
|
||||||
|
* @param height the height of caption bar insets.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
void setCaptionInsetsHeight(int height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls the behavior of system bars.
|
* Controls the behavior of system bars.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ import android.view.ContextThemeWrapper;
|
|||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.InputQueue;
|
import android.view.InputQueue;
|
||||||
import android.view.InsetsState;
|
import android.view.InsetsState;
|
||||||
import android.view.InsetsController;
|
|
||||||
import android.view.InsetsState.InternalInsetsType;
|
import android.view.InsetsState.InternalInsetsType;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.KeyboardShortcutGroup;
|
import android.view.KeyboardShortcutGroup;
|
||||||
@@ -1174,6 +1173,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset,
|
false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset,
|
||||||
animate && !disallowAnimate,
|
animate && !disallowAnimate,
|
||||||
mForceWindowDrawsBarBackgrounds, state);
|
mForceWindowDrawsBarBackgrounds, state);
|
||||||
|
|
||||||
|
if (mHasCaption) {
|
||||||
|
final int captionColor = calculateStatusBarColor();
|
||||||
|
mDecorCaptionView.getCaption().setBackgroundColor(captionColor);
|
||||||
|
updateDecorCaptionShade();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS or
|
// When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS or
|
||||||
@@ -1355,7 +1360,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
: state.attributes.isPresent(insetsState, mWindow.getAttributes().flags, force);
|
: state.attributes.isPresent(insetsState, mWindow.getAttributes().flags, force);
|
||||||
boolean show = state.attributes.isVisible(state.present, color,
|
boolean show = state.attributes.isVisible(state.present, color,
|
||||||
mWindow.getAttributes().flags, force);
|
mWindow.getAttributes().flags, force);
|
||||||
boolean showView = show && !isResizing() && size > 0;
|
boolean showView = show && !isResizing() && !mHasCaption && size > 0;
|
||||||
|
|
||||||
boolean visibilityChanged = false;
|
boolean visibilityChanged = false;
|
||||||
View view = state.view;
|
View view = state.view;
|
||||||
@@ -2021,6 +2026,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
if (getForeground() != null) {
|
if (getForeground() != null) {
|
||||||
drawableChanged();
|
drawableChanged();
|
||||||
}
|
}
|
||||||
|
getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2094,6 +2100,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
mDecorCaptionView.onConfigurationChanged(displayWindowDecor);
|
mDecorCaptionView.onConfigurationChanged(displayWindowDecor);
|
||||||
enableCaption(displayWindowDecor);
|
enableCaption(displayWindowDecor);
|
||||||
}
|
}
|
||||||
|
getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
|
void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
|
||||||
@@ -2182,11 +2189,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
inflater = inflater.from(context);
|
inflater = inflater.from(context);
|
||||||
final DecorCaptionView view = (DecorCaptionView) inflater.inflate(R.layout.decor_caption,
|
final DecorCaptionView view = (DecorCaptionView) inflater.inflate(R.layout.decor_caption,
|
||||||
null);
|
null);
|
||||||
setDecorCaptionShade(context, view);
|
setDecorCaptionShade(view);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setDecorCaptionShade(Context context, DecorCaptionView view) {
|
private void setDecorCaptionShade(DecorCaptionView view) {
|
||||||
final int shade = mWindow.getDecorCaptionShade();
|
final int shade = mWindow.getDecorCaptionShade();
|
||||||
switch (shade) {
|
switch (shade) {
|
||||||
case DECOR_CAPTION_SHADE_LIGHT:
|
case DECOR_CAPTION_SHADE_LIGHT:
|
||||||
@@ -2196,15 +2203,10 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
setDarkDecorCaptionShade(view);
|
setDarkDecorCaptionShade(view);
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
TypedValue value = new TypedValue();
|
if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0) {
|
||||||
context.getTheme().resolveAttribute(R.attr.colorPrimary, value, true);
|
|
||||||
// We invert the shade depending on brightness of the theme. Dark shade for light
|
|
||||||
// theme and vice versa. Thanks to this the buttons should be visible on the
|
|
||||||
// background.
|
|
||||||
if (Color.luminance(value.data) < 0.5) {
|
|
||||||
setLightDecorCaptionShade(view);
|
|
||||||
} else {
|
|
||||||
setDarkDecorCaptionShade(view);
|
setDarkDecorCaptionShade(view);
|
||||||
|
} else {
|
||||||
|
setLightDecorCaptionShade(view);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2213,7 +2215,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
|
|
||||||
void updateDecorCaptionShade() {
|
void updateDecorCaptionShade() {
|
||||||
if (mDecorCaptionView != null) {
|
if (mDecorCaptionView != null) {
|
||||||
setDecorCaptionShade(getContext(), mDecorCaptionView);
|
setDecorCaptionShade(mDecorCaptionView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2483,6 +2485,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
return isShowingCaption() ? mDecorCaptionView.getCaptionHeight() : 0;
|
return isShowingCaption() ? mDecorCaptionView.getCaptionHeight() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
* @return the height of insets covering the top of window content area.
|
||||||
|
*/
|
||||||
|
public int getCaptionInsetsHeight() {
|
||||||
|
if (!mWindow.isOverlayWithDecorCaptionEnabled()) return 0;
|
||||||
|
return getCaptionHeight();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a DIP measure into physical pixels.
|
* Converts a DIP measure into physical pixels.
|
||||||
* @param dip The dip value.
|
* @param dip The dip value.
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.android.internal.widget;
|
package com.android.internal.widget;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@@ -53,8 +52,7 @@ import java.util.ArrayList;
|
|||||||
* <li>..</li>
|
* <li>..</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* Although this ViewGroup has only two direct sub-Views, its behavior is more complex due to
|
* Here describe the behavior of overlaying caption on the content and drawing.
|
||||||
* overlaying caption on the content and drawing.
|
|
||||||
*
|
*
|
||||||
* First, no matter where the content View gets added, it will always be the first child and the
|
* First, no matter where the content View gets added, it will always be the first child and the
|
||||||
* caption will be the second. This way the caption will always be drawn on top of the content when
|
* caption will be the second. This way the caption will always be drawn on top of the content when
|
||||||
@@ -66,11 +64,9 @@ import java.util.ArrayList;
|
|||||||
* <li>DecorCaptionView.onInterceptTouchEvent() will try intercepting the touch events if the
|
* <li>DecorCaptionView.onInterceptTouchEvent() will try intercepting the touch events if the
|
||||||
* down action is performed on top close or maximize buttons; the reason for that is we want these
|
* down action is performed on top close or maximize buttons; the reason for that is we want these
|
||||||
* buttons to always work.</li>
|
* buttons to always work.</li>
|
||||||
* <li>The content View will receive the touch event. Mind that content is actually underneath the
|
* <li>The caption view will try to consume the event to apply the dragging logic.</li>
|
||||||
* caption, so we need to introduce our own dispatch ordering. We achieve this by overriding
|
* <li>If the touch event is not consumed by the caption, the content View will receive the touch
|
||||||
* {@link #buildTouchDispatchChildList()}.</li>
|
* event</li>
|
||||||
* <li>If the touch event is not consumed by the content View, it will go to the caption View
|
|
||||||
* and the dragging logic will be executed.</li>
|
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
|
public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
|
||||||
@@ -137,11 +133,6 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
|
|||||||
mOwner = owner;
|
mOwner = owner;
|
||||||
mShow = show;
|
mShow = show;
|
||||||
mOverlayWithAppContent = owner.isOverlayWithDecorCaptionEnabled();
|
mOverlayWithAppContent = owner.isOverlayWithDecorCaptionEnabled();
|
||||||
if (mOverlayWithAppContent) {
|
|
||||||
// The caption is covering the content, so we make its background transparent to make
|
|
||||||
// the content visible.
|
|
||||||
mCaption.setBackgroundColor(Color.TRANSPARENT);
|
|
||||||
}
|
|
||||||
updateCaptionVisibility();
|
updateCaptionVisibility();
|
||||||
// By changing the outline provider to BOUNDS, the window can remove its
|
// By changing the outline provider to BOUNDS, the window can remove its
|
||||||
// background without removing the shadow.
|
// background without removing the shadow.
|
||||||
@@ -235,18 +226,6 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
|
|||||||
return mDragging || mCheckForDragging;
|
return mDragging || mCheckForDragging;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ArrayList<View> buildTouchDispatchChildList() {
|
|
||||||
mTouchDispatchList.ensureCapacity(3);
|
|
||||||
if (mCaption != null) {
|
|
||||||
mTouchDispatchList.add(mCaption);
|
|
||||||
}
|
|
||||||
if (mContent != null) {
|
|
||||||
mTouchDispatchList.add(mContent);
|
|
||||||
}
|
|
||||||
return mTouchDispatchList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldDelayChildPressedState() {
|
public boolean shouldDelayChildPressedState() {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import static android.view.InsetsController.ANIMATION_TYPE_NONE;
|
|||||||
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
|
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
|
||||||
import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED;
|
import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED;
|
||||||
import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
|
import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
|
||||||
|
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
|
||||||
import static android.view.InsetsState.ITYPE_IME;
|
import static android.view.InsetsState.ITYPE_IME;
|
||||||
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||||
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
||||||
@@ -88,7 +89,6 @@ import java.util.concurrent.CountDownLatch;
|
|||||||
@Presubmit
|
@Presubmit
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class InsetsControllerTest {
|
public class InsetsControllerTest {
|
||||||
|
|
||||||
private InsetsController mController;
|
private InsetsController mController;
|
||||||
private SurfaceSession mSession = new SurfaceSession();
|
private SurfaceSession mSession = new SurfaceSession();
|
||||||
private SurfaceControl mLeash;
|
private SurfaceControl mLeash;
|
||||||
@@ -665,6 +665,26 @@ public class InsetsControllerTest {
|
|||||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCaptionInsetsStateAssemble() {
|
||||||
|
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
|
||||||
|
mController.onFrameChanged(new Rect(0, 0, 100, 300));
|
||||||
|
final InsetsState state = new InsetsState(mController.getState(), true);
|
||||||
|
final Rect captionFrame = new Rect(0, 0, 100, 100);
|
||||||
|
mController.setCaptionInsetsHeight(100);
|
||||||
|
mController.onStateChanged(state);
|
||||||
|
final InsetsState currentState = new InsetsState(mController.getState());
|
||||||
|
// The caption bar source should be synced with the info in mAttachInfo.
|
||||||
|
assertEquals(captionFrame, currentState.peekSource(ITYPE_CAPTION_BAR).getFrame());
|
||||||
|
assertTrue(currentState.equals(state, true /* excludingCaptionInsets*/));
|
||||||
|
mController.setCaptionInsetsHeight(0);
|
||||||
|
mController.onStateChanged(state);
|
||||||
|
// The caption bar source should not be there at all, because we don't add empty
|
||||||
|
// caption to the state from the server.
|
||||||
|
assertNull(mController.getState().peekSource(ITYPE_CAPTION_BAR));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void waitUntilNextFrame() throws Exception {
|
private void waitUntilNextFrame() throws Exception {
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
|
Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
|
||||||
|
|||||||
@@ -153,6 +153,35 @@ public class InsetsStateTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCalculateInsets_captionStatusBarOverlap() throws Exception {
|
||||||
|
try (InsetsModeSession session =
|
||||||
|
new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
|
||||||
|
mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
|
||||||
|
mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
|
||||||
|
mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
|
||||||
|
mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
|
||||||
|
|
||||||
|
Rect visibleInsets = mState.calculateVisibleInsets(
|
||||||
|
new Rect(0, 0, 100, 400), SOFT_INPUT_ADJUST_NOTHING);
|
||||||
|
assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCalculateInsets_captionBarOffset() throws Exception {
|
||||||
|
try (InsetsModeSession session =
|
||||||
|
new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
|
||||||
|
mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
|
||||||
|
mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
|
||||||
|
|
||||||
|
Rect visibleInsets = mState.calculateVisibleInsets(
|
||||||
|
new Rect(0, 0, 150, 400), SOFT_INPUT_ADJUST_NOTHING);
|
||||||
|
assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStripForDispatch() {
|
public void testStripForDispatch() {
|
||||||
mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
|
mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
|
||||||
|
|||||||
Reference in New Issue
Block a user