diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 0c1235cbf4..e19042e8a4 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -29,7 +29,6 @@ import static com.android.launcher3.AbstractFloatingView.TYPE_ON_BOARD_POPUP; import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE; import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY; import static com.android.launcher3.Flags.enableCursorHoverStates; -import static com.android.launcher3.Flags.enableTaskbarCustomization; import static com.android.launcher3.Utilities.calculateTextHeight; import static com.android.launcher3.Utilities.isRunningInTestHarness; import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION; @@ -230,15 +229,12 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mNavigationBarPanelContext = navigationBarPanelContext; applyDeviceProfile(launcherDp); final Resources resources = getResources(); - - if (enableTaskbarCustomization()) { - mTaskbarFeatureEvaluator = TaskbarFeatureEvaluator.getInstance(this); - mTaskbarSpecsEvaluator = new TaskbarSpecsEvaluator( - this, - mTaskbarFeatureEvaluator, - mDeviceProfile.inv.numRows, - mDeviceProfile.inv.numColumns); - } + mTaskbarFeatureEvaluator = TaskbarFeatureEvaluator.getInstance(this); + mTaskbarSpecsEvaluator = new TaskbarSpecsEvaluator( + this, + mTaskbarFeatureEvaluator, + mDeviceProfile.inv.numRows, + mDeviceProfile.inv.numColumns); mImeDrawsImeNavBar = getBoolByName(IME_DRAWS_IME_NAV_BAR_RES_NAME, resources, false); mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode", @@ -1761,12 +1757,10 @@ public class TaskbarActivityContext extends BaseTaskbarContext { return mControllers.taskbarStashController.isInStashedLauncherState(); } - @Nullable public TaskbarFeatureEvaluator getTaskbarFeatureEvaluator() { return mTaskbarFeatureEvaluator; } - @Nullable public TaskbarSpecsEvaluator getTaskbarSpecsEvaluator() { return mTaskbarSpecsEvaluator; } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt index a635537907..b5a33147ce 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDividerPopupView.kt @@ -169,8 +169,11 @@ constructor( override fun addArrow() { super.addArrow() + val location = IntArray(2) + popupContainer.getLocationInDragLayer(dividerView, location) + val dividerViewX = location[0].toFloat() // Change arrow location to the middle of popup. - mArrow.x = (dividerView.x + dividerView.width / 2) - (mArrowWidth / 2) + mArrow.x = (dividerViewX + dividerView.width / 2) - (mArrowWidth / 2) } override fun updateArrowColor() { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index 54a7fdc613..8b8b4da27a 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -22,10 +22,8 @@ import static com.android.launcher3.Flags.enableCursorHoverStates; import static com.android.launcher3.Flags.enableRecentsInTaskbar; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER; -import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR; import static com.android.launcher3.config.FeatureFlags.enableTaskbarPinning; import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR; -import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import android.content.Context; import android.content.res.Resources; @@ -39,12 +37,9 @@ import android.view.InputDevice; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; -import androidx.annotation.DimenRes; -import androidx.annotation.DrawableRes; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -62,13 +57,12 @@ import com.android.launcher3.model.data.CollectionInfo; 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.taskbar.customization.TaskbarAllAppsButtonContainer; +import com.android.launcher3.taskbar.customization.TaskbarDividerContainer; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.util.Themes; import com.android.launcher3.views.ActivityContext; -import com.android.launcher3.views.IconButtonView; -import com.android.quickstep.DeviceConfigWrapper; -import com.android.quickstep.util.AssistStateManager; import com.android.quickstep.util.DesktopTask; import com.android.quickstep.util.GroupTask; import com.android.systemui.shared.recents.model.Task; @@ -100,16 +94,13 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar private View.OnLongClickListener mIconLongClickListener; // Only non-null when the corresponding Folder is open. - private @Nullable FolderIcon mLeaveBehindFolderIcon; + @Nullable private FolderIcon mLeaveBehindFolderIcon; // Only non-null when device supports having an All Apps button. - private @Nullable IconButtonView mAllAppsButton; - private Runnable mAllAppsTouchRunnable; - private long mAllAppsButtonTouchDelayMs; - private boolean mAllAppsTouchTriggered; + @Nullable private final TaskbarAllAppsButtonContainer mAllAppsButtonContainer; - // Only non-null when device supports having an All Apps button, or Recent Apps. - private @Nullable IconButtonView mTaskbarDivider; + // Only non-null when device supports having an All Apps button. + @Nullable private TaskbarDividerContainer mTaskbarDividerContainer; /** * Whether the divider is between Hotseat icons and Recents, @@ -173,55 +164,14 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar // Needed to draw folder leave-behind when opening one. setWillNotDraw(false); - mAllAppsButton = (IconButtonView) LayoutInflater.from(context) - .inflate(R.layout.taskbar_all_apps_button, this, false); - mAllAppsButton.setIconDrawable(resources.getDrawable( - getAllAppsButton(isTransientTaskbar))); - mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding); - mAllAppsButton.setForegroundTint( - mActivityContext.getColor(R.color.all_apps_button_color)); + mAllAppsButtonContainer = new TaskbarAllAppsButtonContainer(context); if (enableTaskbarPinning() || enableRecentsInTaskbar()) { - mTaskbarDivider = (IconButtonView) LayoutInflater.from(context).inflate( - R.layout.taskbar_divider, - this, false); - mTaskbarDivider.setIconDrawable( - resources.getDrawable(R.drawable.taskbar_divider_button)); - mTaskbarDivider.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding); + mTaskbarDividerContainer = new TaskbarDividerContainer(context); } // TODO: Disable touch events on QSB otherwise it can crash. mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false); - - // Default long press (touch) delay = 400ms - mAllAppsButtonTouchDelayMs = ViewConfiguration.getLongPressTimeout(); - } - - @DrawableRes - private int getAllAppsButton(boolean isTransientTaskbar) { - boolean shouldSelectTransientIcon = - (isTransientTaskbar || enableTaskbarPinning()) - && !mActivityContext.isThreeButtonNav(); - if (ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) { - return shouldSelectTransientIcon - ? R.drawable.ic_transient_taskbar_all_apps_search_button - : R.drawable.ic_taskbar_all_apps_search_button; - } else { - return shouldSelectTransientIcon - ? R.drawable.ic_transient_taskbar_all_apps_button - : R.drawable.ic_taskbar_all_apps_button; - } - } - - @DimenRes - public int getAllAppsButtonTranslationXOffset(boolean isTransientTaskbar) { - if (isTransientTaskbar) { - return R.dimen.transient_taskbar_all_apps_button_translation_x_offset; - } else { - return ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get() - ? R.dimen.taskbar_all_apps_search_button_translation_x_offset - : R.dimen.taskbar_all_apps_button_translation_x_offset; - } } @Override @@ -306,27 +256,11 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar mIconClickListener = mControllerCallbacks.getIconOnClickListener(); mIconLongClickListener = mControllerCallbacks.getIconOnLongClickListener(); - if (mAllAppsButton != null) { - mAllAppsButton.setOnClickListener(this::onAllAppsButtonClick); - mAllAppsButton.setOnLongClickListener(this::onAllAppsButtonLongClick); - mAllAppsButton.setOnTouchListener(this::onAllAppsButtonTouch); - mAllAppsButton.setHapticFeedbackEnabled( - mControllerCallbacks.isAllAppsButtonHapticFeedbackEnabled()); - mAllAppsTouchRunnable = () -> { - mControllerCallbacks.triggerAllAppsButtonLongClick(); - mAllAppsTouchTriggered = true; - }; - AssistStateManager assistStateManager = AssistStateManager.INSTANCE.get(mContext); - if (DeviceConfigWrapper.get().getCustomLpaaThresholds() - && assistStateManager.getLPNHDurationMillis().isPresent()) { - mAllAppsButtonTouchDelayMs = assistStateManager.getLPNHDurationMillis().get(); - } + if (mAllAppsButtonContainer != null) { + mAllAppsButtonContainer.setUpCallbacks(callbacks); } - if (mTaskbarDivider != null && !mActivityContext.isThreeButtonNav()) { - mTaskbarDivider.setOnLongClickListener( - mControllerCallbacks.getTaskbarDividerLongClickListener()); - mTaskbarDivider.setOnTouchListener( - mControllerCallbacks.getTaskbarDividerRightClickListener()); + if (mTaskbarDividerContainer != null && callbacks.supportsDividerLongPress()) { + mTaskbarDividerContainer.setUpCallbacks(callbacks); } } @@ -348,11 +282,11 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar int numViewsAnimated = 0; mAddedDividerForRecents = false; - if (mAllAppsButton != null) { - removeView(mAllAppsButton); + if (mAllAppsButtonContainer != null) { + removeView(mAllAppsButtonContainer); - if (mTaskbarDivider != null) { - removeView(mTaskbarDivider); + if (mTaskbarDividerContainer != null) { + removeView(mTaskbarDividerContainer); } } removeView(mQsb); @@ -439,8 +373,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar nextViewIndex++; } - if (mTaskbarDivider != null && !recentTasks.isEmpty()) { - addView(mTaskbarDivider, nextViewIndex++); + if (mTaskbarDividerContainer != null && !recentTasks.isEmpty()) { + addView(mTaskbarDividerContainer, nextViewIndex++); mAddedDividerForRecents = true; } @@ -504,12 +438,14 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar removeAndRecycle(getChildAt(nextViewIndex)); } - if (mAllAppsButton != null) { - addView(mAllAppsButton, mIsRtl ? hotseatItemInfos.length : 0); + if (mAllAppsButtonContainer != null) { + addView(mAllAppsButtonContainer, mIsRtl ? hotseatItemInfos.length : 0); // If there are no recent tasks, add divider after All Apps (unless it's the only view). - if (!mAddedDividerForRecents && mTaskbarDivider != null && getChildCount() > 1) { - addView(mTaskbarDivider, mIsRtl ? (getChildCount() - 1) : 1); + if (!mAddedDividerForRecents + && mTaskbarDividerContainer != null + && getChildCount() > 1) { + addView(mTaskbarDividerContainer, mIsRtl ? (getChildCount() - 1) : 1); } } if (mActivityContext.getDeviceProfile().isQsbInline) { @@ -637,7 +573,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar int qsbTop = (bottom - top - deviceProfile.hotseatQsbHeight) / 2; int qsbBottom = qsbTop + deviceProfile.hotseatQsbHeight; child.layout(qsbStart, qsbTop, qsbEnd, qsbBottom); - } else if (child == mTaskbarDivider) { + } else if (child == mTaskbarDividerContainer) { iconEnd += mItemMarginLeftRight; int iconStart = iconEnd - mIconTouchSize; child.layout(iconStart, mIconLayoutBounds.top, iconEnd, mIconLayoutBounds.bottom); @@ -727,16 +663,16 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar * Returns the all apps button in the taskbar. */ @Nullable - public View getAllAppsButtonView() { - return mAllAppsButton; + public TaskbarAllAppsButtonContainer getAllAppsButtonContainer() { + return mAllAppsButtonContainer; } /** * Returns the taskbar divider in the taskbar. */ @Nullable - public View getTaskbarDividerView() { - return mTaskbarDivider; + public TaskbarDividerContainer getTaskbarDividerViewContainer() { + return mTaskbarDividerContainer; } /** @@ -832,48 +768,6 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar } } } - return mAllAppsButton; - } - - private boolean onAllAppsButtonTouch(View view, MotionEvent ev) { - switch (ev.getAction()) { - case MotionEvent.ACTION_DOWN: - mAllAppsTouchTriggered = false; - MAIN_EXECUTOR.getHandler().postDelayed( - mAllAppsTouchRunnable, mAllAppsButtonTouchDelayMs); - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - cancelAllAppsButtonTouch(); - } - return false; - } - - private void cancelAllAppsButtonTouch() { - MAIN_EXECUTOR.getHandler().removeCallbacks(mAllAppsTouchRunnable); - // ACTION_UP is first triggered, then click listener / long-click listener is triggered on - // the next frame, so we need to post twice and delay the reset. - if (mAllAppsButton != null) { - mAllAppsButton.post(() -> { - mAllAppsButton.post(() -> { - mAllAppsTouchTriggered = false; - }); - }); - } - } - - private void onAllAppsButtonClick(View view) { - if (!mAllAppsTouchTriggered) { - mControllerCallbacks.triggerAllAppsButtonClick(view); - } - } - - // Handle long click from Switch Access and Voice Access - private boolean onAllAppsButtonLongClick(View view) { - if (!MAIN_EXECUTOR.getHandler().hasCallbacks(mAllAppsTouchRunnable) - && !mAllAppsTouchTriggered) { - mControllerCallbacks.triggerAllAppsButtonLongClick(); - } - return true; + return mAllAppsButtonContainer; } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java index e6cac2f9db..296d3792c7 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java @@ -51,7 +51,7 @@ public class TaskbarViewCallbacks { } /** Trigger All Apps button click action. */ - protected void triggerAllAppsButtonClick(View v) { + public void triggerAllAppsButtonClick(View v) { InteractionJankMonitorWrapper.begin(v, Cuj.CUJ_LAUNCHER_OPEN_ALL_APPS, /* tag= */ "TASKBAR_BUTTON"); mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP); @@ -59,7 +59,7 @@ public class TaskbarViewCallbacks { } /** Trigger All Apps button long click action. */ - protected void triggerAllAppsButtonLongClick() { + public void triggerAllAppsButtonLongClick() { mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_LONG_PRESS); } @@ -74,6 +74,11 @@ public class TaskbarViewCallbacks { }; } + /** Check to see if we support long press on taskbar divider */ + public boolean supportsDividerLongPress() { + return !mActivity.isThreeButtonNav(); + } + public View.OnTouchListener getTaskbarDividerRightClickListener() { return (v, event) -> { if (event.isFromSource(InputDevice.SOURCE_MOUSE) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 27c1d9c800..aa3e6bffb8 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -72,7 +72,6 @@ import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.util.MultiPropertyFactory; import com.android.launcher3.util.MultiTranslateDelegate; import com.android.launcher3.util.MultiValueAlpha; -import com.android.launcher3.views.IconButtonView; import com.android.quickstep.util.GroupTask; import com.android.systemui.shared.recents.model.Task; @@ -299,7 +298,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar @Nullable public View getAllAppsButtonView() { - return mTaskbarView.getAllAppsButtonView(); + return mTaskbarView.getAllAppsButtonContainer(); } public AnimatedFloat getTaskbarIconScaleForStash() { @@ -366,9 +365,9 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar View[] iconViews = mTaskbarView.getIconViews(); float scale = mTaskbarIconTranslationXForPinning.value; float transientTaskbarAllAppsOffset = mActivity.getResources().getDimension( - mTaskbarView.getAllAppsButtonTranslationXOffset(true)); + mTaskbarView.getAllAppsButtonContainer().getAllAppsButtonTranslationXOffset(true)); float persistentTaskbarAllAppsOffset = mActivity.getResources().getDimension( - mTaskbarView.getAllAppsButtonTranslationXOffset(false)); + mTaskbarView.getAllAppsButtonContainer().getAllAppsButtonTranslationXOffset(false)); float allAppIconTranslateRange = mapRange(scale, transientTaskbarAllAppsOffset, persistentTaskbarAllAppsOffset); @@ -383,7 +382,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar } if (mActivity.isThreeButtonNav()) { - ((IconButtonView) mTaskbarView.getAllAppsButtonView()) + mTaskbarView.getAllAppsButtonContainer() .setTranslationXForTaskbarAllAppsIcon(allAppIconTranslateRange); return; } @@ -408,8 +407,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar -finalMarginScale * (iconIndex - halfIconCount)); } - if (iconView.equals(mTaskbarView.getAllAppsButtonView())) { - ((IconButtonView) iconView).setTranslationXForTaskbarAllAppsIcon( + if (iconView.equals(mTaskbarView.getAllAppsButtonContainer())) { + mTaskbarView.getAllAppsButtonContainer().setTranslationXForTaskbarAllAppsIcon( allAppIconTranslateRange); } } @@ -537,7 +536,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar } public View getTaskbarDividerView() { - return mTaskbarView.getTaskbarDividerView(); + return mTaskbarView.getTaskbarDividerViewContainer(); } /** @@ -753,8 +752,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar int firstRecentTaskIndex = -1; for (int i = 0; i < mTaskbarView.getChildCount(); i++) { View child = mTaskbarView.getChildAt(i); - boolean isAllAppsButton = child == mTaskbarView.getAllAppsButtonView(); - boolean isTaskbarDividerView = child == mTaskbarView.getTaskbarDividerView(); + boolean isAllAppsButton = child == mTaskbarView.getAllAppsButtonContainer(); + boolean isTaskbarDividerView = child == mTaskbarView.getTaskbarDividerViewContainer(); boolean isRecentTask = child.getTag() instanceof GroupTask; // TODO(b/343522351): show recents on the home screen. final boolean isRecentsInHotseat = false; diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt index 7d2d36d756..726800c2da 100644 --- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt +++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarAllAppsButtonContainer.kt @@ -18,18 +18,27 @@ package com.android.launcher3.taskbar.customization import android.annotation.SuppressLint import android.content.Context +import android.content.res.ColorStateList +import android.graphics.Color.TRANSPARENT import android.util.AttributeSet import android.view.LayoutInflater -import android.widget.LinearLayout +import android.view.MotionEvent +import android.view.View +import android.view.ViewConfiguration import androidx.annotation.DimenRes import androidx.annotation.DrawableRes import androidx.core.view.setPadding import com.android.launcher3.R import com.android.launcher3.Utilities.dpToPx -import com.android.launcher3.config.FeatureFlags +import com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR +import com.android.launcher3.config.FeatureFlags.enableTaskbarPinning import com.android.launcher3.taskbar.TaskbarActivityContext +import com.android.launcher3.taskbar.TaskbarViewCallbacks +import com.android.launcher3.util.Executors.MAIN_EXECUTOR import com.android.launcher3.views.ActivityContext import com.android.launcher3.views.IconButtonView +import com.android.quickstep.DeviceConfigWrapper +import com.android.quickstep.util.AssistStateManager /** Taskbar all apps button container for customizable taskbar. */ class TaskbarAllAppsButtonContainer @@ -38,19 +47,21 @@ constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, -) : LinearLayout(context, attrs), TaskbarContainer { +) : IconButtonView(context, attrs), TaskbarContainer { - private val allAppsButton: IconButtonView = - LayoutInflater.from(context).inflate(R.layout.taskbar_all_apps_button, this, false) - as IconButtonView private val activityContext: TaskbarActivityContext = ActivityContext.lookupContext(context) + private var allAppsTouchTriggered = false + private var allAppsTouchRunnable: Runnable? = null + private var allAppsButtonTouchDelayMs: Long = ViewConfiguration.getLongPressTimeout().toLong() + private lateinit var taskbarViewCallbacks: TaskbarViewCallbacks override val spaceNeeded: Int get() { - return dpToPx(activityContext.taskbarSpecsEvaluator!!.taskbarIconSize.size.toFloat()) + return dpToPx(activityContext.taskbarSpecsEvaluator.taskbarIconSize.size.toFloat()) } init { + LayoutInflater.from(context).inflate(R.layout.taskbar_all_apps_button, null, false) setUpIcon() } @@ -58,24 +69,39 @@ constructor( private fun setUpIcon() { val drawable = resources.getDrawable( - getAllAppsButton(activityContext.taskbarFeatureEvaluator!!.isTransient) + getAllAppsButton(activityContext.taskbarFeatureEvaluator.isTransient) ) - val padding = activityContext.taskbarSpecsEvaluator!!.taskbarIconPadding + backgroundTintList = ColorStateList.valueOf(TRANSPARENT) + setIconDrawable(drawable) + setPadding(dpToPx(activityContext.taskbarSpecsEvaluator.taskbarIconPadding.toFloat())) + setForegroundTint(activityContext.getColor(R.color.all_apps_button_color)) + } - allAppsButton.setIconDrawable(drawable) - allAppsButton.setPadding(padding) - allAppsButton.setForegroundTint(activityContext.getColor(R.color.all_apps_button_color)) - - // TODO(b/356465292) : add click listeners in future cl - addView(allAppsButton) + @SuppressLint("ClickableViewAccessibility") + fun setUpCallbacks(callbacks: TaskbarViewCallbacks) { + taskbarViewCallbacks = callbacks + setOnClickListener(this::onAllAppsButtonClick) + setOnLongClickListener(this::onAllAppsButtonLongClick) + setOnTouchListener(this::onAllAppsButtonTouch) + isHapticFeedbackEnabled = taskbarViewCallbacks.isAllAppsButtonHapticFeedbackEnabled() + allAppsTouchRunnable = Runnable { + taskbarViewCallbacks.triggerAllAppsButtonLongClick() + allAppsTouchTriggered = true + } + val assistStateManager = AssistStateManager.INSTANCE[mContext] + if ( + DeviceConfigWrapper.get().customLpaaThresholds && + assistStateManager.lpnhDurationMillis.isPresent + ) { + allAppsButtonTouchDelayMs = assistStateManager.lpnhDurationMillis.get() + } } @DrawableRes private fun getAllAppsButton(isTransientTaskbar: Boolean): Int { val shouldSelectTransientIcon = - isTransientTaskbar || - (FeatureFlags.enableTaskbarPinning() && !activityContext.isThreeButtonNav) - return if (FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) { + isTransientTaskbar || (enableTaskbarPinning() && !activityContext.isThreeButtonNav) + return if (ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) { if (shouldSelectTransientIcon) R.drawable.ic_transient_taskbar_all_apps_search_button else R.drawable.ic_taskbar_all_apps_search_button } else { @@ -88,10 +114,43 @@ constructor( fun getAllAppsButtonTranslationXOffset(isTransientTaskbar: Boolean): Int { return if (isTransientTaskbar) { R.dimen.transient_taskbar_all_apps_button_translation_x_offset - } else if (FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) { + } else if (ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) { R.dimen.taskbar_all_apps_search_button_translation_x_offset } else { R.dimen.taskbar_all_apps_button_translation_x_offset } } + + private fun onAllAppsButtonTouch(view: View, ev: MotionEvent): Boolean { + when (ev.action) { + MotionEvent.ACTION_DOWN -> { + allAppsTouchTriggered = false + MAIN_EXECUTOR.handler.postDelayed(allAppsTouchRunnable!!, allAppsButtonTouchDelayMs) + } + MotionEvent.ACTION_UP, + MotionEvent.ACTION_CANCEL -> cancelAllAppsButtonTouch() + } + return false + } + + private fun cancelAllAppsButtonTouch() { + MAIN_EXECUTOR.handler.removeCallbacks(allAppsTouchRunnable!!) + // ACTION_UP is first triggered, then click listener / long-click listener is triggered on + // the next frame, so we need to post twice and delay the reset. + this.post { this.post { allAppsTouchTriggered = false } } + } + + private fun onAllAppsButtonClick(view: View) { + if (!allAppsTouchTriggered) { + taskbarViewCallbacks.triggerAllAppsButtonClick(view) + } + } + + // Handle long click from Switch Access and Voice Access + private fun onAllAppsButtonLongClick(view: View): Boolean { + if (!MAIN_EXECUTOR.handler.hasCallbacks(allAppsTouchRunnable!!) && !allAppsTouchTriggered) { + taskbarViewCallbacks.triggerAllAppsButtonLongClick() + } + return true + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarDividerContainer.kt b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarDividerContainer.kt index 26e71f7f08..1fb835ab33 100644 --- a/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarDividerContainer.kt +++ b/quickstep/src/com/android/launcher3/taskbar/customization/TaskbarDividerContainer.kt @@ -18,13 +18,15 @@ package com.android.launcher3.taskbar.customization import android.annotation.SuppressLint import android.content.Context +import android.content.res.ColorStateList +import android.graphics.Color.TRANSPARENT import android.util.AttributeSet import android.view.LayoutInflater -import android.widget.LinearLayout import androidx.core.view.setPadding import com.android.launcher3.R import com.android.launcher3.Utilities.dpToPx import com.android.launcher3.taskbar.TaskbarActivityContext +import com.android.launcher3.taskbar.TaskbarViewCallbacks import com.android.launcher3.views.ActivityContext import com.android.launcher3.views.IconButtonView @@ -35,31 +37,30 @@ constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, -) : LinearLayout(context, attrs), TaskbarContainer { - - private val taskbarDivider: IconButtonView = - LayoutInflater.from(context).inflate(R.layout.taskbar_divider, this, false) - as IconButtonView +) : IconButtonView(context, attrs), TaskbarContainer { private val activityContext: TaskbarActivityContext = ActivityContext.lookupContext(context) override val spaceNeeded: Int get() { - return dpToPx(activityContext.taskbarSpecsEvaluator!!.taskbarIconSize.size.toFloat()) + return dpToPx(activityContext.taskbarSpecsEvaluator.taskbarIconSize.size.toFloat()) } init { + LayoutInflater.from(context).inflate(R.layout.taskbar_divider, null, false) setUpIcon() } @SuppressLint("UseCompatLoadingForDrawables") fun setUpIcon() { + backgroundTintList = ColorStateList.valueOf(TRANSPARENT) val drawable = resources.getDrawable(R.drawable.taskbar_divider_button) - val padding = activityContext.taskbarSpecsEvaluator!!.taskbarIconPadding + setIconDrawable(drawable) + setPadding(dpToPx(activityContext.taskbarSpecsEvaluator.taskbarIconPadding.toFloat())) + } - taskbarDivider.setIconDrawable(drawable) - taskbarDivider.setPadding(padding) - - // TODO(b/356465292):: add click listeners in future cl - addView(taskbarDivider) + @SuppressLint("ClickableViewAccessibility") + fun setUpCallbacks(callbacks: TaskbarViewCallbacks) { + setOnLongClickListener(callbacks.taskbarDividerLongClickListener) + setOnTouchListener(callbacks.taskbarDividerRightClickListener) } }