Loading core/java/android/inputmethodservice/InputMethodService.java +16 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.inputmethodservice; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; import static java.lang.annotation.RetentionPolicy.SOURCE; Loading Loading @@ -62,6 +63,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewRootImpl; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; Loading Loading @@ -595,12 +597,12 @@ public class InputMethodService extends AbstractInputMethodService { if (DEBUG) Log.v(TAG, "hideSoftInput()"); final boolean wasVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); applyVisibilityInInsetsConsumerIfNecessary(false /* setVisible */); if (mIsPreRendered) { if (DEBUG) { Log.v(TAG, "Making IME window invisible"); } setImeWindowStatus(IME_ACTIVE | IME_INVISIBLE, mBackDisposition); applyVisibilityInInsetsConsumer(false /* setVisible */); onPreRenderedWindowVisibilityChanged(false /* setVisible */); } else { mShowInputFlags = 0; Loading Loading @@ -632,11 +634,11 @@ public class InputMethodService extends AbstractInputMethodService { if (DEBUG) { Log.v(TAG, "Making IME window visible"); } applyVisibilityInInsetsConsumer(true /* setVisible */); onPreRenderedWindowVisibilityChanged(true /* setVisible */); } else { showWindow(true); } applyVisibilityInInsetsConsumerIfNecessary(true /* setVisible */); } // If user uses hard keyboard, IME button should always be shown. setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition); Loading Loading @@ -1974,16 +1976,20 @@ public class InputMethodService extends AbstractInputMethodService { /** * Apply the IME visibility in {@link android.view.ImeInsetsSourceConsumer} when * pre-rendering is enabled. * {@link ViewRootImpl.sNewInsetsMode} is enabled. * @param setVisible {@code true} to make it visible, false to hide it. */ private void applyVisibilityInInsetsConsumer(boolean setVisible) { if (!mIsPreRendered) { private void applyVisibilityInInsetsConsumerIfNecessary(boolean setVisible) { if (!isVisibilityAppliedUsingInsetsConsumer()) { return; } mPrivOps.applyImeVisibility(setVisible); } private boolean isVisibilityAppliedUsingInsetsConsumer() { return ViewRootImpl.sNewInsetsMode > NEW_INSETS_MODE_NONE; } private void finishViews(boolean finishingInput) { if (mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInputView"); Loading @@ -2007,7 +2013,11 @@ public class InputMethodService extends AbstractInputMethodService { mWindowVisible = false; finishViews(false /* finishingInput */); if (mDecorViewVisible) { // When insets API is enabled, it is responsible for client and server side // visibility of IME window. if (!isVisibilityAppliedUsingInsetsConsumer()) { mWindow.hide(); } mDecorViewVisible = false; onWindowHidden(); mDecorViewWasVisible = false; Loading core/java/android/view/ImeInsetsSourceConsumer.java +2 −8 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { * editor {@link #mFocusedEditor} if {@link #isServedEditorRendered} is {@code true}. */ private boolean mShowOnNextImeRender; private boolean mHasWindowFocus; public ImeInsetsSourceConsumer( InsetsState state, Supplier<Transaction> transactionSupplier, Loading @@ -68,23 +67,18 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { } public void applyImeVisibility(boolean setVisible) { if (!mHasWindowFocus) { // App window doesn't have focus, any visibility changes would be no-op. return; } mController.applyImeVisibility(setVisible); } @Override public void onWindowFocusGained() { mHasWindowFocus = true; super.onWindowFocusGained(); getImm().registerImeConsumer(this); } @Override public void onWindowFocusLost() { mHasWindowFocus = false; super.onWindowFocusLost(); getImm().unregisterImeConsumer(this); } Loading core/java/android/view/InsetsController.java +17 −7 Original line number Diff line number Diff line Loading @@ -296,7 +296,8 @@ public class InsetsController implements WindowInsetsController { final ArraySet<Integer> internalTypes = mState.toInternalType(types); final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>(); Pair<Integer, Boolean> typesReadyPair = collectConsumers(fromIme, internalTypes, consumers); Pair<Integer, Boolean> typesReadyPair = collectConsumers( fromIme, internalTypes, consumers, listener); int typesReady = typesReadyPair.first; boolean isReady = typesReadyPair.second; if (!isReady) { Loading Loading @@ -324,13 +325,16 @@ public class InsetsController implements WindowInsetsController { * @return Pair of (types ready to animate, is ready to animate). */ private Pair<Integer, Boolean> collectConsumers(boolean fromIme, ArraySet<Integer> internalTypes, SparseArray<InsetsSourceConsumer> consumers) { ArraySet<Integer> internalTypes, SparseArray<InsetsSourceConsumer> consumers, WindowInsetsAnimationControlListener listener) { int typesReady = 0; boolean isReady = true; for (int i = internalTypes.size() - 1; i >= 0; i--) { InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i)); if (consumer.getControl() != null) { if (!consumer.isVisible()) { // Double check for IME that IME target window has focus. if (consumer.getType() != TYPE_IME || consumer.hasWindowFocus()) { boolean setVisible = !consumer.isVisible(); if (setVisible) { // Show request switch(consumer.requestShow(fromIme)) { case ShowResult.SHOW_IMMEDIATELY: Loading @@ -357,8 +361,11 @@ public class InsetsController implements WindowInsetsController { } consumers.put(consumer.getType(), consumer); } else { // TODO: Let calling app know it's not possible, or wait // TODO: Remove it from types // window doesnt have focus, no-op. isReady = false; // TODO: Let the calling app know that window has lost focus and // show()/hide()/controlWindowInsetsAnimation requests will be ignored. typesReady &= ~InsetsState.toPublicType(consumer.getType()); } } return new Pair<>(typesReady, isReady); Loading Loading @@ -533,8 +540,11 @@ public class InsetsController implements WindowInsetsController { @Override public void onCancelled() { // Animator can be null when it is cancelled before onReady() completes. if (mAnimator != null) { mAnimator.cancel(); } } private void onAnimationFinish() { mAnimationDirection = DIRECTION_NONE; Loading core/java/android/view/InsetsSourceConsumer.java +11 −3 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ public class InsetsSourceConsumer { private final @InternalInsetType int mType; private final InsetsState mState; private @Nullable InsetsSourceControl mSourceControl; private boolean mHasWindowFocus; public InsetsSourceConsumer(@InternalInsetType int type, InsetsState state, Supplier<Transaction> transactionSupplier, InsetsController controller) { Loading Loading @@ -104,12 +105,20 @@ public class InsetsSourceConsumer { /** * Called when current window gains focus */ public void onWindowFocusGained() {} public void onWindowFocusGained() { mHasWindowFocus = true; } /** * Called when current window loses focus. */ public void onWindowFocusLost() {} public void onWindowFocusLost() { mHasWindowFocus = false; } boolean hasWindowFocus() { return mHasWindowFocus; } boolean applyLocalVisibilityOverride() { Loading Loading @@ -153,7 +162,6 @@ public class InsetsSourceConsumer { return; } mVisible = visible; applyHiddenToControl(); applyLocalVisibilityOverride(); mController.notifyVisibilityChanged(); } Loading core/java/android/view/InsetsState.java +4 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.view; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME; import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES; import static android.view.WindowInsets.Type.SIZE; Loading Loading @@ -161,13 +162,15 @@ public class InsetsState implements Parcelable { continue; } boolean skipNonImeInImeMode = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_IME && source.getType() != TYPE_IME; boolean skipSystemBars = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL && (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR); boolean skipIme = source.getType() == TYPE_IME && (legacySoftInputMode & LayoutParams.SOFT_INPUT_ADJUST_RESIZE) == 0; boolean skipLegacyTypes = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE && (toPublicType(type) & Type.compatSystemInsets()) != 0; if (skipSystemBars || skipIme || skipLegacyTypes) { if (skipSystemBars || skipIme || skipLegacyTypes || skipNonImeInImeMode) { typeVisibilityMap[indexOf(toPublicType(type))] = source.isVisible(); continue; } Loading Loading
core/java/android/inputmethodservice/InputMethodService.java +16 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.inputmethodservice; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; import static java.lang.annotation.RetentionPolicy.SOURCE; Loading Loading @@ -62,6 +63,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewRootImpl; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; Loading Loading @@ -595,12 +597,12 @@ public class InputMethodService extends AbstractInputMethodService { if (DEBUG) Log.v(TAG, "hideSoftInput()"); final boolean wasVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); applyVisibilityInInsetsConsumerIfNecessary(false /* setVisible */); if (mIsPreRendered) { if (DEBUG) { Log.v(TAG, "Making IME window invisible"); } setImeWindowStatus(IME_ACTIVE | IME_INVISIBLE, mBackDisposition); applyVisibilityInInsetsConsumer(false /* setVisible */); onPreRenderedWindowVisibilityChanged(false /* setVisible */); } else { mShowInputFlags = 0; Loading Loading @@ -632,11 +634,11 @@ public class InputMethodService extends AbstractInputMethodService { if (DEBUG) { Log.v(TAG, "Making IME window visible"); } applyVisibilityInInsetsConsumer(true /* setVisible */); onPreRenderedWindowVisibilityChanged(true /* setVisible */); } else { showWindow(true); } applyVisibilityInInsetsConsumerIfNecessary(true /* setVisible */); } // If user uses hard keyboard, IME button should always be shown. setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition); Loading Loading @@ -1974,16 +1976,20 @@ public class InputMethodService extends AbstractInputMethodService { /** * Apply the IME visibility in {@link android.view.ImeInsetsSourceConsumer} when * pre-rendering is enabled. * {@link ViewRootImpl.sNewInsetsMode} is enabled. * @param setVisible {@code true} to make it visible, false to hide it. */ private void applyVisibilityInInsetsConsumer(boolean setVisible) { if (!mIsPreRendered) { private void applyVisibilityInInsetsConsumerIfNecessary(boolean setVisible) { if (!isVisibilityAppliedUsingInsetsConsumer()) { return; } mPrivOps.applyImeVisibility(setVisible); } private boolean isVisibilityAppliedUsingInsetsConsumer() { return ViewRootImpl.sNewInsetsMode > NEW_INSETS_MODE_NONE; } private void finishViews(boolean finishingInput) { if (mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInputView"); Loading @@ -2007,7 +2013,11 @@ public class InputMethodService extends AbstractInputMethodService { mWindowVisible = false; finishViews(false /* finishingInput */); if (mDecorViewVisible) { // When insets API is enabled, it is responsible for client and server side // visibility of IME window. if (!isVisibilityAppliedUsingInsetsConsumer()) { mWindow.hide(); } mDecorViewVisible = false; onWindowHidden(); mDecorViewWasVisible = false; Loading
core/java/android/view/ImeInsetsSourceConsumer.java +2 −8 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { * editor {@link #mFocusedEditor} if {@link #isServedEditorRendered} is {@code true}. */ private boolean mShowOnNextImeRender; private boolean mHasWindowFocus; public ImeInsetsSourceConsumer( InsetsState state, Supplier<Transaction> transactionSupplier, Loading @@ -68,23 +67,18 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { } public void applyImeVisibility(boolean setVisible) { if (!mHasWindowFocus) { // App window doesn't have focus, any visibility changes would be no-op. return; } mController.applyImeVisibility(setVisible); } @Override public void onWindowFocusGained() { mHasWindowFocus = true; super.onWindowFocusGained(); getImm().registerImeConsumer(this); } @Override public void onWindowFocusLost() { mHasWindowFocus = false; super.onWindowFocusLost(); getImm().unregisterImeConsumer(this); } Loading
core/java/android/view/InsetsController.java +17 −7 Original line number Diff line number Diff line Loading @@ -296,7 +296,8 @@ public class InsetsController implements WindowInsetsController { final ArraySet<Integer> internalTypes = mState.toInternalType(types); final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>(); Pair<Integer, Boolean> typesReadyPair = collectConsumers(fromIme, internalTypes, consumers); Pair<Integer, Boolean> typesReadyPair = collectConsumers( fromIme, internalTypes, consumers, listener); int typesReady = typesReadyPair.first; boolean isReady = typesReadyPair.second; if (!isReady) { Loading Loading @@ -324,13 +325,16 @@ public class InsetsController implements WindowInsetsController { * @return Pair of (types ready to animate, is ready to animate). */ private Pair<Integer, Boolean> collectConsumers(boolean fromIme, ArraySet<Integer> internalTypes, SparseArray<InsetsSourceConsumer> consumers) { ArraySet<Integer> internalTypes, SparseArray<InsetsSourceConsumer> consumers, WindowInsetsAnimationControlListener listener) { int typesReady = 0; boolean isReady = true; for (int i = internalTypes.size() - 1; i >= 0; i--) { InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i)); if (consumer.getControl() != null) { if (!consumer.isVisible()) { // Double check for IME that IME target window has focus. if (consumer.getType() != TYPE_IME || consumer.hasWindowFocus()) { boolean setVisible = !consumer.isVisible(); if (setVisible) { // Show request switch(consumer.requestShow(fromIme)) { case ShowResult.SHOW_IMMEDIATELY: Loading @@ -357,8 +361,11 @@ public class InsetsController implements WindowInsetsController { } consumers.put(consumer.getType(), consumer); } else { // TODO: Let calling app know it's not possible, or wait // TODO: Remove it from types // window doesnt have focus, no-op. isReady = false; // TODO: Let the calling app know that window has lost focus and // show()/hide()/controlWindowInsetsAnimation requests will be ignored. typesReady &= ~InsetsState.toPublicType(consumer.getType()); } } return new Pair<>(typesReady, isReady); Loading Loading @@ -533,8 +540,11 @@ public class InsetsController implements WindowInsetsController { @Override public void onCancelled() { // Animator can be null when it is cancelled before onReady() completes. if (mAnimator != null) { mAnimator.cancel(); } } private void onAnimationFinish() { mAnimationDirection = DIRECTION_NONE; Loading
core/java/android/view/InsetsSourceConsumer.java +11 −3 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ public class InsetsSourceConsumer { private final @InternalInsetType int mType; private final InsetsState mState; private @Nullable InsetsSourceControl mSourceControl; private boolean mHasWindowFocus; public InsetsSourceConsumer(@InternalInsetType int type, InsetsState state, Supplier<Transaction> transactionSupplier, InsetsController controller) { Loading Loading @@ -104,12 +105,20 @@ public class InsetsSourceConsumer { /** * Called when current window gains focus */ public void onWindowFocusGained() {} public void onWindowFocusGained() { mHasWindowFocus = true; } /** * Called when current window loses focus. */ public void onWindowFocusLost() {} public void onWindowFocusLost() { mHasWindowFocus = false; } boolean hasWindowFocus() { return mHasWindowFocus; } boolean applyLocalVisibilityOverride() { Loading Loading @@ -153,7 +162,6 @@ public class InsetsSourceConsumer { return; } mVisible = visible; applyHiddenToControl(); applyLocalVisibilityOverride(); mController.notifyVisibilityChanged(); } Loading
core/java/android/view/InsetsState.java +4 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.view; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME; import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE; import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES; import static android.view.WindowInsets.Type.SIZE; Loading Loading @@ -161,13 +162,15 @@ public class InsetsState implements Parcelable { continue; } boolean skipNonImeInImeMode = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_IME && source.getType() != TYPE_IME; boolean skipSystemBars = ViewRootImpl.sNewInsetsMode != NEW_INSETS_MODE_FULL && (type == TYPE_TOP_BAR || type == TYPE_NAVIGATION_BAR); boolean skipIme = source.getType() == TYPE_IME && (legacySoftInputMode & LayoutParams.SOFT_INPUT_ADJUST_RESIZE) == 0; boolean skipLegacyTypes = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE && (toPublicType(type) & Type.compatSystemInsets()) != 0; if (skipSystemBars || skipIme || skipLegacyTypes) { if (skipSystemBars || skipIme || skipLegacyTypes || skipNonImeInImeMode) { typeVisibilityMap[indexOf(toPublicType(type))] = source.isVisible(); continue; } Loading