blob: ebb319b0b07b62eea7ed947bcadea516456b15a0 [file] [log] [blame]
Winson Chung97d85d22011-04-13 11:27:36 -07001/*
Hyunyoung Songee3e6a72015-02-20 14:25:27 -08002 * Copyright (C) 2015 The Android Open Source Project
Winson Chung97d85d22011-04-13 11:27:36 -07003 *
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
Daniel Sandler325dc232013-06-05 22:57:57 -040017package com.android.launcher3;
Winson Chung97d85d22011-04-13 11:27:36 -070018
Winson Chung4e6a9762011-05-09 11:56:34 -070019import android.content.res.Configuration;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -080020import android.util.Log;
Winson Chung97d85d22011-04-13 11:27:36 -070021import android.view.KeyEvent;
Sunny Goyalb3726d92014-08-20 16:58:17 -070022import android.view.SoundEffectConstants;
Winson Chung97d85d22011-04-13 11:27:36 -070023import android.view.View;
24import android.view.ViewGroup;
Winson Chunga1f133d2013-07-25 11:14:30 -070025import android.widget.ScrollView;
Winson Chung97d85d22011-04-13 11:27:36 -070026
Hyunyoung Songee3e6a72015-02-20 14:25:27 -080027import com.android.launcher3.util.FocusLogic;
Winson Chungfaa13252011-06-13 18:15:54 -070028
Winson Chung97d85d22011-04-13 11:27:36 -070029/**
Winson Chung4d279d92011-07-21 11:46:32 -070030 * A keyboard listener we set on all the workspace icons.
31 */
Adam Cohenac56cff2011-09-28 20:45:37 -070032class IconKeyEventListener implements View.OnKeyListener {
Hyunyoung Songee3e6a72015-02-20 14:25:27 -080033 @Override
Winson Chung4d279d92011-07-21 11:46:32 -070034 public boolean onKey(View v, int keyCode, KeyEvent event) {
Adam Cohenac56cff2011-09-28 20:45:37 -070035 return FocusHelper.handleIconKeyEvent(v, keyCode, event);
36 }
37}
38
39/**
40 * A keyboard listener we set on all the workspace icons.
41 */
42class FolderKeyEventListener implements View.OnKeyListener {
Hyunyoung Songee3e6a72015-02-20 14:25:27 -080043 @Override
Adam Cohenac56cff2011-09-28 20:45:37 -070044 public boolean onKey(View v, int keyCode, KeyEvent event) {
45 return FocusHelper.handleFolderKeyEvent(v, keyCode, event);
Winson Chung4d279d92011-07-21 11:46:32 -070046 }
47}
48
49/**
Winson Chung3d503fb2011-07-13 17:25:49 -070050 * A keyboard listener we set on all the hotseat buttons.
Winson Chung4e6a9762011-05-09 11:56:34 -070051 */
Adam Cohenac56cff2011-09-28 20:45:37 -070052class HotseatIconKeyEventListener implements View.OnKeyListener {
Hyunyoung Songee3e6a72015-02-20 14:25:27 -080053 @Override
Winson Chung4e6a9762011-05-09 11:56:34 -070054 public boolean onKey(View v, int keyCode, KeyEvent event) {
Hyunyoung Songee3e6a72015-02-20 14:25:27 -080055 return FocusHelper.handleHotseatButtonKeyEvent(v, keyCode, event);
Winson Chung4e6a9762011-05-09 11:56:34 -070056 }
57}
58
Winson Chung97d85d22011-04-13 11:27:36 -070059public class FocusHelper {
Winson Chung97d85d22011-04-13 11:27:36 -070060
Hyunyoung Songee3e6a72015-02-20 14:25:27 -080061 private static final String TAG = "FocusHelper";
62 private static final boolean DEBUG = false;
63
64 //
65 // Key code handling methods.
66 //
67
68 /**
69 * Handles key events in the all apps screen.
70 */
71 static boolean handleAppsCustomizeKeyEvent(View v, int keyCode, KeyEvent e) {
72 boolean consume = FocusLogic.shouldConsume(keyCode);
73 if (e.getAction() == KeyEvent.ACTION_UP) {
74 return consume;
75 }
76 if (DEBUG) {
77 Log.v(TAG, String.format("Handle ALL APPS keyevent=[%s].",
78 KeyEvent.keyCodeToString(keyCode)));
79 }
80
81 // Initialize variables.
82 ViewGroup parentLayout;
83 ViewGroup itemContainer;
84 int countX;
85 int countY;
86 if (v.getParent() instanceof ShortcutAndWidgetContainer) {
87 itemContainer = (ViewGroup) v.getParent();
88 parentLayout = (ViewGroup) itemContainer.getParent();
89 countX = ((CellLayout) parentLayout).getCountX();
90 countY = ((CellLayout) parentLayout).getCountY();
91 } else if (v.getParent() instanceof ViewGroup) {
Hyunyoung Song38531712015-03-03 19:25:16 -080092 //TODO(hyunyoungs): figure out when this needs to be called.
Hyunyoung Songee3e6a72015-02-20 14:25:27 -080093 itemContainer = parentLayout = (ViewGroup) v.getParent();
94 countX = ((PagedViewGridLayout) parentLayout).getCellCountX();
95 countY = ((PagedViewGridLayout) parentLayout).getCellCountY();
96 } else {
97 throw new IllegalStateException(
98 "Parent of the focused item inside all apps screen is not a supported type.");
99 }
100 final int iconIndex = itemContainer.indexOfChild(v);
101 final PagedView container = (PagedView) parentLayout.getParent();
102 final int pageIndex = container.indexToPage(container.indexOfChild(parentLayout));
103 final int pageCount = container.getChildCount();
104 ViewGroup newParent = null;
105 View child = null;
Hyunyoung Song38531712015-03-03 19:25:16 -0800106 // TODO(hyunyoungs): this matrix is not applicable on the last page.
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800107 int[][] matrix = FocusLogic.createFullMatrix(countX, countY, true);
108
109 // Process focus.
110 int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX, countY, matrix,
111 iconIndex, pageIndex, pageCount);
112 if (newIconIndex == FocusLogic.NOOP) {
113 return consume;
114 }
115 switch (newIconIndex) {
Hyunyoung Song38531712015-03-03 19:25:16 -0800116 case FocusLogic.PREVIOUS_PAGE_RIGHT_COLUMN:
117 newParent = getAppsCustomizePage(container, pageIndex -1);
118 if (newParent != null) {
119 int row = FocusLogic.findRow(matrix, iconIndex);
120 container.snapToPage(pageIndex - 1);
121 // no need to create a new matrix.
122 child = newParent.getChildAt(matrix[countX-1][row]);
123 }
124 break;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800125 case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
126 newParent = getAppsCustomizePage(container, pageIndex - 1);
127 if (newParent != null) {
128 container.snapToPage(pageIndex - 1);
129 child = newParent.getChildAt(0);
130 }
Hyunyoung Song38531712015-03-03 19:25:16 -0800131 break;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800132 case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
133 newParent = getAppsCustomizePage(container, pageIndex - 1);
134 if (newParent != null) {
135 container.snapToPage(pageIndex - 1);
136 child = newParent.getChildAt(newParent.getChildCount() - 1);
137 }
138 break;
139 case FocusLogic.NEXT_PAGE_FIRST_ITEM:
140 newParent = getAppsCustomizePage(container, pageIndex + 1);
141 if (newParent != null) {
142 container.snapToPage(pageIndex + 1);
143 child = newParent.getChildAt(0);
144 }
145 break;
Hyunyoung Song38531712015-03-03 19:25:16 -0800146 case FocusLogic.NEXT_PAGE_LEFT_COLUMN:
147 newParent = getAppsCustomizePage(container, pageIndex + 1);
148 if (newParent != null) {
149 container.snapToPage(pageIndex + 1);
150 int row = FocusLogic.findRow(matrix, iconIndex);
151 child = newParent.getChildAt(matrix[0][row]);
152 }
153 break;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800154 case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
155 child = container.getChildAt(0);
156 break;
157 case FocusLogic.CURRENT_PAGE_LAST_ITEM:
158 child = itemContainer.getChildAt(itemContainer.getChildCount() - 1);
159 break;
160 default: // Go to some item on the current page.
161 child = itemContainer.getChildAt(newIconIndex);
162 break;
163 }
164 if (child != null) {
165 child.requestFocus();
166 playSoundEffect(keyCode, v);
167 }
168 return consume;
169 }
170
171 /**
172 * Handles key events in the workspace hot seat (bottom of the screen).
173 * <p>Currently we don't special case for the phone UI in different orientations, even though
174 * the hotseat is on the side in landscape mode. This is to ensure that accessibility
175 * consistency is maintained across rotations.
176 */
177 static boolean handleHotseatButtonKeyEvent(View v, int keyCode, KeyEvent e) {
178 boolean consume = FocusLogic.shouldConsume(keyCode);
179 if (e.getAction() == KeyEvent.ACTION_UP || !consume) {
180 return consume;
181 }
182 int orientation = v.getResources().getConfiguration().orientation;
183
184 if (DEBUG) {
185 Log.v(TAG, String.format(
186 "Handle HOTSEAT BUTTONS keyevent=[%s] on hotseat buttons, orientation=%d",
187 KeyEvent.keyCodeToString(keyCode), orientation));
188 }
189
190 // Initialize the variables.
191 final ShortcutAndWidgetContainer hotseatParent = (ShortcutAndWidgetContainer) v.getParent();
192 final CellLayout hotseatLayout = (CellLayout) hotseatParent.getParent();
Hyunyoung Song31178b82015-02-24 14:12:51 -0800193 Hotseat hotseat = (Hotseat) hotseatLayout.getParent();
194
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800195 Workspace workspace = (Workspace) v.getRootView().findViewById(R.id.workspace);
196 int pageIndex = workspace.getCurrentPage();
197 int pageCount = workspace.getChildCount();
Hyunyoung Song31178b82015-02-24 14:12:51 -0800198 int countX = -1;
199 int countY = -1;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800200 int iconIndex = findIndexOfView(hotseatParent, v);
201
202 final CellLayout iconLayout = (CellLayout) workspace.getChildAt(pageIndex);
203 final ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
204
205 ViewGroup parent = null;
Hyunyoung Song31178b82015-02-24 14:12:51 -0800206 int[][] matrix = null;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800207
208 if (keyCode == KeyEvent.KEYCODE_DPAD_UP &&
209 orientation == Configuration.ORIENTATION_PORTRAIT) {
Hyunyoung Song31178b82015-02-24 14:12:51 -0800210 matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, orientation,
211 hotseat.getAllAppsButtonRank(), true /* include all apps icon */);
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800212 iconIndex += iconParent.getChildCount();
213 countX = iconLayout.getCountX();
214 countY = iconLayout.getCountY() + hotseatLayout.getCountY();
215 parent = iconParent;
216 } else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT &&
217 orientation == Configuration.ORIENTATION_LANDSCAPE) {
Hyunyoung Song31178b82015-02-24 14:12:51 -0800218 matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, orientation,
219 hotseat.getAllAppsButtonRank(), true /* include all apps icon */);
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800220 iconIndex += iconParent.getChildCount();
221 countX = iconLayout.getCountX() + hotseatLayout.getCountX();
222 countY = iconLayout.getCountY();
223 parent = iconParent;
Hyunyoung Song31178b82015-02-24 14:12:51 -0800224 } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT &&
225 orientation == Configuration.ORIENTATION_LANDSCAPE) {
226 keyCode = KeyEvent.KEYCODE_PAGE_DOWN;
227 }else {
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800228 // For other KEYCODE_DPAD_LEFT and KEYCODE_DPAD_RIGHT navigation, do not use the
229 // matrix extended with hotseat.
230 matrix = FocusLogic.createSparseMatrix(hotseatLayout);
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800231 countX = hotseatLayout.getCountX();
232 countY = hotseatLayout.getCountY();
Hyunyoung Song31178b82015-02-24 14:12:51 -0800233 parent = hotseatParent;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800234 }
235
236 // Process the focus.
237 int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX, countY, matrix,
238 iconIndex, pageIndex, pageCount);
239
Hyunyoung Song31178b82015-02-24 14:12:51 -0800240 View newIcon = null;
241 if (newIconIndex == FocusLogic.NEXT_PAGE_FIRST_ITEM) {
242 parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
243 newIcon = parent.getChildAt(0);
244 // TODO(hyunyoungs): handle cases where the child is not an icon but
245 // a folder or a widget.
246 workspace.snapToPage(pageIndex + 1);
247 }
248 if (parent == iconParent && newIconIndex >= iconParent.getChildCount()) {
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800249 newIconIndex -= iconParent.getChildCount();
250 }
251 if (parent != null) {
Hyunyoung Song31178b82015-02-24 14:12:51 -0800252 if (newIcon == null && newIconIndex >=0) {
253 newIcon = parent.getChildAt(newIconIndex);
254 }
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800255 if (newIcon != null) {
256 newIcon.requestFocus();
257 playSoundEffect(keyCode, v);
258 }
259 }
260 return consume;
261 }
262
263 /**
264 * Handles key events in a workspace containing icons.
265 */
266 static boolean handleIconKeyEvent(View v, int keyCode, KeyEvent e) {
267 boolean consume = FocusLogic.shouldConsume(keyCode);
268 if (e.getAction() == KeyEvent.ACTION_UP || !consume) {
269 return consume;
270 }
271 int orientation = v.getResources().getConfiguration().orientation;
272 if (DEBUG) {
273 Log.v(TAG, String.format("Handle WORKSPACE ICONS keyevent=[%s] orientation=%d",
274 KeyEvent.keyCodeToString(keyCode), orientation));
275 }
276
277 // Initialize the variables.
278 ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
Hyunyoung Song38531712015-03-03 19:25:16 -0800279 CellLayout iconLayout = (CellLayout) parent.getParent();
Hyunyoung Song31178b82015-02-24 14:12:51 -0800280 final Workspace workspace = (Workspace) iconLayout.getParent();
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800281 final ViewGroup launcher = (ViewGroup) workspace.getParent();
282 final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.search_drop_target_bar);
Hyunyoung Song31178b82015-02-24 14:12:51 -0800283 final Hotseat hotseat = (Hotseat) launcher.findViewById(R.id.hotseat);
284 int pageIndex = workspace.indexOfChild(iconLayout);
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800285 int pageCount = workspace.getChildCount();
Hyunyoung Song31178b82015-02-24 14:12:51 -0800286 int countX = iconLayout.getCountX();
287 int countY = iconLayout.getCountY();
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800288 final int iconIndex = findIndexOfView(parent, v);
289
290 CellLayout hotseatLayout = (CellLayout) hotseat.getChildAt(0);
291 ShortcutAndWidgetContainer hotseatParent = hotseatLayout.getShortcutsAndWidgets();
292 int[][] matrix;
293
Hyunyoung Song31178b82015-02-24 14:12:51 -0800294 // KEYCODE_DPAD_DOWN in portrait (KEYCODE_DPAD_RIGHT in landscape) is the only key allowed
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800295 // to take a user to the hotseat. For other dpad navigation, do not use the matrix extended
296 // with the hotseat.
297 if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN &&
298 orientation == Configuration.ORIENTATION_PORTRAIT) {
Hyunyoung Song31178b82015-02-24 14:12:51 -0800299 matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, orientation,
300 hotseat.getAllAppsButtonRank(), false /* all apps icon is ignored */);
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800301 countY = countY + 1;
Hyunyoung Song31178b82015-02-24 14:12:51 -0800302 } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT &&
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800303 orientation == Configuration.ORIENTATION_LANDSCAPE) {
Hyunyoung Song31178b82015-02-24 14:12:51 -0800304 matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, orientation,
305 hotseat.getAllAppsButtonRank(), false /* all apps icon is ignored */);
306 countX = countX + 1;
307 } else if (keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) {
308 workspace.removeWorkspaceItem(v);
309 return consume;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800310 } else {
Hyunyoung Song31178b82015-02-24 14:12:51 -0800311 matrix = FocusLogic.createSparseMatrix(iconLayout);
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800312 }
313
314 // Process the focus.
315 int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX, countY, matrix,
316 iconIndex, pageIndex, pageCount);
317 View newIcon = null;
318 switch (newIconIndex) {
319 case FocusLogic.NOOP:
320 if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
321 newIcon = tabs;
322 }
323 break;
Hyunyoung Song38531712015-03-03 19:25:16 -0800324 case FocusLogic.PREVIOUS_PAGE_RIGHT_COLUMN:
325 int row = FocusLogic.findRow(matrix, iconIndex);
326 parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
327 if (parent != null) {
328 iconLayout = (CellLayout) parent.getParent();
329 matrix = FocusLogic.createSparseMatrix(iconLayout, orientation,
330 iconLayout.getCountX(), row);
331 newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX + 1, countY, matrix,
332 FocusLogic.PIVOT, pageIndex - 1, pageCount);
333 newIcon = parent.getChildAt(newIconIndex);
334 }
335 break;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800336 case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
337 parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
338 newIcon = parent.getChildAt(0);
339 workspace.snapToPage(pageIndex - 1);
Hyunyoung Song38531712015-03-03 19:25:16 -0800340 break;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800341 case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
342 parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
343 newIcon = parent.getChildAt(parent.getChildCount() - 1);
344 workspace.snapToPage(pageIndex - 1);
345 break;
346 case FocusLogic.NEXT_PAGE_FIRST_ITEM:
347 parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
348 newIcon = parent.getChildAt(0);
Hyunyoung Song31178b82015-02-24 14:12:51 -0800349 workspace.snapToPage(pageIndex + 1);
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800350 break;
Hyunyoung Song38531712015-03-03 19:25:16 -0800351 case FocusLogic.NEXT_PAGE_LEFT_COLUMN:
352 row = FocusLogic.findRow(matrix, iconIndex);
353 parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
354 if (parent != null) {
355 iconLayout = (CellLayout) parent.getParent();
356 matrix = FocusLogic.createSparseMatrix(iconLayout, orientation, -1, row);
357 newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX + 1, countY, matrix,
358 FocusLogic.PIVOT, pageIndex, pageCount);
359 newIcon = parent.getChildAt(newIconIndex);
360 }
361 break;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800362 case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
363 newIcon = parent.getChildAt(0);
364 break;
365 case FocusLogic.CURRENT_PAGE_LAST_ITEM:
366 newIcon = parent.getChildAt(parent.getChildCount() - 1);
367 break;
368 default:
369 // current page, some item.
370 if (0 <= newIconIndex && newIconIndex < parent.getChildCount()) {
371 newIcon = parent.getChildAt(newIconIndex);
372 } else if (parent.getChildCount() <= newIconIndex &&
373 newIconIndex < parent.getChildCount() + hotseatParent.getChildCount()) {
374 newIcon = hotseatParent.getChildAt(newIconIndex - parent.getChildCount());
375 }
376 break;
377 }
378 if (newIcon != null) {
379 newIcon.requestFocus();
380 playSoundEffect(keyCode, v);
381 }
382 return consume;
383 }
384
385 /**
386 * Handles key events for items in a Folder.
387 */
388 static boolean handleFolderKeyEvent(View v, int keyCode, KeyEvent e) {
389 boolean consume = FocusLogic.shouldConsume(keyCode);
390 if (e.getAction() == KeyEvent.ACTION_UP || !consume) {
391 return consume;
392 }
393 if (DEBUG) {
394 Log.v(TAG, String.format("Handle FOLDER keyevent=[%s].",
395 KeyEvent.keyCodeToString(keyCode)));
396 }
397
398 // Initialize the variables.
399 ShortcutAndWidgetContainer parent = (ShortcutAndWidgetContainer) v.getParent();
400 final CellLayout layout = (CellLayout) parent.getParent();
401 final ScrollView scrollView = (ScrollView) layout.getParent();
402 final Folder folder = (Folder) scrollView.getParent();
403 View title = folder.mFolderName;
404 Workspace workspace = (Workspace) v.getRootView().findViewById(R.id.workspace);
405 final int countX = layout.getCountX();
406 final int countY = layout.getCountY();
407 final int iconIndex = findIndexOfView(parent, v);
408 int pageIndex = workspace.indexOfChild(layout);
409 int pageCount = workspace.getChildCount();
Hyunyoung Song31178b82015-02-24 14:12:51 -0800410 int[][] map = FocusLogic.createFullMatrix(countX, countY, true /* incremental order */);
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800411
412 // Process the focus.
413 int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX, countY, map, iconIndex,
414 pageIndex, pageCount);
415 View newIcon = null;
416 switch (newIconIndex) {
417 case FocusLogic.NOOP:
418 if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
419 newIcon = title;
420 }
421 break;
422 case FocusLogic.PREVIOUS_PAGE_FIRST_ITEM:
423 case FocusLogic.PREVIOUS_PAGE_LAST_ITEM:
424 case FocusLogic.NEXT_PAGE_FIRST_ITEM:
425 case FocusLogic.CURRENT_PAGE_FIRST_ITEM:
426 case FocusLogic.CURRENT_PAGE_LAST_ITEM:
427 if (DEBUG) {
428 Log.v(TAG, "Page advance handling not supported on folder icons.");
429 }
430 break;
431 default: // current page some item.
432 newIcon = parent.getChildAt(newIconIndex);
433 break;
434 }
435 if (newIcon != null) {
436 newIcon.requestFocus();
437 playSoundEffect(keyCode, v);
438 }
439 return consume;
440 }
441
442 //
443 // Helper methods.
444 //
445
Winson Chung97d85d22011-04-13 11:27:36 -0700446 /**
Adam Cohenae4f1552011-10-20 00:15:42 -0700447 * Returns the Viewgroup containing page contents for the page at the index specified.
448 */
449 private static ViewGroup getAppsCustomizePage(ViewGroup container, int index) {
450 ViewGroup page = (ViewGroup) ((PagedView) container).getPageAt(index);
Winson Chungc58497e2013-09-03 17:48:37 -0700451 if (page instanceof CellLayout) {
Adam Cohenae4f1552011-10-20 00:15:42 -0700452 // There are two layers, a PagedViewCellLayout and PagedViewCellLayoutChildren
Winson Chungc58497e2013-09-03 17:48:37 -0700453 page = ((CellLayout) page).getShortcutsAndWidgets();
Adam Cohenae4f1552011-10-20 00:15:42 -0700454 }
455 return page;
456 }
457
458 /**
Winson Chung97d85d22011-04-13 11:27:36 -0700459 * Private helper method to get the CellLayoutChildren given a CellLayout index.
460 */
Michael Jurkaa52570f2012-03-20 03:18:20 -0700461 private static ShortcutAndWidgetContainer getCellLayoutChildrenForIndex(
462 ViewGroup container, int i) {
Sunny Goyalb3726d92014-08-20 16:58:17 -0700463 CellLayout parent = (CellLayout) container.getChildAt(i);
464 return parent.getShortcutsAndWidgets();
Winson Chung97d85d22011-04-13 11:27:36 -0700465 }
466
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800467 private static int findIndexOfView(ViewGroup parent, View v) {
468 for (int i = 0; i < parent.getChildCount(); i++) {
469 if (v != null && v.equals(parent.getChildAt(i))) {
470 return i;
Winson Chung97d85d22011-04-13 11:27:36 -0700471 }
472 }
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800473 return -1;
Winson Chung97d85d22011-04-13 11:27:36 -0700474 }
475
476 /**
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800477 * Helper method to be used for playing sound effects.
Winson Chung97d85d22011-04-13 11:27:36 -0700478 */
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800479 private static void playSoundEffect(int keyCode, View v) {
Winson Chung97d85d22011-04-13 11:27:36 -0700480 switch (keyCode) {
481 case KeyEvent.KEYCODE_DPAD_LEFT:
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800482 v.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
Winson Chung97d85d22011-04-13 11:27:36 -0700483 break;
484 case KeyEvent.KEYCODE_DPAD_RIGHT:
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800485 v.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
Winson Chung97d85d22011-04-13 11:27:36 -0700486 break;
487 case KeyEvent.KEYCODE_DPAD_DOWN:
Winson Chung97d85d22011-04-13 11:27:36 -0700488 case KeyEvent.KEYCODE_PAGE_DOWN:
Winson Chung97d85d22011-04-13 11:27:36 -0700489 case KeyEvent.KEYCODE_MOVE_END:
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800490 v.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN);
Adam Cohenac56cff2011-09-28 20:45:37 -0700491 break;
492 case KeyEvent.KEYCODE_DPAD_UP:
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800493 case KeyEvent.KEYCODE_PAGE_UP:
Adam Cohenac56cff2011-09-28 20:45:37 -0700494 case KeyEvent.KEYCODE_MOVE_HOME:
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800495 v.playSoundEffect(SoundEffectConstants.NAVIGATION_UP);
Adam Cohenac56cff2011-09-28 20:45:37 -0700496 break;
Hyunyoung Songee3e6a72015-02-20 14:25:27 -0800497 default:
Winson Chung97d85d22011-04-13 11:27:36 -0700498 break;
Winson Chung97d85d22011-04-13 11:27:36 -0700499 }
Winson Chung97d85d22011-04-13 11:27:36 -0700500 }
501}