From 16fd85629dca9b96bcb6e3e51c7dd64c923b02f3 Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Thu, 25 Mar 2021 12:31:23 -0700 Subject: [PATCH] Initial commit of 3 button work Home, Back and Recents basic functionality working Fixes: 180046394 Change-Id: Ifc5c767e35e88183500d14d14736eb40df436369 --- quickstep/res/drawable/ic_sysbar_back.xml | 28 +++++ quickstep/res/drawable/ic_sysbar_home.xml | 27 +++++ quickstep/res/drawable/ic_sysbar_recent.xml | 27 +++++ .../taskbar_icon_click_feedback_roundrect.xml | 26 +++++ quickstep/res/values/colors.xml | 1 + .../launcher3/taskbar/TaskbarController.java | 28 ++++- .../taskbar/TaskbarNavButtonController.java | 89 +++++++++++++++ .../launcher3/taskbar/TaskbarView.java | 105 ++++++++++++++++-- .../quickstep/SysUINavigationMode.java | 4 +- .../quickstep/TouchInteractionService.java | 14 +++ 10 files changed, 339 insertions(+), 10 deletions(-) create mode 100644 quickstep/res/drawable/ic_sysbar_back.xml create mode 100644 quickstep/res/drawable/ic_sysbar_home.xml create mode 100644 quickstep/res/drawable/ic_sysbar_recent.xml create mode 100644 quickstep/res/drawable/taskbar_icon_click_feedback_roundrect.xml create mode 100644 quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java diff --git a/quickstep/res/drawable/ic_sysbar_back.xml b/quickstep/res/drawable/ic_sysbar_back.xml new file mode 100644 index 0000000000..1eea6774b1 --- /dev/null +++ b/quickstep/res/drawable/ic_sysbar_back.xml @@ -0,0 +1,28 @@ + + + + + + + \ No newline at end of file diff --git a/quickstep/res/drawable/ic_sysbar_home.xml b/quickstep/res/drawable/ic_sysbar_home.xml new file mode 100644 index 0000000000..b4b397b59c --- /dev/null +++ b/quickstep/res/drawable/ic_sysbar_home.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/quickstep/res/drawable/ic_sysbar_recent.xml b/quickstep/res/drawable/ic_sysbar_recent.xml new file mode 100644 index 0000000000..f8c4778a2b --- /dev/null +++ b/quickstep/res/drawable/ic_sysbar_recent.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/quickstep/res/drawable/taskbar_icon_click_feedback_roundrect.xml b/quickstep/res/drawable/taskbar_icon_click_feedback_roundrect.xml new file mode 100644 index 0000000000..d6160def0f --- /dev/null +++ b/quickstep/res/drawable/taskbar_icon_click_feedback_roundrect.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml index 3bc8ddc0a8..167c7c3d0f 100644 --- a/quickstep/res/values/colors.xml +++ b/quickstep/res/values/colors.xml @@ -27,4 +27,5 @@ #101010 + #E0E0E0 \ No newline at end of file diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java index c93de00f4f..cf6cfb34e8 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java @@ -48,9 +48,12 @@ import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.states.StateAnimationConfig; +import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.views.ActivityContext; import com.android.quickstep.AnimatedFloat; +import com.android.quickstep.SysUINavigationMode; +import com.android.quickstep.TaskAnimationManager; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.WindowManagerWrapper; @@ -73,9 +76,13 @@ public class TaskbarController { private final TaskbarAnimationController mTaskbarAnimationController; private final TaskbarHotseatController mHotseatController; private final TaskbarDragController mDragController; + private final TaskbarNavButtonController mNavButtonController; // Initialized in init(). private WindowManager.LayoutParams mWindowLayoutParams; + private SysUINavigationMode.Mode mNavMode = SysUINavigationMode.Mode.NO_BUTTON; + private final SysUINavigationMode.NavigationModeChangeListener mNavigationModeChangeListener = + this::onNavModeChanged; private @Nullable Animator mAnimator; private boolean mIsAnimatingToLauncher; @@ -89,6 +96,7 @@ public class TaskbarController { mTaskbarViewInApp.construct(createTaskbarViewCallbacks()); mTaskbarViewOnHome = taskbarViewOnHome; mTaskbarViewOnHome.construct(createTaskbarViewCallbacks()); + mNavButtonController = new TaskbarNavButtonController(launcher); mWindowManager = mLauncher.getWindowManager(); mTaskbarSize = new Point(MATCH_PARENT, mLauncher.getDeviceProfile().taskbarSize); mTaskbarStateHandler = mLauncher.getTaskbarStateHandler(); @@ -212,6 +220,11 @@ public class TaskbarController { alignRealHotseatWithTaskbar(); } } + + @Override + public void onNavigationButtonClick(@TaskbarButton int buttonType) { + mNavButtonController.onButtonClick(buttonType); + } }; } @@ -228,8 +241,10 @@ public class TaskbarController { * Initializes the Taskbar, including adding it to the screen. */ public void init() { - mTaskbarViewInApp.init(mHotseatController.getNumHotseatIcons()); - mTaskbarViewOnHome.init(mHotseatController.getNumHotseatIcons()); + mNavMode = SysUINavigationMode.INSTANCE.get(mLauncher) + .addModeChangeListener(mNavigationModeChangeListener); + mTaskbarViewInApp.init(mHotseatController.getNumHotseatIcons(), mNavMode); + mTaskbarViewOnHome.init(mHotseatController.getNumHotseatIcons(), mNavMode); mTaskbarContainerView.init(mTaskbarViewInApp); addToWindowManager(); mTaskbarStateHandler.setTaskbarCallbacks(createTaskbarStateHandlerCallbacks()); @@ -278,6 +293,8 @@ public class TaskbarController { mHotseatController.cleanup(); setWhichTaskbarViewIsVisible(null); + SysUINavigationMode.INSTANCE.get(mLauncher) + .removeModeChangeListener(mNavigationModeChangeListener); } private void removeFromWindowManager() { @@ -315,6 +332,12 @@ public class TaskbarController { mWindowManager.addView(mTaskbarContainerView, mWindowLayoutParams); } + private void onNavModeChanged(SysUINavigationMode.Mode newMode) { + mNavMode = newMode; + cleanup(); + init(); + } + /** * Should be called from onResume() and onPause(), and animates the Taskbar accordingly. */ @@ -507,6 +530,7 @@ public class TaskbarController { /** Returns how much to scale non-icon elements such as spacing and dividers. */ float getNonIconScale(TaskbarView taskbarView); void onItemPositionsChanged(TaskbarView taskbarView); + void onNavigationButtonClick(@TaskbarButton int buttonType); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java new file mode 100644 index 0000000000..cf8ff381b1 --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java @@ -0,0 +1,89 @@ +/* + * Copyright 2021 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.taskbar; + +import android.content.Context; +import android.content.Intent; + +import androidx.annotation.IntDef; + +import com.android.quickstep.OverviewCommandHelper; +import com.android.quickstep.SystemUiProxy; +import com.android.quickstep.TouchInteractionService; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Controller for 3 button mode in the taskbar. + * Handles all the functionality of the various buttons, making/routing the right calls into + * launcher or sysui/system. + * + * TODO: Create callbacks to hook into UI layer since state will change for more context buttons/ + * assistant invocation. + */ +public class TaskbarNavButtonController { + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + BUTTON_BACK, + BUTTON_HOME, + BUTTON_RECENTS + }) + + public @interface TaskbarButton {} + + static final int BUTTON_BACK = 1; + static final int BUTTON_HOME = BUTTON_BACK << 1; + static final int BUTTON_RECENTS = BUTTON_HOME << 1; + + + private final Context mContext; + + public TaskbarNavButtonController(Context context) { + mContext = context; + } + + public void onButtonClick(@TaskbarButton int buttonType) { + switch (buttonType) { + case BUTTON_BACK: + executeBack(); + break; + case BUTTON_HOME: + navigateHome(); + break; + case BUTTON_RECENTS: + navigateToOverview();; + break; + } + } + + private void navigateHome() { + mContext.startActivity(new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_HOME) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + + private void navigateToOverview() { + TouchInteractionService.getInstance().getOverviewCommandHelper() + .addCommand(OverviewCommandHelper.TYPE_SHOW); + } + + private void executeBack() { + SystemUiProxy.INSTANCE.getNoCreate().onBackPressed(); + } + +} diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index 60a7add7fd..5be25b9bbb 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -15,6 +15,13 @@ */ package com.android.launcher3.taskbar; +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; + +import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK; +import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME; +import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_RECENTS; + import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.LayoutTransition; @@ -24,11 +31,14 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.RectF; +import android.os.SystemProperties; import android.util.AttributeSet; import android.view.DragEvent; +import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import android.widget.ImageView; import android.widget.LinearLayout; import androidx.annotation.LayoutRes; @@ -45,12 +55,17 @@ import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.views.ActivityContext; +import com.android.quickstep.SysUINavigationMode; /** * Hosts the Taskbar content such as Hotseat and Recent Apps. Drawn on top of other apps. */ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconParent, Insettable { + + private static final boolean ENABLE_THREE_BUTTON_TASKBAR = + SystemProperties.getBoolean("persist.debug.taskbar_three_button", false); + private final int mIconTouchSize; private final boolean mIsRtl; private final int mTouchSlop; @@ -69,6 +84,8 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa private int mHotseatStartIndex; private int mHotseatEndIndex; + private LinearLayout mButtonRegion; + // Delegate touches to the closest view if within mIconTouchSize. private boolean mDelegateTargeted; private View mDelegateView; @@ -77,6 +94,8 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa // Only non-null when the corresponding Folder is open. private @Nullable FolderIcon mLeaveBehindFolderIcon; + private int mNavButtonStartIndex; + public TaskbarView(@NonNull Context context) { this(context, null); } @@ -107,8 +126,18 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa mItemMarginLeftRight = Math.round(mItemMarginLeftRight * mNonIconScale); } - protected void init(int numHotseatIcons) { - mHotseatStartIndex = 0; + protected void init(int numHotseatIcons, SysUINavigationMode.Mode newMode) { + // TODO: check if buttons on left + if (newMode == SysUINavigationMode.Mode.THREE_BUTTONS && ENABLE_THREE_BUTTON_TASKBAR) { + // 3 button + mNavButtonStartIndex = 0; + createNavButtons(); + } else { + mNavButtonStartIndex = -1; + removeNavButtons(); + } + + mHotseatStartIndex = mNavButtonStartIndex + 1; mHotseatEndIndex = mHotseatStartIndex + numHotseatIcons - 1; updateHotseatItems(new ItemInfo[numHotseatIcons]); @@ -185,11 +214,11 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa if (hotseatView == null || hotseatView.getSourceLayoutResId() != expectedLayoutResId || needsReinflate) { removeView(hotseatView); - ActivityContext activityContext = ActivityContext.lookupContext(getContext()); + ActivityContext activityContext = getActivityContext(); if (isFolder) { FolderInfo folderInfo = (FolderInfo) hotseatItemInfo; FolderIcon folderIcon = FolderIcon.inflateFolderAndIcon(expectedLayoutResId, - ActivityContext.lookupContext(getContext()), this, folderInfo); + getActivityContext(), this, folderInfo); folderIcon.setTextVisible(false); hotseatView = folderIcon; } else { @@ -335,12 +364,71 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa return findDelegateView(xInOurCoordinates, yInOurCoorindates) != null; } + private void removeNavButtons() { + if (mButtonRegion != null) { + mButtonRegion.removeAllViews(); + removeView(mButtonRegion); + } // else We've never been in 3 button. Woah Scoob! + } + + /** + * Add back/home/recents buttons into a single ViewGroup that will be inserted at + * {@param navButtonStartIndex} + */ + private void createNavButtons() { + ActivityContext context = getActivityContext(); + if (mButtonRegion == null) { + mButtonRegion = new LinearLayout(getContext()); + } else { + mButtonRegion.removeAllViews(); + } + mButtonRegion.setVisibility(VISIBLE); + LayoutParams regionParams = new LayoutParams(WRAP_CONTENT, MATCH_PARENT); + regionParams.gravity = Gravity.START; // check left/right preference + regionParams.setMargins(mItemMarginLeftRight, 0, mItemMarginLeftRight, 0); + + LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams( + context.getDeviceProfile().iconSizePx, + context.getDeviceProfile().iconSizePx + ); + buttonParams.gravity = Gravity.CENTER; + + // Back button + ImageView backButton = new ImageView(getContext()); + backButton.setImageResource(R.drawable.ic_sysbar_back); + backButton.setBackgroundResource(R.drawable.taskbar_icon_click_feedback_roundrect); + backButton.setPadding(mItemMarginLeftRight, 0, mItemMarginLeftRight, 0); + backButton.setOnClickListener(view -> mControllerCallbacks.onNavigationButtonClick( + BUTTON_BACK)); + mButtonRegion.addView(backButton, buttonParams); + + // Home button + ImageView homeButton = new ImageView(getContext()); + homeButton.setImageResource(R.drawable.ic_sysbar_home); + homeButton.setBackgroundResource(R.drawable.taskbar_icon_click_feedback_roundrect); + homeButton.setPadding(mItemMarginLeftRight, 0, mItemMarginLeftRight, 0); + homeButton.setOnClickListener(view -> mControllerCallbacks.onNavigationButtonClick( + BUTTON_HOME)); + mButtonRegion.addView(homeButton, buttonParams); + + // Recents button + ImageView recentsButton = new ImageView(getContext()); + recentsButton.setImageResource(R.drawable.ic_sysbar_recent); + recentsButton.setBackgroundResource(R.drawable.taskbar_icon_click_feedback_roundrect); + recentsButton.setPadding(mItemMarginLeftRight, 0, mItemMarginLeftRight, 0); + recentsButton.setOnClickListener(view -> mControllerCallbacks.onNavigationButtonClick( + BUTTON_RECENTS)); + mButtonRegion.addView(recentsButton, buttonParams); + + addView(mButtonRegion, mNavButtonStartIndex); + } + @Override public boolean onDragEvent(DragEvent event) { switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: mIsDraggingItem = true; - AbstractFloatingView.closeAllOpenViews(ActivityContext.lookupContext(getContext())); + AbstractFloatingView.closeAllOpenViews(getActivityContext()); return true; case DragEvent.ACTION_DRAG_ENDED: mIsDraggingItem = false; @@ -407,12 +495,15 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa } private View inflate(@LayoutRes int layoutResId) { - return ActivityContext.lookupContext(getContext()).getLayoutInflater() - .inflate(layoutResId, this, false); + return getActivityContext().getLayoutInflater().inflate(layoutResId, this, false); } @Override public void setInsets(Rect insets) { // Ignore, we just implement Insettable to draw behind system insets. } + + private T getActivityContext() { + return ActivityContext.lookupContext(getContext()); + } } diff --git a/quickstep/src/com/android/quickstep/SysUINavigationMode.java b/quickstep/src/com/android/quickstep/SysUINavigationMode.java index efec037b92..74f4bea2a8 100644 --- a/quickstep/src/com/android/quickstep/SysUINavigationMode.java +++ b/quickstep/src/com/android/quickstep/SysUINavigationMode.java @@ -34,6 +34,7 @@ import com.android.launcher3.util.MainThreadInitializedObject; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * Observer for the resource config that specifies the navigation bar mode. @@ -75,7 +76,8 @@ public class SysUINavigationMode { private int mNavBarGesturalHeight; private int mNavBarLargerGesturalHeight; - private final List mChangeListeners = new ArrayList<>(); + private final List mChangeListeners = + new CopyOnWriteArrayList<>(); private final List mOneHandedOverlayChangeListeners = new ArrayList<>(); diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 4fc97702ed..afda3b9486 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -259,6 +259,7 @@ public class TouchInteractionService extends Service implements PluginListener