Loading core/java/android/view/PendingInsetsController.java 0 → 100644 +181 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 android.os.CancellationSignal; import android.view.WindowInsets.Type.InsetsType; import android.view.animation.Interpolator; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; /** * An insets controller that keeps track of pending requests. This is such that an app can freely * use {@link WindowInsetsController} before the view root is attached during activity startup. * @hide */ public class PendingInsetsController implements WindowInsetsController { private static final int KEEP_BEHAVIOR = -1; private final ArrayList<PendingRequest> mRequests = new ArrayList<>(); private @Appearance int mAppearance; private @Appearance int mAppearanceMask; private @Behavior int mBehavior = KEEP_BEHAVIOR; private final InsetsState mDummyState = new InsetsState(); private InsetsController mReplayedInsetsController; @Override public void show(int types) { if (mReplayedInsetsController != null) { mReplayedInsetsController.show(types); } else { mRequests.add(new ShowRequest(types)); } } @Override public void hide(int types) { if (mReplayedInsetsController != null) { mReplayedInsetsController.hide(types); } else { mRequests.add(new HideRequest(types)); } } @Override public CancellationSignal controlWindowInsetsAnimation(int types, long durationMillis, Interpolator interpolator, WindowInsetsAnimationControlListener listener) { if (mReplayedInsetsController != null) { return mReplayedInsetsController.controlWindowInsetsAnimation(types, durationMillis, interpolator, listener); } else { listener.onCancelled(); CancellationSignal cancellationSignal = new CancellationSignal(); cancellationSignal.cancel(); return cancellationSignal; } } @Override public void setSystemBarsAppearance(int appearance, int mask) { if (mReplayedInsetsController != null) { mReplayedInsetsController.setSystemBarsAppearance(appearance, mask); } else { mAppearance = (mAppearance & ~mask) | (appearance & mask); mAppearanceMask |= mask; } } @Override public int getSystemBarsAppearance() { if (mReplayedInsetsController != null) { return mReplayedInsetsController.getSystemBarsAppearance(); } return mAppearance; } @Override public void setSystemBarsBehavior(int behavior) { if (mReplayedInsetsController != null) { mReplayedInsetsController.setSystemBarsBehavior(behavior); } else { mBehavior = behavior; } } @Override public int getSystemBarsBehavior() { if (mReplayedInsetsController != null) { return mReplayedInsetsController.getSystemBarsBehavior(); } return mBehavior; } @Override public InsetsState getState() { return mDummyState; } /** * Replays the commands on {@code controller} and attaches it to this instance such that any * calls will be forwarded to the real instance in the future. */ @VisibleForTesting public void replayAndAttach(InsetsController controller) { if (mBehavior != KEEP_BEHAVIOR) { controller.setSystemBarsBehavior(mBehavior); } if (mAppearanceMask != 0) { controller.setSystemBarsAppearance(mAppearance, mAppearanceMask); } int size = mRequests.size(); for (int i = 0; i < size; i++) { mRequests.get(i).replay(controller); } // Reset all state so it doesn't get applied twice just in case mRequests.clear(); mBehavior = KEEP_BEHAVIOR; mAppearance = 0; mAppearanceMask = 0; // After replaying, we forward everything directly to the replayed instance. mReplayedInsetsController = controller; } /** * Detaches the controller to no longer forward calls to the real instance. */ @VisibleForTesting public void detach() { mReplayedInsetsController = null; } private interface PendingRequest { void replay(InsetsController controller); } private static class ShowRequest implements PendingRequest { private final @InsetsType int mTypes; public ShowRequest(int types) { mTypes = types; } @Override public void replay(InsetsController controller) { controller.show(mTypes); } } private static class HideRequest implements PendingRequest { private final @InsetsType int mTypes; public HideRequest(int types) { mTypes = types; } @Override public void replay(InsetsController controller) { controller.hide(mTypes); } } } core/java/android/view/View.java +6 −2 Original line number Diff line number Diff line Loading @@ -11415,14 +11415,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Retrieves the single {@link WindowInsetsController} of the window this view is attached to. * * @return The {@link WindowInsetsController} or {@code null} if the view isn't attached to a * a window. * @return The {@link WindowInsetsController} or {@code null} if the view is neither attached to * a window nor a view tree with a decor. * @see Window#getInsetsController() */ public @Nullable WindowInsetsController getWindowInsetsController() { if (mAttachInfo != null) { return mAttachInfo.mViewRootImpl.getInsetsController(); } ViewParent parent = getParent(); if (parent instanceof View) { return ((View) parent).getWindowInsetsController(); } return null; } core/java/android/view/ViewRootImpl.java +8 −0 Original line number Diff line number Diff line Loading @@ -1117,6 +1117,14 @@ public final class ViewRootImpl implements ViewParent, mFirstInputStage = nativePreImeStage; mFirstPostImeInputStage = earlyPostImeStage; mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix; if (mView instanceof RootViewSurfaceTaker) { PendingInsetsController pendingInsetsController = ((RootViewSurfaceTaker) mView).providePendingInsetsController(); if (pendingInsetsController != null) { pendingInsetsController.replayAndAttach(mInsetsController); } } } } } Loading core/java/com/android/internal/policy/DecorView.java +20 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.InputQueue; import android.view.InsetsState; import android.view.InsetsController; import android.view.InsetsState.InternalInsetsType; import android.view.KeyEvent; import android.view.KeyboardShortcutGroup; Loading @@ -85,6 +86,7 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.PendingInsetsController; import android.view.ThreadedRenderer; import android.view.View; import android.view.ViewGroup; Loading Loading @@ -286,6 +288,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind */ private boolean mUseNewInsetsApi; private PendingInsetsController mPendingInsetsController = new PendingInsetsController(); DecorView(Context context, int featureId, PhoneWindow window, WindowManager.LayoutParams params) { super(context); Loading Loading @@ -1780,6 +1784,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind getViewRootImpl().removeWindowCallbacks(this); mWindowResizeCallbacksAdded = false; } mPendingInsetsController.detach(); } @Override Loading Loading @@ -1819,6 +1825,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind updateColorViewTranslations(); } @Override public PendingInsetsController providePendingInsetsController() { return mPendingInsetsController; } private ActionMode createActionMode( int type, ActionMode.Callback2 callback, View originatingView) { switch (type) { Loading Loading @@ -2539,6 +2550,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind return AccessibilityNodeInfo.ROOT_ITEM_ID; } @Override public WindowInsetsController getWindowInsetsController() { if (isAttachedToWindow()) { return super.getWindowInsetsController(); } else { return mPendingInsetsController; } } @Override public String toString() { return "DecorView@" + Integer.toHexString(this.hashCode()) + "[" Loading core/java/com/android/internal/view/RootViewSurfaceTaker.java +4 −0 Original line number Diff line number Diff line Loading @@ -15,8 +15,11 @@ */ package com.android.internal.view; import android.annotation.Nullable; import android.view.InputQueue; import android.view.PendingInsetsController; import android.view.SurfaceHolder; import android.view.WindowInsetsController; /** hahahah */ public interface RootViewSurfaceTaker { Loading @@ -26,4 +29,5 @@ public interface RootViewSurfaceTaker { void setSurfaceKeepScreenOn(boolean keepOn); InputQueue.Callback willYouTakeTheInputQueue(); void onRootViewScrollYChanged(int scrollY); @Nullable PendingInsetsController providePendingInsetsController(); } Loading
core/java/android/view/PendingInsetsController.java 0 → 100644 +181 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 android.os.CancellationSignal; import android.view.WindowInsets.Type.InsetsType; import android.view.animation.Interpolator; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; /** * An insets controller that keeps track of pending requests. This is such that an app can freely * use {@link WindowInsetsController} before the view root is attached during activity startup. * @hide */ public class PendingInsetsController implements WindowInsetsController { private static final int KEEP_BEHAVIOR = -1; private final ArrayList<PendingRequest> mRequests = new ArrayList<>(); private @Appearance int mAppearance; private @Appearance int mAppearanceMask; private @Behavior int mBehavior = KEEP_BEHAVIOR; private final InsetsState mDummyState = new InsetsState(); private InsetsController mReplayedInsetsController; @Override public void show(int types) { if (mReplayedInsetsController != null) { mReplayedInsetsController.show(types); } else { mRequests.add(new ShowRequest(types)); } } @Override public void hide(int types) { if (mReplayedInsetsController != null) { mReplayedInsetsController.hide(types); } else { mRequests.add(new HideRequest(types)); } } @Override public CancellationSignal controlWindowInsetsAnimation(int types, long durationMillis, Interpolator interpolator, WindowInsetsAnimationControlListener listener) { if (mReplayedInsetsController != null) { return mReplayedInsetsController.controlWindowInsetsAnimation(types, durationMillis, interpolator, listener); } else { listener.onCancelled(); CancellationSignal cancellationSignal = new CancellationSignal(); cancellationSignal.cancel(); return cancellationSignal; } } @Override public void setSystemBarsAppearance(int appearance, int mask) { if (mReplayedInsetsController != null) { mReplayedInsetsController.setSystemBarsAppearance(appearance, mask); } else { mAppearance = (mAppearance & ~mask) | (appearance & mask); mAppearanceMask |= mask; } } @Override public int getSystemBarsAppearance() { if (mReplayedInsetsController != null) { return mReplayedInsetsController.getSystemBarsAppearance(); } return mAppearance; } @Override public void setSystemBarsBehavior(int behavior) { if (mReplayedInsetsController != null) { mReplayedInsetsController.setSystemBarsBehavior(behavior); } else { mBehavior = behavior; } } @Override public int getSystemBarsBehavior() { if (mReplayedInsetsController != null) { return mReplayedInsetsController.getSystemBarsBehavior(); } return mBehavior; } @Override public InsetsState getState() { return mDummyState; } /** * Replays the commands on {@code controller} and attaches it to this instance such that any * calls will be forwarded to the real instance in the future. */ @VisibleForTesting public void replayAndAttach(InsetsController controller) { if (mBehavior != KEEP_BEHAVIOR) { controller.setSystemBarsBehavior(mBehavior); } if (mAppearanceMask != 0) { controller.setSystemBarsAppearance(mAppearance, mAppearanceMask); } int size = mRequests.size(); for (int i = 0; i < size; i++) { mRequests.get(i).replay(controller); } // Reset all state so it doesn't get applied twice just in case mRequests.clear(); mBehavior = KEEP_BEHAVIOR; mAppearance = 0; mAppearanceMask = 0; // After replaying, we forward everything directly to the replayed instance. mReplayedInsetsController = controller; } /** * Detaches the controller to no longer forward calls to the real instance. */ @VisibleForTesting public void detach() { mReplayedInsetsController = null; } private interface PendingRequest { void replay(InsetsController controller); } private static class ShowRequest implements PendingRequest { private final @InsetsType int mTypes; public ShowRequest(int types) { mTypes = types; } @Override public void replay(InsetsController controller) { controller.show(mTypes); } } private static class HideRequest implements PendingRequest { private final @InsetsType int mTypes; public HideRequest(int types) { mTypes = types; } @Override public void replay(InsetsController controller) { controller.hide(mTypes); } } }
core/java/android/view/View.java +6 −2 Original line number Diff line number Diff line Loading @@ -11415,14 +11415,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Retrieves the single {@link WindowInsetsController} of the window this view is attached to. * * @return The {@link WindowInsetsController} or {@code null} if the view isn't attached to a * a window. * @return The {@link WindowInsetsController} or {@code null} if the view is neither attached to * a window nor a view tree with a decor. * @see Window#getInsetsController() */ public @Nullable WindowInsetsController getWindowInsetsController() { if (mAttachInfo != null) { return mAttachInfo.mViewRootImpl.getInsetsController(); } ViewParent parent = getParent(); if (parent instanceof View) { return ((View) parent).getWindowInsetsController(); } return null; }
core/java/android/view/ViewRootImpl.java +8 −0 Original line number Diff line number Diff line Loading @@ -1117,6 +1117,14 @@ public final class ViewRootImpl implements ViewParent, mFirstInputStage = nativePreImeStage; mFirstPostImeInputStage = earlyPostImeStage; mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix; if (mView instanceof RootViewSurfaceTaker) { PendingInsetsController pendingInsetsController = ((RootViewSurfaceTaker) mView).providePendingInsetsController(); if (pendingInsetsController != null) { pendingInsetsController.replayAndAttach(mInsetsController); } } } } } Loading
core/java/com/android/internal/policy/DecorView.java +20 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.InputQueue; import android.view.InsetsState; import android.view.InsetsController; import android.view.InsetsState.InternalInsetsType; import android.view.KeyEvent; import android.view.KeyboardShortcutGroup; Loading @@ -85,6 +86,7 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.PendingInsetsController; import android.view.ThreadedRenderer; import android.view.View; import android.view.ViewGroup; Loading Loading @@ -286,6 +288,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind */ private boolean mUseNewInsetsApi; private PendingInsetsController mPendingInsetsController = new PendingInsetsController(); DecorView(Context context, int featureId, PhoneWindow window, WindowManager.LayoutParams params) { super(context); Loading Loading @@ -1780,6 +1784,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind getViewRootImpl().removeWindowCallbacks(this); mWindowResizeCallbacksAdded = false; } mPendingInsetsController.detach(); } @Override Loading Loading @@ -1819,6 +1825,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind updateColorViewTranslations(); } @Override public PendingInsetsController providePendingInsetsController() { return mPendingInsetsController; } private ActionMode createActionMode( int type, ActionMode.Callback2 callback, View originatingView) { switch (type) { Loading Loading @@ -2539,6 +2550,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind return AccessibilityNodeInfo.ROOT_ITEM_ID; } @Override public WindowInsetsController getWindowInsetsController() { if (isAttachedToWindow()) { return super.getWindowInsetsController(); } else { return mPendingInsetsController; } } @Override public String toString() { return "DecorView@" + Integer.toHexString(this.hashCode()) + "[" Loading
core/java/com/android/internal/view/RootViewSurfaceTaker.java +4 −0 Original line number Diff line number Diff line Loading @@ -15,8 +15,11 @@ */ package com.android.internal.view; import android.annotation.Nullable; import android.view.InputQueue; import android.view.PendingInsetsController; import android.view.SurfaceHolder; import android.view.WindowInsetsController; /** hahahah */ public interface RootViewSurfaceTaker { Loading @@ -26,4 +29,5 @@ public interface RootViewSurfaceTaker { void setSurfaceKeepScreenOn(boolean keepOn); InputQueue.Callback willYouTakeTheInputQueue(); void onRootViewScrollYChanged(int scrollY); @Nullable PendingInsetsController providePendingInsetsController(); }