Adding a keyboard shortcut delegarte to move logic outside of the launcher
Bug: 301142423
Test: compiling, this change is a no-op change
Change-Id: I2f5ee35a9ab645c26cc97669f6a745490fdfdb61
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index b8e7737..c454a91 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -43,7 +43,6 @@
import static com.android.launcher3.LauncherState.NO_SCALE;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.Utilities.postAsyncCallback;
-import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions;
import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
import static com.android.launcher3.config.FeatureFlags.MULTI_SELECT_EDIT_MODE;
import static com.android.launcher3.config.FeatureFlags.SHOW_DOT_PAGINATION;
@@ -114,7 +113,6 @@
import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.KeyboardShortcutGroup;
-import android.view.KeyboardShortcutInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MotionEvent;
@@ -137,7 +135,6 @@
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.accessibility.BaseAccessibilityDelegate.LauncherAction;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.allapps.AllAppsRecyclerView;
@@ -205,6 +202,7 @@
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.KeyboardShortcutsDelegate;
import com.android.launcher3.util.LockedUserState;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.PackageUserKey;
@@ -335,6 +333,7 @@
private static final boolean DESKTOP_MODE_SUPPORTED =
"1".equals(Utilities.getSystemProperty("persist.wm.debug.desktop_mode_2", "0"));
+ KeyboardShortcutsDelegate mKeyboardShortcutsDelegate = new KeyboardShortcutsDelegate(this);
@Thunk
Workspace<?> mWorkspace;
@Thunk
@@ -3183,84 +3182,51 @@
mOverlayManager.dump(prefix, writer);
}
+ /**
+ * Populates the list of shortcuts. Logic delegated to {@Link KeyboardShortcutsDelegate}.
+ *
+ * @param data The data list to populate with shortcuts.
+ * @param menu The current menu, which may be null.
+ * @param deviceId The id for the connected device the shortcuts should be provided for.
+ */
@Override
public void onProvideKeyboardShortcuts(
List<KeyboardShortcutGroup> data, Menu menu, int deviceId) {
-
- ArrayList<KeyboardShortcutInfo> shortcutInfos = new ArrayList<>();
- if (isInState(NORMAL)) {
- shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.all_apps_button_label),
- KeyEvent.KEYCODE_A, KeyEvent.META_CTRL_ON));
- shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.widget_button_text),
- KeyEvent.KEYCODE_W, KeyEvent.META_CTRL_ON));
- }
- getSupportedActions(this, getCurrentFocus()).forEach(la ->
- shortcutInfos.add(new KeyboardShortcutInfo(
- la.accessibilityAction.getLabel(), la.keyCode, KeyEvent.META_CTRL_ON)));
- if (!shortcutInfos.isEmpty()) {
- data.add(new KeyboardShortcutGroup(getString(R.string.home_screen), shortcutInfos));
- }
-
+ mKeyboardShortcutsDelegate.onProvideKeyboardShortcuts(data, menu, deviceId);
super.onProvideKeyboardShortcuts(data, menu, deviceId);
}
+ /**
+ * Logic delegated to {@Link KeyboardShortcutsDelegate}.
+ * @param keyCode The value in event.getKeyCode().
+ * @param event Description of the key event.
+ */
@Override
public boolean onKeyShortcut(int keyCode, KeyEvent event) {
- if (event.hasModifiers(KeyEvent.META_CTRL_ON)) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_A:
- if (isInState(NORMAL)) {
- getStateManager().goToState(ALL_APPS);
- return true;
- }
- break;
- case KeyEvent.KEYCODE_W:
- if (isInState(NORMAL)) {
- OptionsPopupView.openWidgets(this);
- return true;
- }
- break;
- default:
- for (LauncherAction la : getSupportedActions(this, getCurrentFocus())) {
- if (la.keyCode == keyCode) {
- return la.invokeFromKeyboard(getCurrentFocus());
- }
- }
- }
- }
- return super.onKeyShortcut(keyCode, event);
+ Boolean result = mKeyboardShortcutsDelegate.onKeyShortcut(keyCode, event);
+ return result != null ? result : super.onKeyShortcut(keyCode, event);
}
+ /**
+ * Logic delegated to {@Link KeyboardShortcutsDelegate}.
+ * @param keyCode The value in event.getKeyCode().
+ * @param event Description of the key event.
+ */
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_ESCAPE) {
- // Close any open floating views.
- closeOpenViews();
- return true;
- }
- return super.onKeyDown(keyCode, event);
+ Boolean result = mKeyboardShortcutsDelegate.onKeyDown(keyCode, event);
+ return result != null ? result : super.onKeyDown(keyCode, event);
}
+ /**
+ * Logic delegated to {@Link KeyboardShortcutsDelegate}.
+ * @param keyCode The value in event.getKeyCode().
+ * @param event Description of the key event.
+ */
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_MENU) {
- // KEYCODE_MENU is sent by some tests, for example
- // LauncherJankTests#testWidgetsContainerFling. Don't just remove its handling.
- if (!mDragController.isDragging() && !mWorkspace.isSwitchingState() &&
- isInState(NORMAL)) {
- // Close any open floating views.
- closeOpenViews();
-
- // Setting the touch point to (-1, -1) will show the options popup in the center of
- // the screen.
- if (Utilities.isRunningInTestHarness()) {
- Log.d(TestProtocol.PERMANENT_DIAG_TAG, "Opening options popup on key up");
- }
- showDefaultOptions(-1, -1);
- }
- return true;
- }
- return super.onKeyUp(keyCode, event);
+ Boolean result = mKeyboardShortcutsDelegate.onKeyUp(keyCode, event);
+ return result != null ? result : super.onKeyUp(keyCode, event);
}
/**
@@ -3338,7 +3304,7 @@
getStateManager().goToState(LauncherState.NORMAL);
}
- private void closeOpenViews() {
+ public void closeOpenViews() {
closeOpenViews(true);
}
diff --git a/src/com/android/launcher3/util/KeyboardShortcutsDelegate.java b/src/com/android/launcher3/util/KeyboardShortcutsDelegate.java
new file mode 100644
index 0000000..3ec339d
--- /dev/null
+++ b/src/com/android/launcher3/util/KeyboardShortcutsDelegate.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2023 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.launcher3.util;
+
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions;
+
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
+import android.view.KeyboardShortcutInfo;
+import android.view.Menu;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
+import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.launcher3.views.OptionsPopupView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Delegate to define the keyboard shortcuts.
+ */
+public class KeyboardShortcutsDelegate {
+
+ Launcher mLauncher;
+
+ public KeyboardShortcutsDelegate(Launcher launcher) {
+ mLauncher = launcher;
+ }
+
+ /**
+ * Populates the list of shortcuts.
+ */
+ public void onProvideKeyboardShortcuts(
+ List<KeyboardShortcutGroup> data, Menu menu, int deviceId) {
+ ArrayList<KeyboardShortcutInfo> shortcutInfos = new ArrayList<>();
+ if (mLauncher.isInState(NORMAL)) {
+ shortcutInfos.add(
+ new KeyboardShortcutInfo(mLauncher.getString(R.string.all_apps_button_label),
+ KeyEvent.KEYCODE_A, KeyEvent.META_CTRL_ON));
+ shortcutInfos.add(
+ new KeyboardShortcutInfo(mLauncher.getString(R.string.widget_button_text),
+ KeyEvent.KEYCODE_W, KeyEvent.META_CTRL_ON));
+ }
+ getSupportedActions(mLauncher, mLauncher.getCurrentFocus()).forEach(la ->
+ shortcutInfos.add(new KeyboardShortcutInfo(
+ la.accessibilityAction.getLabel(), la.keyCode, KeyEvent.META_CTRL_ON)));
+ if (!shortcutInfos.isEmpty()) {
+ data.add(new KeyboardShortcutGroup(mLauncher.getString(R.string.home_screen),
+ shortcutInfos));
+ }
+ }
+
+ /**
+ * Handles combinations of keys like ctrl+s or ctrl+c and runs before onKeyDown.
+ * @param keyCode code of the key being pressed.
+ * @see android.view.KeyEvent
+ * @return weather the event is already handled and if it should be passed to other components.
+ */
+ public Boolean onKeyShortcut(int keyCode, KeyEvent event) {
+ if (event.hasModifiers(KeyEvent.META_CTRL_ON)) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_A:
+ if (mLauncher.isInState(NORMAL)) {
+ mLauncher.getStateManager().goToState(ALL_APPS);
+ return true;
+ }
+ break;
+ case KeyEvent.KEYCODE_W:
+ if (mLauncher.isInState(NORMAL)) {
+ OptionsPopupView.openWidgets(mLauncher);
+ return true;
+ }
+ break;
+ default:
+ for (BaseAccessibilityDelegate.LauncherAction la : getSupportedActions(
+ mLauncher, mLauncher.getCurrentFocus())) {
+ if (la.keyCode == keyCode) {
+ return la.invokeFromKeyboard(mLauncher.getCurrentFocus());
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Handle key down event.
+ * @param keyCode code of the key being pressed.
+ * @see android.view.KeyEvent
+ */
+ public Boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_ESCAPE) {
+ // Close any open floating views.
+ mLauncher.closeOpenViews();
+ return true;
+ }
+ return null;
+ }
+
+ /**
+ * Handle key up event.
+ * @param keyCode code of the key being pressed.
+ * @see android.view.KeyEvent
+ */
+ public Boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_MENU) {
+ // KEYCODE_MENU is sent by some tests, for example
+ // LauncherJankTests#testWidgetsContainerFling. Don't just remove its handling.
+ if (!mLauncher.getDragController().isDragging()
+ && !mLauncher.getWorkspace().isSwitchingState()
+ && mLauncher.isInState(NORMAL)) {
+ // Close any open floating views.
+ mLauncher.closeOpenViews();
+
+ // Setting the touch point to (-1, -1) will show the options popup in the center of
+ // the screen.
+ if (Utilities.isRunningInTestHarness()) {
+ Log.d(TestProtocol.PERMANENT_DIAG_TAG, "Opening options popup on key up");
+ }
+ mLauncher.showDefaultOptions(-1, -1);
+ }
+ return true;
+ }
+ return null;
+ }
+}