blob: 60c2fa61830c45242ec304a8d815a6454c1dc102 [file] [log] [blame]
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +01001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar;
18
19import android.app.AlertDialog;
20import android.app.Dialog;
21import android.content.Context;
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000022import android.content.DialogInterface;
23import android.content.DialogInterface.OnClickListener;
Clara Bayarri75e09792015-07-29 16:20:40 +010024import android.os.Handler;
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000025import android.os.Looper;
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +000026import android.view.ContextThemeWrapper;
Clara Bayarri75e09792015-07-29 16:20:40 +010027import android.view.KeyEvent;
28import android.view.KeyboardShortcutGroup;
29import android.view.KeyboardShortcutInfo;
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010030import android.view.LayoutInflater;
31import android.view.View;
Andrei Stingaceanu844927d2016-02-16 14:31:58 +000032import android.view.ViewGroup;
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010033import android.view.Window;
Clara Bayarri75e09792015-07-29 16:20:40 +010034import android.view.WindowManager.KeyboardShortcutsReceiver;
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000035import android.widget.LinearLayout;
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000036import android.widget.TextView;
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010037
38import com.android.systemui.R;
Clara Bayarri75e09792015-07-29 16:20:40 +010039import com.android.systemui.recents.Recents;
40
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000041import java.util.ArrayList;
Clara Bayarri75e09792015-07-29 16:20:40 +010042import java.util.List;
43
44import static android.content.Context.LAYOUT_INFLATER_SERVICE;
Clara Bayarri75e09792015-07-29 16:20:40 +010045import static android.view.Gravity.TOP;
46import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010047
48/**
49 * Contains functionality for handling keyboard shortcuts.
50 */
51public class KeyboardShortcuts {
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000052 private static final char SYSTEM_HOME_BASE_CHARACTER = '\u2386';
53 private static final char SYSTEM_BACK_BASE_CHARACTER = '\u007F';
54 private static final char SYSTEM_RECENTS_BASE_CHARACTER = '\u0009';
55
56 private final Handler mHandler = new Handler(Looper.getMainLooper());
57 private final Context mContext;
58 private final OnClickListener dialogCloseListener = new DialogInterface.OnClickListener() {
59 public void onClick(DialogInterface dialog, int id) {
60 dismissKeyboardShortcutsDialog();
61 }
62 };
Clara Bayarri75e09792015-07-29 16:20:40 +010063
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010064 private Dialog mKeyboardShortcutsDialog;
65
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000066 public KeyboardShortcuts(Context context) {
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +000067 this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000068 }
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010069
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000070 public void toggleKeyboardShortcuts() {
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010071 if (mKeyboardShortcutsDialog == null) {
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000072 Recents.getSystemServices().requestKeyboardShortcuts(mContext,
Clara Bayarri75e09792015-07-29 16:20:40 +010073 new KeyboardShortcutsReceiver() {
74 @Override
75 public void onKeyboardShortcutsReceived(
76 final List<KeyboardShortcutGroup> result) {
77 KeyboardShortcutGroup systemGroup = new KeyboardShortcutGroup(
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000078 mContext.getString(R.string.keyboard_shortcut_group_system), true);
Clara Bayarri75e09792015-07-29 16:20:40 +010079 systemGroup.addItem(new KeyboardShortcutInfo(
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000080 mContext.getString(R.string.keyboard_shortcut_group_system_home),
81 SYSTEM_HOME_BASE_CHARACTER, KeyEvent.META_META_ON));
Clara Bayarri75e09792015-07-29 16:20:40 +010082 systemGroup.addItem(new KeyboardShortcutInfo(
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000083 mContext.getString(R.string.keyboard_shortcut_group_system_back),
84 SYSTEM_BACK_BASE_CHARACTER, KeyEvent.META_META_ON));
Clara Bayarri75e09792015-07-29 16:20:40 +010085 systemGroup.addItem(new KeyboardShortcutInfo(
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000086 mContext.getString(R.string.keyboard_shortcut_group_system_recents),
87 SYSTEM_RECENTS_BASE_CHARACTER, KeyEvent.META_ALT_ON));
Clara Bayarri75e09792015-07-29 16:20:40 +010088 result.add(systemGroup);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000089 showKeyboardShortcutsDialog(result);
Clara Bayarri75e09792015-07-29 16:20:40 +010090 }
91 });
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010092 } else {
93 dismissKeyboardShortcutsDialog();
94 }
95 }
96
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010097 public void dismissKeyboardShortcutsDialog() {
98 if (mKeyboardShortcutsDialog != null) {
99 mKeyboardShortcutsDialog.dismiss();
100 mKeyboardShortcutsDialog = null;
101 }
102 }
103
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000104 private void showKeyboardShortcutsDialog(
105 final List<KeyboardShortcutGroup> keyboardShortcutGroups) {
106 // Need to post on the main thread.
107 mHandler.post(new Runnable() {
108 @Override
109 public void run() {
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000110 handleShowKeyboardShortcuts(keyboardShortcutGroups);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000111 }
112 });
113 }
114
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000115 private void handleShowKeyboardShortcuts(List<KeyboardShortcutGroup> keyboardShortcutGroups) {
116 AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
117 LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
118 LAYOUT_INFLATER_SERVICE);
119 final View keyboardShortcutsView = inflater.inflate(
120 R.layout.keyboard_shortcuts_view, null);
121 populateKeyboardShortcuts((LinearLayout) keyboardShortcutsView.findViewById(
122 R.id.keyboard_shortcuts_container), keyboardShortcutGroups);
123 dialogBuilder.setView(keyboardShortcutsView);
124 dialogBuilder.setPositiveButton(R.string.quick_settings_done, dialogCloseListener);
125 mKeyboardShortcutsDialog = dialogBuilder.create();
126 mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
127 Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
128 keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
129 mKeyboardShortcutsDialog.show();
130 }
131
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000132 private void populateKeyboardShortcuts(LinearLayout keyboardShortcutsLayout,
133 List<KeyboardShortcutGroup> keyboardShortcutGroups) {
134 LayoutInflater inflater = LayoutInflater.from(mContext);
135 final int keyboardShortcutGroupsSize = keyboardShortcutGroups.size();
136 for (int i = 0; i < keyboardShortcutGroupsSize; i++) {
137 KeyboardShortcutGroup group = keyboardShortcutGroups.get(i);
138 TextView categoryTitle = (TextView) inflater.inflate(
139 R.layout.keyboard_shortcuts_category_title, keyboardShortcutsLayout, false);
140 categoryTitle.setText(group.getLabel());
141 categoryTitle.setTextColor(group.isSystemGroup()
142 ? mContext.getColor(R.color.ksh_system_group_color)
143 : mContext.getColor(R.color.ksh_application_group_color));
144 keyboardShortcutsLayout.addView(categoryTitle);
145
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000146 LinearLayout shortcutContainer = (LinearLayout) inflater.inflate(
147 R.layout.keyboard_shortcuts_container, keyboardShortcutsLayout, false);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000148 final int itemsSize = group.getItems().size();
149 for (int j = 0; j < itemsSize; j++) {
150 KeyboardShortcutInfo info = group.getItems().get(j);
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000151 View shortcutView = inflater.inflate(R.layout.keyboard_shortcut_app_item,
152 shortcutContainer, false);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000153 TextView textView = (TextView) shortcutView
154 .findViewById(R.id.keyboard_shortcuts_keyword);
155 textView.setText(info.getLabel());
156
Andrei Stingaceanu844927d2016-02-16 14:31:58 +0000157 ViewGroup shortcutItemsContainer = (ViewGroup) shortcutView
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000158 .findViewById(R.id.keyboard_shortcuts_item_container);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000159 List<String> shortcutKeys = getHumanReadableShortcutKeys(info);
160 final int shortcutKeysSize = shortcutKeys.size();
161 for (int k = 0; k < shortcutKeysSize; k++) {
162 String shortcutKey = shortcutKeys.get(k);
163 TextView shortcutKeyView = (TextView) inflater.inflate(
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000164 R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer, false);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000165 shortcutKeyView.setText(shortcutKey);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000166 shortcutItemsContainer.addView(shortcutKeyView);
167 }
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000168 shortcutContainer.addView(shortcutView);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000169 }
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000170 keyboardShortcutsLayout.addView(shortcutContainer);
171 if (i < keyboardShortcutGroupsSize - 1) {
172 View separator = inflater.inflate(
173 R.layout.keyboard_shortcuts_category_separator, keyboardShortcutsLayout,
174 false);
175 keyboardShortcutsLayout.addView(separator);
176 }
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000177 }
178 }
179
180 private List<String> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
181 // TODO: fix the shortcuts. Find or build an util which can produce human readable
182 // names of the baseCharacter and the modifiers.
183 List<String> shortcutKeys = new ArrayList<>();
184 shortcutKeys.add(KeyEvent.metaStateToString(info.getModifiers()).toUpperCase());
185 shortcutKeys.add(Character.getName(info.getBaseCharacter()).toUpperCase());
186 return shortcutKeys;
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +0100187 }
188}