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

Commit cede9295 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Integrate modifier keys settings UI with APIs"

parents b8a45779 aa1d9c4d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@
    <uses-permission android:name="android.permission.START_VIEW_APP_FEATURES" />
    <uses-permission android:name="android.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS" />
    <uses-permission android:name="android.permission.CUSTOMIZE_SYSTEM_UI" />
    <uses-permission android:name="android.permission.REMAP_MODIFIER_KEYS" />

    <application
            android:name=".SettingsApplication"
+51 −10
Original line number Diff line number Diff line
@@ -21,10 +21,12 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.hardware.input.InputManager;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -43,31 +45,48 @@ import com.android.settings.R;
import com.android.settingslib.Utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ModifierKeysPickerDialogFragment extends DialogFragment {

    private Preference mPreference;
    private String mKeyDefaultName;
    private Context mContext;
    private InputManager mIm;

    private List<int[]> mRemappableKeyList =
            new ArrayList<>(Arrays.asList(
                    new int[]{KeyEvent.KEYCODE_CAPS_LOCK},
                    new int[]{KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.KEYCODE_CTRL_RIGHT},
                    new int[]{KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_META_RIGHT},
                    new int[]{KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.KEYCODE_ALT_RIGHT}));

    private Map<String, int[]> mRemappableKeyMap = new HashMap<>();

    public ModifierKeysPickerDialogFragment() {
    }

    public ModifierKeysPickerDialogFragment(Preference preference) {
    public ModifierKeysPickerDialogFragment(Preference preference, InputManager inputManager) {
        mPreference = preference;
        mKeyDefaultName = preference.getTitle().toString();
        mIm = inputManager;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        super.onCreateDialog(savedInstanceState);
        mContext = getActivity();
        String[] modifierKeys = new String[] {
        List<String> modifierKeys = new ArrayList<String>(Arrays.asList(
                mContext.getString(R.string.modifier_keys_caps_lock),
                mContext.getString(R.string.modifier_keys_ctrl),
                mContext.getString(R.string.modifier_keys_meta),
                mContext.getString(R.string.modifier_keys_alt)};
                mContext.getString(R.string.modifier_keys_alt)));
        for (int i = 0; i < modifierKeys.size(); i++) {
            mRemappableKeyMap.put(modifierKeys.get(i), mRemappableKeyList.get(i));
        }

        View dialoglayout  =
                LayoutInflater.from(mContext).inflate(R.layout.modifier_key_picker_dialog, null);
@@ -79,11 +98,7 @@ public class ModifierKeysPickerDialogFragment extends DialogFragment {
                R.string.modifier_keys_picker_summary, mKeyDefaultName);
        summary.setText(summaryText);

        List<String> list = new ArrayList<>();
        for (int i = 0; i < modifierKeys.length; i++) {
            list.add(modifierKeys[i]);
        }
        ModifierKeyAdapter adapter = new ModifierKeyAdapter(list);
        ModifierKeyAdapter adapter = new ModifierKeyAdapter(modifierKeys);
        ListView listView = dialoglayout.findViewById(R.id.modifier_key_picker);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@@ -98,7 +113,7 @@ public class ModifierKeysPickerDialogFragment extends DialogFragment {
        AlertDialog modifierKeyDialog = dialogBuilder.create();
        Button doneButton = dialoglayout.findViewById(R.id.modifier_key_done_button);
        doneButton.setOnClickListener(v -> {
            String selectedItem = list.get(adapter.getCurrentItem());
            String selectedItem = modifierKeys.get(adapter.getCurrentItem());
            Spannable itemSummary;
            if (selectedItem.equals(mKeyDefaultName)) {
                itemSummary = new SpannableString(
@@ -106,12 +121,34 @@ public class ModifierKeysPickerDialogFragment extends DialogFragment {
                itemSummary.setSpan(
                        new ForegroundColorSpan(getColorOfTextColorSecondary()),
                        0, itemSummary.length(), 0);
                // TODO(b/252812993): remapModifierKey
                // Set keys to default.
                int[] keys = mRemappableKeyMap.get(mKeyDefaultName);
                for (int i = 0; i < keys.length; i++) {
                    mIm.remapModifierKey(keys[i], keys[i]);
                }
            } else {
                itemSummary = new SpannableString(selectedItem);
                itemSummary.setSpan(
                        new ForegroundColorSpan(getColorOfColorAccentPrimaryVariant()),
                        0, itemSummary.length(), 0);
                int[] fromKeys = mRemappableKeyMap.get(mKeyDefaultName);
                int[] toKeys = mRemappableKeyMap.get(selectedItem);
                // CAPS_LOCK only one key, so always choose the left key for remapping.
                if (isKeyCapsLock(mContext, mKeyDefaultName)) {
                    mIm.remapModifierKey(fromKeys[0], toKeys[0]);
                }
                // Remap KEY_LEFT and KEY_RIGHT to CAPS_LOCK.
                if (!isKeyCapsLock(mContext, mKeyDefaultName)
                        && isKeyCapsLock(mContext, selectedItem)) {
                    mIm.remapModifierKey(fromKeys[0], toKeys[0]);
                    mIm.remapModifierKey(fromKeys[1], toKeys[0]);
                }
                // Auto handle left and right keys remapping.
                if (!isKeyCapsLock(mContext, mKeyDefaultName)
                        && !isKeyCapsLock(mContext, selectedItem)) {
                    mIm.remapModifierKey(fromKeys[0], toKeys[0]);
                    mIm.remapModifierKey(fromKeys[1], toKeys[1]);
                }
            }
            mPreference.setSummary(itemSummary);
            modifierKeyDialog.dismiss();
@@ -128,6 +165,10 @@ public class ModifierKeysPickerDialogFragment extends DialogFragment {
        return modifierKeyDialog;
    }

    private static boolean isKeyCapsLock(Context context, String key) {
        return key.equals(context.getString(R.string.modifier_keys_caps_lock));
    }

    class ModifierKeyAdapter extends BaseAdapter {
        private int mCurrentItem = 0;
        private boolean mIsClick = false;
+95 −4
Original line number Diff line number Diff line
@@ -17,6 +17,11 @@
package com.android.settings.inputmethod;

import android.content.Context;
import android.hardware.input.InputManager;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.view.KeyEvent;

import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
@@ -24,18 +29,50 @@ import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.Utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class ModifierKeysPreferenceController extends BasePreferenceController {

    private static String KEY_TAG = "modifier_keys_dialog_tag";
    private static String KEY_RESTORE_PREFERENCE = "modifier_keys_restore";

    private static final String KEY_PREFERENCE_CAPS_LOCK = "modifier_keys_caps_lock";
    private static final String KEY_PREFERENCE_CTRL = "modifier_keys_ctrl";
    private static final String KEY_PREFERENCE_META = "modifier_keys_meta";
    private static final String KEY_PREFERENCE_ALT = "modifier_keys_alt";

    private Fragment mParent;
    private FragmentManager mFragmentManager;
    private final InputManager mIm;

    private final List<Integer> mRemappableKeys = new ArrayList<>(
            Arrays.asList(
                    KeyEvent.KEYCODE_CTRL_LEFT, KeyEvent.KEYCODE_CTRL_RIGHT,
                    KeyEvent.KEYCODE_META_LEFT, KeyEvent.KEYCODE_META_RIGHT,
                    KeyEvent.KEYCODE_ALT_LEFT, KeyEvent.KEYCODE_ALT_RIGHT,
                    KeyEvent.KEYCODE_CAPS_LOCK));

    private String[] mKeyNames = new String[] {
            mContext.getString(R.string.modifier_keys_ctrl),
            mContext.getString(R.string.modifier_keys_ctrl),
            mContext.getString(R.string.modifier_keys_meta),
            mContext.getString(R.string.modifier_keys_meta),
            mContext.getString(R.string.modifier_keys_alt),
            mContext.getString(R.string.modifier_keys_alt),
            mContext.getString(R.string.modifier_keys_caps_lock)};

    public ModifierKeysPreferenceController(Context context, String key) {
        super(context, key);
        mIm = context.getSystemService(InputManager.class);
        Objects.requireNonNull(mIm, "InputManager service cannot be null");
    }

    public void setFragment(Fragment parent) {
@@ -45,12 +82,37 @@ public class ModifierKeysPreferenceController extends BasePreferenceController {
    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        // TODO: getModifierKeyRemapping()
        // setTitle
        // setSummary

        if (mParent == null) {
            return;
        }

        for (Map.Entry<Integer, Integer> entry : mIm.getModifierKeyRemapping().entrySet()) {
            int fromKey = entry.getKey();
            int toKey = entry.getValue();
            int index = mRemappableKeys.indexOf(toKey);

            if (isCtrl(fromKey) && mRemappableKeys.contains(toKey)) {
                Preference preference = screen.findPreference(KEY_PREFERENCE_CTRL);
                preference.setSummary(changeSummaryColor(mKeyNames[index]));
            }

            if (isMeta(fromKey) && mRemappableKeys.contains(toKey)) {
                Preference preference = screen.findPreference(KEY_PREFERENCE_META);
                preference.setSummary(changeSummaryColor(mKeyNames[index]));
            }

            if (isAlt(fromKey) && mRemappableKeys.contains(toKey)) {
                Preference preference = screen.findPreference(KEY_PREFERENCE_ALT);
                preference.setSummary(changeSummaryColor(mKeyNames[index]));
            }

            if (isCapLock(fromKey) && mRemappableKeys.contains(toKey)) {
                Preference preference = screen.findPreference(KEY_PREFERENCE_CAPS_LOCK);
                preference.setSummary(changeSummaryColor(mKeyNames[index]));
            }
        }

        // The dialog screen depends on the previous selected key's fragment.
        // In the rotation scenario, we should remove the previous dialog screen first.
        clearPreviousDialog();
@@ -72,7 +134,7 @@ public class ModifierKeysPreferenceController extends BasePreferenceController {

    private void showModifierKeysDialog(Preference preference) {
        ModifierKeysPickerDialogFragment fragment =
                new ModifierKeysPickerDialogFragment(preference);
                new ModifierKeysPickerDialogFragment(preference, mIm);
        fragment.setTargetFragment(mParent, 0);
        fragment.show(mFragmentManager, KEY_TAG);
    }
@@ -85,4 +147,33 @@ public class ModifierKeysPreferenceController extends BasePreferenceController {
            preKeysDialogFragment.dismiss();
        }
    }

    private Spannable changeSummaryColor(String summary) {
        Spannable spannableSummary = new SpannableString(summary);
        spannableSummary.setSpan(
                new ForegroundColorSpan(getColorOfColorAccentPrimaryVariant()),
                0, spannableSummary.length(), 0);
        return spannableSummary;
    }

    private int getColorOfColorAccentPrimaryVariant() {
        return Utils.getColorAttrDefaultColor(
                mContext, com.android.internal.R.attr.colorAccentPrimaryVariant);
    }

    private static boolean isCtrl(int keyCode) {
        return keyCode == KeyEvent.KEYCODE_CTRL_LEFT || keyCode == KeyEvent.KEYCODE_CTRL_RIGHT;
    }

    private static boolean isMeta(int keyCode) {
        return keyCode == KeyEvent.KEYCODE_META_LEFT || keyCode == KeyEvent.KEYCODE_META_RIGHT;
    }

    private static boolean isAlt(int keyCode) {
        return keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT;
    }

    private static boolean isCapLock(int keyCode) {
        return keyCode == KeyEvent.KEYCODE_CAPS_LOCK;
    }
}
+8 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.hardware.input.InputManager;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
@@ -44,6 +45,7 @@ public class ModifierKeysResetDialogFragment extends DialogFragment {
    private static final String MODIFIER_KEYS_ALT = "modifier_keys_alt";

    private PreferenceScreen mScreen;
    private InputManager mIm;
    private String[] mKeys = {
            MODIFIER_KEYS_CAPS_LOCK,
            MODIFIER_KEYS_CTRL,
@@ -53,8 +55,9 @@ public class ModifierKeysResetDialogFragment extends DialogFragment {
    public ModifierKeysResetDialogFragment() {
    }

    public ModifierKeysResetDialogFragment(PreferenceScreen screen) {
    public ModifierKeysResetDialogFragment(PreferenceScreen screen, InputManager inputManager) {
        mScreen = screen;
        mIm = inputManager;
    }

    @Override
@@ -95,7 +98,10 @@ public class ModifierKeysResetDialogFragment extends DialogFragment {
                    0, title.length(), 0);
            preference.setSummary(title);
        }
        // TODO(b/252812993): clearAllModifierKeyRemappings()

        if (mIm != null) {
            mIm.clearAllModifierKeyRemappings();
        }
    }

    private int getColorOfTextColorSecondary() {
+4 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.settings.inputmethod;

import android.content.Context;
import android.hardware.input.InputManager;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
@@ -38,9 +39,11 @@ public class ModifierKeysRestorePreferenceController extends BasePreferenceContr
    private Fragment mParent;
    private FragmentManager mFragmentManager;
    private PreferenceScreen mScreen;
    private final InputManager mIm;

    public ModifierKeysRestorePreferenceController(Context context, String key) {
        super(context, key);
        mIm = context.getSystemService(InputManager.class);
    }

    public void setFragment(Fragment parent) {
@@ -76,7 +79,7 @@ public class ModifierKeysRestorePreferenceController extends BasePreferenceContr

    private void showResetDialog() {
        ModifierKeysResetDialogFragment fragment =
                new ModifierKeysResetDialogFragment(mScreen);
                new ModifierKeysResetDialogFragment(mScreen, mIm);
        fragment.setTargetFragment(mParent, 0);
        fragment.show(mFragmentManager, KEY_TAG);
    }