blob: a70a805dd7715645da23ac86060d6e34a9079231 [file] [log] [blame]
Steve McKay04718262016-11-08 11:01:35 -08001/*
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 */
16package com.android.documentsui;
17
Felipe Leme9de58072018-01-19 16:40:04 -080018import static com.android.documentsui.base.SharedMinimal.DEBUG;
Ben Lin0902f072017-03-13 18:25:29 -070019
20import android.util.Log;
Steve McKay04718262016-11-08 11:01:35 -080021import android.view.KeyEvent;
22
Riddle Hsu0c375982018-06-21 22:06:43 +080023import androidx.recyclerview.selection.SelectionTracker;
24
Steve McKay04718262016-11-08 11:01:35 -080025import com.android.documentsui.base.Events;
Steve McKay98f8c5f2017-03-03 13:52:14 -080026import com.android.documentsui.base.Features;
Steve McKay04718262016-11-08 11:01:35 -080027import com.android.documentsui.base.Procedure;
Ben Lin0902f072017-03-13 18:25:29 -070028import com.android.documentsui.dirlist.FocusHandler;
Steve McKay04718262016-11-08 11:01:35 -080029
Riddle Hsu0c375982018-06-21 22:06:43 +080030/**
31 * Handle common input events.
32 */
Steve McKay04718262016-11-08 11:01:35 -080033public class SharedInputHandler {
34
Ben Lin0902f072017-03-13 18:25:29 -070035 private static final String TAG = "SharedInputHandler";
36
37 private final FocusHandler mFocusManager;
38 private final Procedure mSearchCanceler;
Steve McKay98f8c5f2017-03-03 13:52:14 -080039 private final Procedure mDirPopper;
Bill Lin35bfbef2019-08-05 16:09:53 +080040 private final Runnable mSearchExecutor;
Steve McKay98f8c5f2017-03-03 13:52:14 -080041 private final Features mFeatures;
Riddle Hsu0c375982018-06-21 22:06:43 +080042 private final SelectionTracker<String> mSelectionMgr;
Rhed Jao76a9d712018-05-16 15:32:59 +080043 private final DrawerController mDrawer;
Steve McKay04718262016-11-08 11:01:35 -080044
Ben Lin0902f072017-03-13 18:25:29 -070045 public SharedInputHandler(
46 FocusHandler focusHandler,
Riddle Hsu0c375982018-06-21 22:06:43 +080047 SelectionTracker<String> selectionMgr,
Ben Lin0902f072017-03-13 18:25:29 -070048 Procedure searchCanceler,
49 Procedure dirPopper,
Rhed Jao76a9d712018-05-16 15:32:59 +080050 Features features,
Bill Lin35bfbef2019-08-05 16:09:53 +080051 DrawerController drawer,
52 Runnable searchExcutor) {
Ben Lin0902f072017-03-13 18:25:29 -070053 mFocusManager = focusHandler;
54 mSearchCanceler = searchCanceler;
55 mSelectionMgr = selectionMgr;
Steve McKay04718262016-11-08 11:01:35 -080056 mDirPopper = dirPopper;
Steve McKay98f8c5f2017-03-03 13:52:14 -080057 mFeatures = features;
Rhed Jao76a9d712018-05-16 15:32:59 +080058 mDrawer = drawer;
Bill Lin35bfbef2019-08-05 16:09:53 +080059 mSearchExecutor = searchExcutor;
Steve McKay04718262016-11-08 11:01:35 -080060 }
61
62 public boolean onKeyDown(int keyCode, KeyEvent event) {
Ben Lin0902f072017-03-13 18:25:29 -070063 switch (keyCode) {
64 // Unhandled ESC keys end up being rethrown back at us as BACK keys. So by returning
65 // true, we make sure it always does no-op.
66 case KeyEvent.KEYCODE_ESCAPE:
67 return onEscape();
68
69 case KeyEvent.KEYCODE_DEL:
70 return onDelete();
71
72 // This is the Android back button, not backspace.
73 case KeyEvent.KEYCODE_BACK:
74 return onBack();
75
76 case KeyEvent.KEYCODE_TAB:
77 return onTab();
78
Bill Lin35bfbef2019-08-05 16:09:53 +080079 case KeyEvent.KEYCODE_SEARCH:
80 mSearchExecutor.run();
81 return true;
82
Ben Lin0902f072017-03-13 18:25:29 -070083 default:
84 // Instead of duplicating the switch-case in #isNavigationKeyCode, best just to
85 // leave it here.
86 if (Events.isNavigationKeyCode(keyCode)) {
87 // Forward all unclaimed navigation keystrokes to the directory list.
88 // This causes any stray navigation keystrokes to focus the content pane,
89 // which is probably what the user is trying to do.
90 mFocusManager.focusDirectoryList();
91 return true;
92 }
93 return false;
94 }
95 }
96
97 private boolean onTab() {
98 if (!mFeatures.isSystemKeyboardNavigationEnabled()) {
Steve McKay04718262016-11-08 11:01:35 -080099 // Tab toggles focus on the navigation drawer.
Ben Lin0902f072017-03-13 18:25:29 -0700100 // This should only be called in pre-O devices, since O has built-in keyboard
101 // navigation
Ben Lin340ab172017-01-27 11:41:26 -0800102 // support.
Steve McKay04718262016-11-08 11:01:35 -0800103 mFocusManager.advanceFocusArea();
104 return true;
Steve McKay04718262016-11-08 11:01:35 -0800105 }
106
107 return false;
108 }
Ben Lin0902f072017-03-13 18:25:29 -0700109
110 private boolean onDelete() {
111 mDirPopper.run();
112 return true;
113 }
114
115 private boolean onBack() {
Rhed Jao76a9d712018-05-16 15:32:59 +0800116 if (mDrawer.isPresent() && mDrawer.isOpen()) {
117 mDrawer.setOpen(false);
118 return true;
119 }
120
Ben Lin0902f072017-03-13 18:25:29 -0700121 if (mSearchCanceler.run()) {
122 return true;
123 }
124
125 if (mSelectionMgr.hasSelection()) {
Jason Chang96f886b2019-03-29 17:59:02 +0800126 if (DEBUG) {
127 Log.d(TAG, "Back pressed. Clearing existing selection.");
128 }
Ben Lin0902f072017-03-13 18:25:29 -0700129 mSelectionMgr.clearSelection();
130 return true;
131 }
132
133 return mDirPopper.run();
134 }
135
136 private boolean onEscape() {
137 if (mSearchCanceler.run()) {
138 return true;
139 }
140
141 if (mSelectionMgr.hasSelection()) {
Jason Chang96f886b2019-03-29 17:59:02 +0800142 if (DEBUG) {
143 Log.d(TAG, "ESC pressed. Clearing existing selection.");
144 }
Ben Lin0902f072017-03-13 18:25:29 -0700145 mSelectionMgr.clearSelection();
146 return true;
147 }
148
149 return true;
150 }
Steve McKay04718262016-11-08 11:01:35 -0800151}