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

Commit d5f7ed9f authored by Michael Wright's avatar Michael Wright
Browse files

Switch and store keyboard layouts based on IME subtype.

Rather than associate the keyboard layout solely with a specific
hardware model, we should also associate it with a given IME subtype.
This lets users switch between various languages and have the
keyboard change in unison with them so they can use the appropriate
layouts for each language.

This change adds initial support for associating IME subtypes and
keyboard layouts. We still need to:
  - Remove support for the old style of layout association once the
    Settings apps begins to use the new APIs
  - Automatically select an appropriate layout based on the given
    subtype (or set a reasonable universal default such as QWERTY)

Bug: 25752812

Change-Id: Ie88ce1ab77dbfe03ab51d89c1dc9e0a7ddbb3216
parent e501c39e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import android.os.IBinder;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.PointerIcon;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;

/** @hide */
interface IInputManager {
@@ -59,6 +61,11 @@ interface IInputManager {
            String keyboardLayoutDescriptor);
    void removeKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
            String keyboardLayoutDescriptor);
    KeyboardLayout getKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
            in InputMethodInfo imeInfo, in InputMethodSubtype imeSubtype);
    void setKeyboardLayoutForInputDevice(in InputDeviceIdentifier identifier,
            in InputMethodInfo imeInfo, in InputMethodSubtype imeSubtype,
            String keyboardLayoutDescriptor);

    // Registers an input devices changed listener.
    void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);
+49 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package android.hardware.input;

import android.view.PointerIcon;
import com.android.internal.inputmethod.InputMethodSubtypeHandle;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;

@@ -40,6 +40,9 @@ import android.util.Log;
import android.util.SparseArray;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.PointerIcon;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -643,6 +646,51 @@ public final class InputManager {
        }
    }


    /**
     * Gets the keyboard layout for the specified input device and IME subtype.
     *
     * @param identifier The identifier for the input device.
     * @param inputMethodInfo The input method.
     * @param inputMethodSubtype The input method subtype.
     *
     * @return The associated {@link KeyboardLayout}, or null if one has not been set.
     *
     * @hide
     */
    public KeyboardLayout getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
            InputMethodInfo inputMethodInfo, InputMethodSubtype inputMethodSubtype) {
        try {
            return mIm.getKeyboardLayoutForInputDevice(
                    identifier, inputMethodInfo, inputMethodSubtype);
        } catch (RemoteException ex) {
            Log.w(TAG, "Could not set keyboard layout.", ex);
            return null;
        }
    }

    /**
     * Sets the keyboard layout for the specified input device and IME subtype pair.
     *
     * @param identifier The identifier for the input device.
     * @param inputMethodInfo The input method with which to associate the keyboard layout.
     * @param inputMethodSubtype The input method subtype which which to associate the keyboard
     *                           layout.
     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to set
     *
     * @hide
     */
    public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
            InputMethodInfo inputMethodInfo, InputMethodSubtype inputMethodSubtype,
            String keyboardLayoutDescriptor) {
        try {
            mIm.setKeyboardLayoutForInputDevice(identifier, inputMethodInfo,
                    inputMethodSubtype, keyboardLayoutDescriptor);
        } catch (RemoteException ex) {
            Log.w(TAG, "Could not set keyboard layout.", ex);
        }
    }

    /**
     * Gets the TouchCalibration applied to the specified input device's coordinates.
     *
+6 −0
Original line number Diff line number Diff line
@@ -123,4 +123,10 @@ public class TouchCalibration implements Parcelable {
               Float.floatToIntBits(mYScale)  ^
               Float.floatToIntBits(mYOffset);
    }

    @Override
    public String toString() {
        return String.format("[%f, %f, %f, %f, %f, %f]",
                mXScale, mXYMix, mXOffset, mYXMix, mYScale, mYOffset);
    }
}
+0 −6
Original line number Diff line number Diff line
@@ -440,12 +440,6 @@ public interface WindowManagerPolicy {
         */
        public int getCameraLensCoverState();

        /**
         * Switch the keyboard layout for the given device.
         * Direction should be +1 or -1 to go to the next or previous keyboard layout.
         */
        public void switchKeyboardLayout(int deviceId, int direction);

        /**
         * Switch the input method, to be precise, input method subtype.
         *
+71 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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 com.android.internal.inputmethod;

import android.text.TextUtils;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;

import java.util.Objects;

public class InputMethodSubtypeHandle {
    private final String mInputMethodId;
    private final int mSubtypeId;

    public InputMethodSubtypeHandle(InputMethodInfo info, InputMethodSubtype subtype) {
        mInputMethodId = info.getId();
        if (subtype != null) {
            mSubtypeId = subtype.hashCode();
        } else {
            mSubtypeId = 0;
        }
    }

    public InputMethodSubtypeHandle(String inputMethodId, int subtypeId) {
        mInputMethodId = inputMethodId;
        mSubtypeId = subtypeId;
    }

    public String getInputMethodId() {
        return mInputMethodId;
    }

    public int getSubtypeId() {
        return mSubtypeId;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || !(o instanceof InputMethodSubtypeHandle)) {
            return false;
        }
        InputMethodSubtypeHandle other = (InputMethodSubtypeHandle) o;
        return TextUtils.equals(mInputMethodId, other.getInputMethodId())
                && mSubtypeId == other.getSubtypeId();
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(mInputMethodId) * 31 + mSubtypeId;
    }

    @Override
    public String toString() {
        return "InputMethodSubtypeHandle{mInputMethodId=" + mInputMethodId
            + ", mSubtypeId=" + mSubtypeId + "}";
    }
}
Loading