Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7fc5864 authored by Taran Singh's avatar Taran Singh
Browse files

Ime target window should control when to hide IME (2/2)

This followup CL implements hideInsets() introduced in 1/2.

Bug: 142461756
Bug: 111084606
Test: Manually tested using steps below:
  1. Make sure new insets flag is enabled
  2. Launch any activity which has child window with NOT_FOCUSABLE,
     ALT_FOCUSABLE_IM (e.g. Instagram login screen)
  3. Verify IME can be shown and hidden by this window.

Change-Id: I307594014eca8a06397c739ffbc9c12eac160fdc
parent f1e0887e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -229,6 +229,10 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
            final InsetsSourceConsumer consumer = items.valueAt(i);
            final InsetsSource source = mInitialInsetsState.getSource(consumer.getType());
            final InsetsSourceControl control = consumer.getControl();
            if (control == null) {
                // Control may not be available for consumer yet or revoked.
                continue;
            }
            final SurfaceControl leash = consumer.getControl().getLeash();

            mTmpMatrix.setTranslate(control.getSurfacePosition().x, control.getSurfacePosition().y);
+31 −34
Original line number Diff line number Diff line
@@ -251,6 +251,10 @@ public class InsetsController implements WindowInsetsController {

    @Override
    public void hide(@InsetType int types) {
        hide(types, false /* fromIme */);
    }

    void hide(@InsetType int types, boolean fromIme) {
        int typesReady = 0;
        final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
        for (int i = internalTypes.size() - 1; i >= 0; i--) {
@@ -265,7 +269,7 @@ public class InsetsController implements WindowInsetsController {
            }
            typesReady |= InsetsState.toPublicType(consumer.getType());
        }
        applyAnimation(typesReady, false /* show */, false /* fromIme */);
        applyAnimation(typesReady, false /* show */, fromIme /* fromIme */);
    }

    @Override
@@ -331,8 +335,6 @@ public class InsetsController implements WindowInsetsController {
        boolean isReady = true;
        for (int i = internalTypes.size() - 1; i >= 0; i--) {
            InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i));
            // 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
@@ -356,17 +358,12 @@ public class InsetsController implements WindowInsetsController {
                // Hide request
                // TODO: Move notifyHidden() to beginning of the hide animation
                // (when visibility actually changes using hideDirectly()).
                if (!fromIme) {
                    consumer.notifyHidden();
                }
                typesReady |= InsetsState.toPublicType(consumer.getType());
            }
            consumers.put(consumer.getType(), consumer);
            } else {
                // 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);
    }
+8 −4
Original line number Diff line number Diff line
@@ -3570,10 +3570,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                return;
            }
            if (!setVisible) {
                // Client hides the IME directly.
                if (mCurClient != null && mCurClient.client != null) {
                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
                            MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, mCurClient));
                if (mCurClient != null) {
                    // IMMS only knows of focused window, not the actual IME target.
                    // e.g. it isn't aware of any window that has both
                    // NOT_FOCUSABLE, ALT_FOCUSABLE_IM flags set and can the IME target.
                    // Send it to window manager to hide IME from IME target window.
                    // TODO(b/139861270): send to mCurClient.client once IMMS is aware of
                    // actual IME target.
                    mWindowManagerInternal.hideIme(mCurClient.selfReportedDisplayId);
                }
            } else {
                // Send to window manager to show IME after IME layout finishes.
+22 −7
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ import android.view.WindowInsets;
 */
class ImeInsetsSourceProvider extends InsetsSourceProvider {

    private WindowState mCurImeTarget;
    private WindowState mImeTargetFromIme;
    private Runnable mShowImeRunner;
    private boolean mIsImeLayoutDrawn;

@@ -40,8 +40,8 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider {
    void onPostLayout() {
        super.onPostLayout();

        if (mCurImeTarget != null
                && mCurImeTarget == mDisplayContent.mInputMethodTarget
        if (mImeTargetFromIme != null
                && isImeTargetFromDisplayContentAndImeSame()
                && mWin != null
                && mWin.isDrawnLw()
                && !mWin.mGivenInsetsPending) {
@@ -64,18 +64,33 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider {
    /**
     * Called from {@link WindowManagerInternal#showImePostLayout} when {@link InputMethodService}
     * requests to show IME on {@param imeTarget}.
     * @param imeTarget imeTarget on which IME is displayed.
     * @param imeTarget imeTarget on which IME request is coming from.
     */
    void scheduleShowImePostLayout(WindowState imeTarget) {
        mCurImeTarget = imeTarget;
        mImeTargetFromIme = imeTarget;
        mShowImeRunner = () -> {
            // Target should still be the same.
            if (mCurImeTarget == mDisplayContent.mInputMethodTarget) {
            if (isImeTargetFromDisplayContentAndImeSame()) {
                mDisplayContent.mInputMethodTarget.showInsets(
                        WindowInsets.Type.ime(), true /* fromIme */);
            }
            mCurImeTarget = null;
            mImeTargetFromIme = null;
        };
    }

    private boolean isImeTargetFromDisplayContentAndImeSame() {
        // IMMS#mLastImeTargetWindow always considers focused window as
        // IME target, however DisplayContent#computeImeTarget() can compute
        // a different IME target.
        // Refer to WindowManagerService#applyImeVisibility(token, false).
        // If IMMS's imeTarget is child of DisplayContent's imeTarget and child window
        // is above the parent, we will consider it as the same target for now.
        // TODO(b/139861270): Remove the child & sublayer check once IMMS is aware of
        //  actual IME target.
        return mImeTargetFromIme == mDisplayContent.mInputMethodTarget
                || (mDisplayContent.mInputMethodTarget.getParentWindow() == mImeTargetFromIme
                        && mDisplayContent.mInputMethodTarget.mSubLayer
                                > mImeTargetFromIme.mSubLayer);
    }

}
+7 −0
Original line number Diff line number Diff line
@@ -513,6 +513,13 @@ public abstract class WindowManagerInternal {
     */
    public abstract void showImePostLayout(IBinder imeTargetWindowToken);

    /**
     * Hide IME using imeTargetWindow when requested.
     *
     * @param displayId on which IME is shown
     */
    public abstract void hideIme(int displayId);

    /**
     * Tell window manager about a package that should not be running with high refresh rate
     * setting until removeNonHighRefreshRatePackage is called for the same package.
Loading