| /* |
| * Copyright (C) 2022 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 static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS; |
| import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS; |
| |
| import static com.android.launcher3.taskbar.NavbarButtonsViewController.ALPHA_INDEX_IMMERSIVE_MODE; |
| import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IMMERSIVE_MODE; |
| |
| import android.os.Handler; |
| import android.os.Looper; |
| import android.view.MotionEvent; |
| |
| import com.android.launcher3.compat.AccessibilityManagerCompat; |
| import com.android.launcher3.util.MultiValueAlpha; |
| import com.android.launcher3.util.TouchController; |
| import com.android.quickstep.AnimatedFloat; |
| |
| import java.util.Optional; |
| import java.util.function.Consumer; |
| |
| /** |
| * Controller for taskbar when force visible in immersive mode is set. |
| */ |
| public class TaskbarForceVisibleImmersiveController implements TouchController { |
| private static final int NAV_BAR_ICONS_DIM_ANIMATION_START_DELAY_MS = 4500; |
| private static final int NAV_BAR_ICONS_DIM_ANIMATION_DURATION_MS = 500; |
| private static final int NAV_BAR_ICONS_UNDIM_ANIMATION_DURATION_MS = 250; |
| private static final float NAV_BAR_ICONS_DIM_PCT = 0.15f; |
| private static final float NAV_BAR_ICONS_UNDIM_PCT = 1f; |
| |
| private final TaskbarActivityContext mContext; |
| private final Handler mHandler = new Handler(Looper.getMainLooper()); |
| private final Runnable mDimmingRunnable = this::dimIcons; |
| private final Runnable mUndimmingRunnable = this::undimIcons; |
| private final AnimatedFloat mIconAlphaForDimming = new AnimatedFloat( |
| this::updateIconDimmingAlpha); |
| private final Consumer<MultiValueAlpha> mImmersiveModeAlphaUpdater = alpha -> alpha.getProperty( |
| ALPHA_INDEX_IMMERSIVE_MODE).setValue(mIconAlphaForDimming.value); |
| |
| // Initialized in init. |
| private TaskbarControllers mControllers; |
| private boolean mIsImmersiveMode; |
| |
| public TaskbarForceVisibleImmersiveController(TaskbarActivityContext context) { |
| mContext = context; |
| } |
| |
| /** |
| * Initialize controllers. |
| */ |
| public void init(TaskbarControllers controllers) { |
| mControllers = controllers; |
| } |
| |
| /** Update values tracked via sysui flags. */ |
| public void updateSysuiFlags(int sysuiFlags) { |
| mIsImmersiveMode = (sysuiFlags & SYSUI_STATE_IMMERSIVE_MODE) != 0; |
| if (mContext.isNavBarForceVisible()) { |
| if (mIsImmersiveMode) { |
| startIconDimming(); |
| } else { |
| startIconUndimming(); |
| } |
| } |
| } |
| |
| /** Clean up animations. */ |
| public void onDestroy() { |
| startIconUndimming(); |
| } |
| |
| private void startIconUndimming() { |
| mHandler.removeCallbacks(mDimmingRunnable); |
| mHandler.removeCallbacks(mUndimmingRunnable); |
| mHandler.post(mUndimmingRunnable); |
| } |
| |
| private void undimIcons() { |
| mIconAlphaForDimming.animateToValue(NAV_BAR_ICONS_UNDIM_PCT).setDuration( |
| NAV_BAR_ICONS_UNDIM_ANIMATION_DURATION_MS).start(); |
| } |
| |
| private void startIconDimming() { |
| mHandler.removeCallbacks(mDimmingRunnable); |
| int accessibilityDimmingTimeout = AccessibilityManagerCompat.getRecommendedTimeoutMillis( |
| mContext, NAV_BAR_ICONS_DIM_ANIMATION_START_DELAY_MS, |
| (FLAG_CONTENT_ICONS | FLAG_CONTENT_CONTROLS)); |
| mHandler.postDelayed(mDimmingRunnable, accessibilityDimmingTimeout); |
| } |
| |
| private void dimIcons() { |
| mIconAlphaForDimming.animateToValue(NAV_BAR_ICONS_DIM_PCT).setDuration( |
| NAV_BAR_ICONS_DIM_ANIMATION_DURATION_MS).start(); |
| } |
| |
| /** |
| * Returns whether the taskbar is always visible in immersive mode. |
| */ |
| private boolean isNavbarShownInImmersiveMode() { |
| return mIsImmersiveMode && mContext.isNavBarForceVisible(); |
| } |
| |
| private void updateIconDimmingAlpha() { |
| getBackButtonAlphaOptional().ifPresent(mImmersiveModeAlphaUpdater); |
| getHomeButtonAlphaOptional().ifPresent(mImmersiveModeAlphaUpdater); |
| } |
| |
| private Optional<MultiValueAlpha> getBackButtonAlphaOptional() { |
| if (mControllers == null || mControllers.navbarButtonsViewController == null) { |
| return Optional.empty(); |
| } |
| return Optional.ofNullable(mControllers.navbarButtonsViewController.getBackButtonAlpha()); |
| } |
| |
| private Optional<MultiValueAlpha> getHomeButtonAlphaOptional() { |
| if (mControllers == null || mControllers.navbarButtonsViewController == null) { |
| return Optional.empty(); |
| } |
| return Optional.ofNullable(mControllers.navbarButtonsViewController.getHomeButtonAlpha()); |
| } |
| |
| @Override |
| public boolean onControllerInterceptTouchEvent(MotionEvent ev) { |
| if (!isNavbarShownInImmersiveMode() |
| || mControllers.taskbarStashController.supportsManualStashing()) { |
| return false; |
| } |
| return onControllerTouchEvent(ev); |
| } |
| |
| @Override |
| public boolean onControllerTouchEvent(MotionEvent ev) { |
| switch (ev.getAction()) { |
| case MotionEvent.ACTION_DOWN: |
| startIconUndimming(); |
| break; |
| case MotionEvent.ACTION_UP: |
| case MotionEvent.ACTION_CANCEL: |
| startIconDimming(); |
| break; |
| } |
| return false; |
| } |
| } |