/* * Copyright (C) 2022 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.settings.inputmethod; 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 androidx.fragment.app.Fragment; 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 final String KEY_TAG = "modifier_keys_dialog_tag"; private static final 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 PreferenceScreen mScreen; private final List 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) { mParent = parent; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); if (mParent == null) { return; } mScreen = screen; refreshUi(); } private void refreshUi() { for (Map.Entry 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 = mScreen.findPreference(KEY_PREFERENCE_CTRL); preference.setSummary(changeSummaryColor(mKeyNames[index])); } if (isMeta(fromKey) && mRemappableKeys.contains(toKey)) { Preference preference = mScreen.findPreference(KEY_PREFERENCE_META); preference.setSummary(changeSummaryColor(mKeyNames[index])); } if (isAlt(fromKey) && mRemappableKeys.contains(toKey)) { Preference preference = mScreen.findPreference(KEY_PREFERENCE_ALT); preference.setSummary(changeSummaryColor(mKeyNames[index])); } if (isCapLock(fromKey) && mRemappableKeys.contains(toKey)) { Preference preference = mScreen.findPreference(KEY_PREFERENCE_CAPS_LOCK); preference.setSummary(changeSummaryColor(mKeyNames[index])); } } } @Override public boolean handlePreferenceTreeClick(Preference preference) { if (preference.getKey().equals(KEY_RESTORE_PREFERENCE)) { return false; } showModifierKeysDialog(preference); return true; } @Override public int getAvailabilityStatus() { return AVAILABLE; } private void showModifierKeysDialog(Preference preference) { mFragmentManager = mParent.getFragmentManager(); ModifierKeysPickerDialogFragment fragment = new ModifierKeysPickerDialogFragment(); fragment.setTargetFragment(mParent, 0); Bundle bundle = new Bundle(); bundle.putString( ModifierKeysPickerDialogFragment.DEFAULT_KEY, preference.getTitle().toString()); bundle.putString( ModifierKeysPickerDialogFragment.SELECTION_KEY, preference.getSummary().toString()); fragment.setArguments(bundle); fragment.show(mFragmentManager, KEY_TAG); } private Spannable changeSummaryColor(String summary) { Spannable spannableSummary = new SpannableString(summary); spannableSummary.setSpan( new ForegroundColorSpan(getColorOfMaterialColorPrimary()), 0, spannableSummary.length(), 0); return spannableSummary; } private int getColorOfMaterialColorPrimary() { return Utils.getColorAttrDefaultColor( mContext, com.android.internal.R.attr.materialColorPrimary); } 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; } }