Loading AndroidManifest.xml +1 −0 Original line number Original line Diff line number Diff line Loading @@ -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" Loading src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java +51 −10 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading @@ -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() { Loading @@ -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( Loading @@ -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(); Loading @@ -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; Loading src/com/android/settings/inputmethod/ModifierKeysPreferenceController.java +95 −4 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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(); Loading @@ -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); } } Loading @@ -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; } } } src/com/android/settings/inputmethod/ModifierKeysResetDialogFragment.java +8 −2 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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, Loading @@ -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 Loading Loading @@ -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() { Loading src/com/android/settings/inputmethod/ModifierKeysRestorePreferenceController.java +4 −1 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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); } } Loading Loading
AndroidManifest.xml +1 −0 Original line number Original line Diff line number Diff line Loading @@ -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" Loading
src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java +51 −10 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading @@ -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() { Loading @@ -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( Loading @@ -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(); Loading @@ -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; Loading
src/com/android/settings/inputmethod/ModifierKeysPreferenceController.java +95 −4 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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(); Loading @@ -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); } } Loading @@ -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; } } }
src/com/android/settings/inputmethod/ModifierKeysResetDialogFragment.java +8 −2 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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, Loading @@ -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 Loading Loading @@ -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() { Loading
src/com/android/settings/inputmethod/ModifierKeysRestorePreferenceController.java +4 −1 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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); } } Loading