The new color were already introduces in a previous CL ag/30322786 This CL is about replacing the attribute usage by the new color resources, which should work the same but cannot be overwritten, or styled, guaranteeing consistency across the OS. The old attributes will be removed in CL: ag/29910036 Bug: 374273611 Test: presubmit Flag: EXEMPT Un-flaggable refactor of private color resources Change-Id: I05b5261054bcb6de40e4e40d633025495f3dd01f
322 lines
13 KiB
Java
322 lines
13 KiB
Java
/*
|
|
* 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 static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
|
|
|
|
import android.app.Activity;
|
|
import android.app.AlertDialog;
|
|
import android.app.Dialog;
|
|
import android.app.settings.SettingsEnums;
|
|
import android.content.Context;
|
|
import android.graphics.drawable.Drawable;
|
|
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;
|
|
import android.view.Window;
|
|
import android.widget.AdapterView;
|
|
import android.widget.BaseAdapter;
|
|
import android.widget.Button;
|
|
import android.widget.ImageView;
|
|
import android.widget.ListView;
|
|
import android.widget.TextView;
|
|
|
|
import androidx.core.graphics.drawable.DrawableCompat;
|
|
import androidx.fragment.app.DialogFragment;
|
|
import androidx.preference.Preference;
|
|
|
|
import com.android.settings.R;
|
|
import com.android.settings.overlay.FeatureFactory;
|
|
import com.android.settingslib.Utils;
|
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
|
|
|
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 {
|
|
|
|
static final String DEFAULT_KEY = "default_key";
|
|
static final String SELECTION_KEY = "delection_key";
|
|
|
|
private Preference mPreference;
|
|
private String mKeyDefaultName;
|
|
private String mKeyFocus;
|
|
private Activity mActivity;
|
|
private KeyboardSettingsFeatureProvider mFeatureProvider;
|
|
private Drawable mActionKeyDrawable;
|
|
private TextView mLeftBracket;
|
|
private TextView mRightBracket;
|
|
private ImageView mActionKeyIcon;
|
|
private MetricsFeatureProvider mMetricsFeatureProvider;
|
|
|
|
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() {}
|
|
|
|
@Override
|
|
public void onSaveInstanceState(Bundle savedInstanceState) {
|
|
savedInstanceState.putString(SELECTION_KEY, mKeyFocus);
|
|
super.onSaveInstanceState(savedInstanceState);
|
|
}
|
|
|
|
@Override
|
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
super.onCreateDialog(savedInstanceState);
|
|
|
|
mActivity = getActivity();
|
|
FeatureFactory featureFactory = FeatureFactory.getFeatureFactory();
|
|
mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider();
|
|
mFeatureProvider = featureFactory.getKeyboardSettingsFeatureProvider();
|
|
InputManager inputManager = mActivity.getSystemService(InputManager.class);
|
|
mKeyDefaultName = getArguments().getString(DEFAULT_KEY);
|
|
mKeyFocus = getArguments().getString(SELECTION_KEY);
|
|
if (savedInstanceState != null) {
|
|
mKeyFocus = savedInstanceState.getString(SELECTION_KEY);
|
|
}
|
|
List<String> modifierKeys = new ArrayList<String>(Arrays.asList(
|
|
mActivity.getString(R.string.modifier_keys_caps_lock),
|
|
mActivity.getString(R.string.modifier_keys_ctrl),
|
|
mActivity.getString(R.string.modifier_keys_meta),
|
|
mActivity.getString(R.string.modifier_keys_alt)));
|
|
for (int i = 0; i < modifierKeys.size(); i++) {
|
|
mRemappableKeyMap.put(modifierKeys.get(i), mRemappableKeyList.get(i));
|
|
}
|
|
Drawable drawable = mFeatureProvider.getActionKeyIcon(mActivity);
|
|
if (drawable != null) {
|
|
mActionKeyDrawable = DrawableCompat.wrap(drawable);
|
|
}
|
|
|
|
View dialoglayout =
|
|
LayoutInflater.from(mActivity).inflate(R.layout.modifier_key_picker_dialog, null);
|
|
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mActivity);
|
|
dialogBuilder.setView(dialoglayout);
|
|
|
|
TextView summary = dialoglayout.findViewById(R.id.modifier_key_picker_summary);
|
|
CharSequence summaryText = mActivity.getString(
|
|
R.string.modifier_keys_picker_summary, mKeyDefaultName);
|
|
summary.setText(summaryText);
|
|
|
|
ModifierKeyAdapter adapter = new ModifierKeyAdapter(modifierKeys);
|
|
ListView listView = dialoglayout.findViewById(R.id.modifier_key_picker);
|
|
listView.setAdapter(adapter);
|
|
setInitialFocusItem(modifierKeys, adapter);
|
|
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
|
@Override
|
|
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
|
adapter.setCurrentItem(i);
|
|
adapter.notifyDataSetChanged();
|
|
}
|
|
});
|
|
|
|
AlertDialog modifierKeyDialog = dialogBuilder.create();
|
|
Button doneButton = dialoglayout.findViewById(R.id.modifier_key_done_button);
|
|
doneButton.setOnClickListener(v -> {
|
|
String selectedItem = modifierKeys.get(adapter.getCurrentItem());
|
|
Spannable itemSummary;
|
|
logMetricsForRemapping(selectedItem);
|
|
if (selectedItem.equals(mKeyDefaultName)) {
|
|
itemSummary = new SpannableString(
|
|
mActivity.getString(R.string.modifier_keys_default_summary));
|
|
itemSummary.setSpan(
|
|
new ForegroundColorSpan(getColorOfTextColorSecondary()),
|
|
0, itemSummary.length(), 0);
|
|
// Set keys to default.
|
|
int[] keys = mRemappableKeyMap.get(mKeyDefaultName);
|
|
for (int i = 0; i < keys.length; i++) {
|
|
inputManager.remapModifierKey(keys[i], keys[i]);
|
|
}
|
|
} else {
|
|
itemSummary = new SpannableString(selectedItem);
|
|
itemSummary.setSpan(
|
|
new ForegroundColorSpan(getColorOfMaterialColorPrimary()),
|
|
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(mActivity, mKeyDefaultName)) {
|
|
inputManager.remapModifierKey(fromKeys[0], toKeys[0]);
|
|
}
|
|
// Remap KEY_LEFT and KEY_RIGHT to CAPS_LOCK.
|
|
if (!isKeyCapsLock(mActivity, mKeyDefaultName)
|
|
&& isKeyCapsLock(mActivity, selectedItem)) {
|
|
inputManager.remapModifierKey(fromKeys[0], toKeys[0]);
|
|
inputManager.remapModifierKey(fromKeys[1], toKeys[0]);
|
|
}
|
|
// Auto handle left and right keys remapping.
|
|
if (!isKeyCapsLock(mActivity, mKeyDefaultName)
|
|
&& !isKeyCapsLock(mActivity, selectedItem)) {
|
|
inputManager.remapModifierKey(fromKeys[0], toKeys[0]);
|
|
inputManager.remapModifierKey(fromKeys[1], toKeys[1]);
|
|
}
|
|
}
|
|
dismiss();
|
|
mActivity.recreate();
|
|
});
|
|
|
|
Button cancelButton = dialoglayout.findViewById(R.id.modifier_key_cancel_button);
|
|
cancelButton.setOnClickListener(v -> {
|
|
dismiss();
|
|
});
|
|
|
|
final Window window = modifierKeyDialog.getWindow();
|
|
window.setType(TYPE_SYSTEM_DIALOG);
|
|
|
|
return modifierKeyDialog;
|
|
}
|
|
|
|
private void logMetricsForRemapping(String selectedItem) {
|
|
if (mKeyDefaultName.equals("Caps lock")) {
|
|
mMetricsFeatureProvider.action(
|
|
mActivity, SettingsEnums.ACTION_FROM_CAPS_LOCK_TO, selectedItem);
|
|
}
|
|
|
|
if (mKeyDefaultName.equals("Ctrl")) {
|
|
mMetricsFeatureProvider.action(
|
|
mActivity, SettingsEnums.ACTION_FROM_CTRL_TO, selectedItem);
|
|
}
|
|
|
|
if (mKeyDefaultName.equals("Action key")) {
|
|
mMetricsFeatureProvider.action(
|
|
mActivity, SettingsEnums.ACTION_FROM_ACTION_KEY_TO, selectedItem);
|
|
}
|
|
|
|
if (mKeyDefaultName.equals("Alt")) {
|
|
mMetricsFeatureProvider.action(
|
|
mActivity, SettingsEnums.ACTION_FROM_ALT_TO, selectedItem);
|
|
}
|
|
}
|
|
|
|
private void setInitialFocusItem(
|
|
List<String> modifierKeys, ModifierKeyAdapter adapter) {
|
|
if (modifierKeys.indexOf(mKeyFocus) == -1) {
|
|
adapter.setCurrentItem(modifierKeys.indexOf(mKeyDefaultName));
|
|
} else {
|
|
adapter.setCurrentItem(modifierKeys.indexOf(mKeyFocus));
|
|
}
|
|
adapter.notifyDataSetChanged();
|
|
}
|
|
|
|
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 List<String> mList;
|
|
|
|
ModifierKeyAdapter(List<String> list) {
|
|
this.mList = list;
|
|
}
|
|
|
|
@Override
|
|
public int getCount() {
|
|
return mList.size();
|
|
}
|
|
|
|
@Override
|
|
public Object getItem(int i) {
|
|
return mList.get(i);
|
|
}
|
|
|
|
@Override
|
|
public long getItemId(int i) {
|
|
return i;
|
|
}
|
|
|
|
@Override
|
|
public View getView(int i, View view, ViewGroup viewGroup) {
|
|
if (view == null) {
|
|
view = LayoutInflater.from(mActivity).inflate(R.layout.modifier_key_item, null);
|
|
}
|
|
TextView textView = view.findViewById(R.id.modifier_key_text);
|
|
ImageView checkIcon = view.findViewById(R.id.modifier_key_check_icon);
|
|
textView.setText(mList.get(i));
|
|
if (mCurrentItem == i) {
|
|
mKeyFocus = mList.get(i);
|
|
textView.setTextColor(getColorOfMaterialColorPrimary());
|
|
checkIcon.setImageAlpha(255);
|
|
view.setBackground(
|
|
mActivity.getDrawable(R.drawable.modifier_key_lisetview_background));
|
|
if (mActionKeyDrawable != null && i == 2) {
|
|
setActionKeyIcon(view);
|
|
setActionKeyColor(getColorOfMaterialColorPrimary());
|
|
}
|
|
} else {
|
|
textView.setTextColor(getColorOfTextColorPrimary());
|
|
checkIcon.setImageAlpha(0);
|
|
view.setBackground(null);
|
|
if (mActionKeyDrawable != null && i == 2) {
|
|
setActionKeyIcon(view);
|
|
setActionKeyColor(getColorOfTextColorPrimary());
|
|
}
|
|
}
|
|
return view;
|
|
}
|
|
|
|
public void setCurrentItem(int currentItem) {
|
|
this.mCurrentItem = currentItem;
|
|
}
|
|
|
|
public int getCurrentItem() {
|
|
return this.mCurrentItem;
|
|
}
|
|
}
|
|
|
|
private void setActionKeyIcon(View view) {
|
|
mLeftBracket = view.findViewById(R.id.modifier_key_left_bracket);
|
|
mRightBracket = view.findViewById(R.id.modifier_key_right_bracket);
|
|
mActionKeyIcon = view.findViewById(R.id.modifier_key_action_key_icon);
|
|
mLeftBracket.setText("(");
|
|
mRightBracket.setText(")");
|
|
mActionKeyIcon.setImageDrawable(mActionKeyDrawable);
|
|
}
|
|
|
|
private void setActionKeyColor(int color) {
|
|
mLeftBracket.setTextColor(color);
|
|
mRightBracket.setTextColor(color);
|
|
DrawableCompat.setTint(mActionKeyDrawable, color);
|
|
}
|
|
|
|
private int getColorOfTextColorPrimary() {
|
|
return Utils.getColorAttrDefaultColor(mActivity, android.R.attr.textColorPrimary);
|
|
}
|
|
|
|
private int getColorOfTextColorSecondary() {
|
|
return Utils.getColorAttrDefaultColor(mActivity, android.R.attr.textColorSecondary);
|
|
}
|
|
|
|
private int getColorOfMaterialColorPrimary() {
|
|
return mActivity.getColor(com.android.internal.R.color.materialColorPrimary);
|
|
}
|
|
}
|