1 /* 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 package com.android.documentsui; 17 18 import static com.android.documentsui.base.SharedMinimal.DEBUG; 19 20 import android.util.Log; 21 import android.view.KeyEvent; 22 23 import androidx.recyclerview.selection.SelectionTracker; 24 25 import com.android.documentsui.base.Events; 26 import com.android.documentsui.base.Features; 27 import com.android.documentsui.base.Procedure; 28 import com.android.documentsui.dirlist.FocusHandler; 29 30 /** 31 * Handle common input events. 32 */ 33 public class SharedInputHandler { 34 35 private static final String TAG = "SharedInputHandler"; 36 37 private final FocusHandler mFocusManager; 38 private final Procedure mSearchCanceler; 39 private final Procedure mDirPopper; 40 private final Features mFeatures; 41 private final SelectionTracker<String> mSelectionMgr; 42 private final DrawerController mDrawer; 43 SharedInputHandler( FocusHandler focusHandler, SelectionTracker<String> selectionMgr, Procedure searchCanceler, Procedure dirPopper, Features features, DrawerController drawer)44 public SharedInputHandler( 45 FocusHandler focusHandler, 46 SelectionTracker<String> selectionMgr, 47 Procedure searchCanceler, 48 Procedure dirPopper, 49 Features features, 50 DrawerController drawer) { 51 mFocusManager = focusHandler; 52 mSearchCanceler = searchCanceler; 53 mSelectionMgr = selectionMgr; 54 mDirPopper = dirPopper; 55 mFeatures = features; 56 mDrawer = drawer; 57 } 58 onKeyDown(int keyCode, KeyEvent event)59 public boolean onKeyDown(int keyCode, KeyEvent event) { 60 switch (keyCode) { 61 // Unhandled ESC keys end up being rethrown back at us as BACK keys. So by returning 62 // true, we make sure it always does no-op. 63 case KeyEvent.KEYCODE_ESCAPE: 64 return onEscape(); 65 66 case KeyEvent.KEYCODE_DEL: 67 return onDelete(); 68 69 // This is the Android back button, not backspace. 70 case KeyEvent.KEYCODE_BACK: 71 return onBack(); 72 73 case KeyEvent.KEYCODE_TAB: 74 return onTab(); 75 76 default: 77 // Instead of duplicating the switch-case in #isNavigationKeyCode, best just to 78 // leave it here. 79 if (Events.isNavigationKeyCode(keyCode)) { 80 // Forward all unclaimed navigation keystrokes to the directory list. 81 // This causes any stray navigation keystrokes to focus the content pane, 82 // which is probably what the user is trying to do. 83 mFocusManager.focusDirectoryList(); 84 return true; 85 } 86 return false; 87 } 88 } 89 onTab()90 private boolean onTab() { 91 if (!mFeatures.isSystemKeyboardNavigationEnabled()) { 92 // Tab toggles focus on the navigation drawer. 93 // This should only be called in pre-O devices, since O has built-in keyboard 94 // navigation 95 // support. 96 mFocusManager.advanceFocusArea(); 97 return true; 98 } 99 100 return false; 101 } 102 onDelete()103 private boolean onDelete() { 104 mDirPopper.run(); 105 return true; 106 } 107 onBack()108 private boolean onBack() { 109 if (mDrawer.isPresent() && mDrawer.isOpen()) { 110 mDrawer.setOpen(false); 111 return true; 112 } 113 114 if (mSearchCanceler.run()) { 115 return true; 116 } 117 118 if (mSelectionMgr.hasSelection()) { 119 if (DEBUG) { 120 Log.d(TAG, "Back pressed. Clearing existing selection."); 121 } 122 mSelectionMgr.clearSelection(); 123 return true; 124 } 125 126 return mDirPopper.run(); 127 } 128 onEscape()129 private boolean onEscape() { 130 if (mSearchCanceler.run()) { 131 return true; 132 } 133 134 if (mSelectionMgr.hasSelection()) { 135 if (DEBUG) { 136 Log.d(TAG, "ESC pressed. Clearing existing selection."); 137 } 138 mSelectionMgr.clearSelection(); 139 return true; 140 } 141 142 return true; 143 } 144 } 145