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

Commit 75d7404a authored by Vaibhav Devmurari's avatar Vaibhav Devmurari Committed by Android (Google) Code Review
Browse files

Merge "Capture Ctrl+Space shortcut in InputMethodService" into main

parents a35bd2ca c93a60b0
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -3363,6 +3363,13 @@ public class InputMethodService extends AbstractInputMethodService {
                return true;
            }
            return false;
        } else if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && KeyEvent.metaStateHasModifiers(
                event.getMetaState() & ~KeyEvent.META_SHIFT_MASK, KeyEvent.META_CTRL_ON)) {
            if (mDecorViewVisible && mWindowVisible) {
                int direction = (event.getMetaState() & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
                mPrivOps.switchKeyboardLayoutAsync(direction);
                return true;
            }
        }
        return doMovementKey(keyCode, event, MOVEMENT_DOWN);
    }
+1 −0
Original line number Diff line number Diff line
@@ -46,4 +46,5 @@ oneway interface IInputMethodPrivilegedOperations {
            in @nullable ImeTracker.Token statsToken);
    void onStylusHandwritingReady(int requestId, int pid);
    void resetStylusHandwriting(int requestId);
    void switchKeyboardLayoutAsync(int direction);
}
+16 −0
Original line number Diff line number Diff line
@@ -431,4 +431,20 @@ public final class InputMethodPrivilegedOperations {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Calls {@link IInputMethodPrivilegedOperations#switchKeyboardLayoutAsync(int)}.
     */
    @AnyThread
    public void switchKeyboardLayoutAsync(int direction) {
        final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
        if (ops == null) {
            return;
        }
        try {
            ops.switchKeyboardLayoutAsync(direction);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
+53 −32
Original line number Diff line number Diff line
@@ -5529,6 +5529,42 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
        return canAccess;
    }

    @GuardedBy("ImfLock.class")
    private void switchKeyboardLayoutLocked(int direction) {
        final InputMethodInfo currentImi = mMethodMap.get(getSelectedMethodIdLocked());
        if (currentImi == null) {
            return;
        }
        final InputMethodSubtypeHandle currentSubtypeHandle =
                InputMethodSubtypeHandle.of(currentImi, mCurrentSubtype);
        final InputMethodSubtypeHandle nextSubtypeHandle =
                mHardwareKeyboardShortcutController.onSubtypeSwitch(currentSubtypeHandle,
                        direction > 0);
        if (nextSubtypeHandle == null) {
            return;
        }
        final InputMethodInfo nextImi = mMethodMap.get(nextSubtypeHandle.getImeId());
        if (nextImi == null) {
            return;
        }

        final int subtypeCount = nextImi.getSubtypeCount();
        if (subtypeCount == 0) {
            if (nextSubtypeHandle.equals(InputMethodSubtypeHandle.of(nextImi, null))) {
                setInputMethodLocked(nextImi.getId(), NOT_A_SUBTYPE_ID);
            }
            return;
        }

        for (int i = 0; i < subtypeCount; ++i) {
            if (nextSubtypeHandle.equals(
                    InputMethodSubtypeHandle.of(nextImi, nextImi.getSubtypeAt(i)))) {
                setInputMethodLocked(nextImi.getId(), i);
                return;
            }
        }
    }

    private void publishLocalService() {
        LocalServices.addService(InputMethodManagerInternal.class, new LocalServiceImpl());
    }
@@ -5734,38 +5770,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
        @Override
        public void switchKeyboardLayout(int direction) {
            synchronized (ImfLock.class) {
                final InputMethodInfo currentImi = mMethodMap.get(getSelectedMethodIdLocked());
                if (currentImi == null) {
                    return;
                }
                final InputMethodSubtypeHandle currentSubtypeHandle =
                        InputMethodSubtypeHandle.of(currentImi, mCurrentSubtype);
                final InputMethodSubtypeHandle nextSubtypeHandle =
                        mHardwareKeyboardShortcutController.onSubtypeSwitch(currentSubtypeHandle,
                                direction > 0);
                if (nextSubtypeHandle == null) {
                    return;
                }
                final InputMethodInfo nextImi = mMethodMap.get(nextSubtypeHandle.getImeId());
                if (nextImi == null) {
                    return;
                }

                final int subtypeCount = nextImi.getSubtypeCount();
                if (subtypeCount == 0) {
                    if (nextSubtypeHandle.equals(InputMethodSubtypeHandle.of(nextImi, null))) {
                        setInputMethodLocked(nextImi.getId(), NOT_A_SUBTYPE_ID);
                    }
                    return;
                }

                for (int i = 0; i < subtypeCount; ++i) {
                    if (nextSubtypeHandle.equals(
                            InputMethodSubtypeHandle.of(nextImi, nextImi.getSubtypeAt(i)))) {
                        setInputMethodLocked(nextImi.getId(), i);
                        return;
                    }
                }
                switchKeyboardLayoutLocked(direction);
            }
        }

@@ -6767,5 +6772,21 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
        public void resetStylusHandwriting(int requestId) {
            mImms.resetStylusHandwriting(requestId);
        }

        @BinderThread
        @Override
        public void switchKeyboardLayoutAsync(int direction) {
            synchronized (ImfLock.class) {
                if (!mImms.calledWithValidTokenLocked(mToken)) {
                    return;
                }
                final long ident = Binder.clearCallingIdentity();
                try {
                    mImms.switchKeyboardLayoutLocked(direction);
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            }
        }
    }
}
+23 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.util.Log;
import android.view.KeyEvent;
import android.view.WindowManagerGlobal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
@@ -598,6 +599,28 @@ public class InputMethodServiceTest {
                false /* orientationPortrait */);
    }

    @Test
    public void switchesKeyboardLayout_withShortcut_onlyIfImeVisible() throws Exception {
        setShowImeWithHardKeyboard(true /* enabled */);

        assertThat(mInputMethodService.isInputViewShown()).isFalse();
        assertThat(mInputMethodService.onKeyDown(KeyEvent.KEYCODE_SPACE,
                new KeyEvent(0 /* downTime */, 0 /* eventTime */, KeyEvent.ACTION_DOWN,
                        KeyEvent.KEYCODE_SPACE, 0 /* repeat */,
                        KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON))).isFalse();

        verifyInputViewStatusOnMainSync(
                () -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
                true /* expected */,
                true /* inputViewStarted */);

        assertThat(mInputMethodService.isInputViewShown()).isTrue();
        assertThat(mInputMethodService.onKeyDown(KeyEvent.KEYCODE_SPACE,
                new KeyEvent(0 /* downTime */, 0 /* eventTime */, KeyEvent.ACTION_DOWN,
                        KeyEvent.KEYCODE_SPACE, 0 /* repeat */,
                        KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON))).isTrue();
    }

    /**
     * This checks that when the system navigation bar is not created (e.g. emulator),
     * then the IME caption bar is also not created.