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 Original line 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.START_VIEW_APP_FEATURES" />
    <uses-permission android:name="android.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS" />
    <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.CUSTOMIZE_SYSTEM_UI" />
    <uses-permission android:name="android.permission.REMAP_MODIFIER_KEYS" />


    <application
    <application
            android:name=".SettingsApplication"
            android:name=".SettingsApplication"
+51 −10
Original line number Original line 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.AlertDialog;
import android.app.Dialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Context;
import android.hardware.input.InputManager;
import android.os.Bundle;
import android.os.Bundle;
import android.text.Spannable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.text.style.ForegroundColorSpan;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup;
@@ -43,31 +45,48 @@ import com.android.settings.R;
import com.android.settingslib.Utils;
import com.android.settingslib.Utils;


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


public class ModifierKeysPickerDialogFragment extends DialogFragment {
public class ModifierKeysPickerDialogFragment extends DialogFragment {


    private Preference mPreference;
    private Preference mPreference;
    private String mKeyDefaultName;
    private String mKeyDefaultName;
    private Context mContext;
    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() {
    }
    }


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


    @Override
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        super.onCreateDialog(savedInstanceState);
        super.onCreateDialog(savedInstanceState);
        mContext = getActivity();
        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_caps_lock),
                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)));
        for (int i = 0; i < modifierKeys.size(); i++) {
            mRemappableKeyMap.put(modifierKeys.get(i), mRemappableKeyList.get(i));
        }


        View dialoglayout  =
        View dialoglayout  =
                LayoutInflater.from(mContext).inflate(R.layout.modifier_key_picker_dialog, null);
                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);
                R.string.modifier_keys_picker_summary, mKeyDefaultName);
        summary.setText(summaryText);
        summary.setText(summaryText);


        List<String> list = new ArrayList<>();
        ModifierKeyAdapter adapter = new ModifierKeyAdapter(modifierKeys);
        for (int i = 0; i < modifierKeys.length; i++) {
            list.add(modifierKeys[i]);
        }
        ModifierKeyAdapter adapter = new ModifierKeyAdapter(list);
        ListView listView = dialoglayout.findViewById(R.id.modifier_key_picker);
        ListView listView = dialoglayout.findViewById(R.id.modifier_key_picker);
        listView.setAdapter(adapter);
        listView.setAdapter(adapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@@ -98,7 +113,7 @@ public class ModifierKeysPickerDialogFragment extends DialogFragment {
        AlertDialog modifierKeyDialog = dialogBuilder.create();
        AlertDialog modifierKeyDialog = dialogBuilder.create();
        Button doneButton = dialoglayout.findViewById(R.id.modifier_key_done_button);
        Button doneButton = dialoglayout.findViewById(R.id.modifier_key_done_button);
        doneButton.setOnClickListener(v -> {
        doneButton.setOnClickListener(v -> {
            String selectedItem = list.get(adapter.getCurrentItem());
            String selectedItem = modifierKeys.get(adapter.getCurrentItem());
            Spannable itemSummary;
            Spannable itemSummary;
            if (selectedItem.equals(mKeyDefaultName)) {
            if (selectedItem.equals(mKeyDefaultName)) {
                itemSummary = new SpannableString(
                itemSummary = new SpannableString(
@@ -106,12 +121,34 @@ public class ModifierKeysPickerDialogFragment extends DialogFragment {
                itemSummary.setSpan(
                itemSummary.setSpan(
                        new ForegroundColorSpan(getColorOfTextColorSecondary()),
                        new ForegroundColorSpan(getColorOfTextColorSecondary()),
                        0, itemSummary.length(), 0);
                        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 {
            } else {
                itemSummary = new SpannableString(selectedItem);
                itemSummary = new SpannableString(selectedItem);
                itemSummary.setSpan(
                itemSummary.setSpan(
                        new ForegroundColorSpan(getColorOfColorAccentPrimaryVariant()),
                        new ForegroundColorSpan(getColorOfColorAccentPrimaryVariant()),
                        0, itemSummary.length(), 0);
                        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);
            mPreference.setSummary(itemSummary);
            modifierKeyDialog.dismiss();
            modifierKeyDialog.dismiss();
@@ -128,6 +165,10 @@ public class ModifierKeysPickerDialogFragment extends DialogFragment {
        return modifierKeyDialog;
        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 {
    class ModifierKeyAdapter extends BaseAdapter {
        private int mCurrentItem = 0;
        private int mCurrentItem = 0;
        private boolean mIsClick = false;
        private boolean mIsClick = false;
+95 −4
Original line number Original line Diff line number Diff line
@@ -17,6 +17,11 @@
package com.android.settings.inputmethod;
package com.android.settings.inputmethod;


import android.content.Context;
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.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.Fragment;
@@ -24,18 +29,50 @@ import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceScreen;


import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
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 {
public class ModifierKeysPreferenceController extends BasePreferenceController {


    private static String KEY_TAG = "modifier_keys_dialog_tag";
    private static String KEY_TAG = "modifier_keys_dialog_tag";
    private static String KEY_RESTORE_PREFERENCE = "modifier_keys_restore";
    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 Fragment mParent;
    private FragmentManager mFragmentManager;
    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) {
    public ModifierKeysPreferenceController(Context context, String key) {
        super(context, key);
        super(context, key);
        mIm = context.getSystemService(InputManager.class);
        Objects.requireNonNull(mIm, "InputManager service cannot be null");
    }
    }


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

        // setTitle
        // setSummary
        if (mParent == null) {
        if (mParent == null) {
            return;
            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.
        // The dialog screen depends on the previous selected key's fragment.
        // In the rotation scenario, we should remove the previous dialog screen first.
        // In the rotation scenario, we should remove the previous dialog screen first.
        clearPreviousDialog();
        clearPreviousDialog();
@@ -72,7 +134,7 @@ public class ModifierKeysPreferenceController extends BasePreferenceController {


    private void showModifierKeysDialog(Preference preference) {
    private void showModifierKeysDialog(Preference preference) {
        ModifierKeysPickerDialogFragment fragment =
        ModifierKeysPickerDialogFragment fragment =
                new ModifierKeysPickerDialogFragment(preference);
                new ModifierKeysPickerDialogFragment(preference, mIm);
        fragment.setTargetFragment(mParent, 0);
        fragment.setTargetFragment(mParent, 0);
        fragment.show(mFragmentManager, KEY_TAG);
        fragment.show(mFragmentManager, KEY_TAG);
    }
    }
@@ -85,4 +147,33 @@ public class ModifierKeysPreferenceController extends BasePreferenceController {
            preKeysDialogFragment.dismiss();
            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 Original line 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.AlertDialog;
import android.app.Dialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Context;
import android.hardware.input.InputManager;
import android.os.Bundle;
import android.os.Bundle;
import android.text.Spannable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableString;
@@ -44,6 +45,7 @@ public class ModifierKeysResetDialogFragment extends DialogFragment {
    private static final String MODIFIER_KEYS_ALT = "modifier_keys_alt";
    private static final String MODIFIER_KEYS_ALT = "modifier_keys_alt";


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


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


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

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


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


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


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


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


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