Merge "Update gesture navigation tutorial with new specs for foldable devices." into sc-v2-dev
diff --git a/quickstep/res/layout/taskbar.xml b/quickstep/res/layout/taskbar.xml
index 83ad9f3..3b1d217 100644
--- a/quickstep/res/layout/taskbar.xml
+++ b/quickstep/res/layout/taskbar.xml
@@ -30,6 +30,11 @@
android:layout_gravity="bottom"
android:clipChildren="false" />
+ <com.android.launcher3.taskbar.TaskbarScrimView
+ android:id="@+id/taskbar_scrim"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+
<FrameLayout
android:id="@+id/navbuttons_view"
android:layout_width="match_parent"
@@ -42,6 +47,7 @@
android:layout_height="match_parent"
android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
+ android:paddingTop="@dimen/taskbar_contextual_padding_top"
android:gravity="center_vertical"
android:layout_gravity="start"/>
@@ -62,6 +68,7 @@
android:layout_height="match_parent"
android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
+ android:paddingTop="@dimen/taskbar_contextual_padding_top"
android:gravity="center_vertical"
android:layout_gravity="end"/>
</FrameLayout>
diff --git a/quickstep/res/layout/taskbar_contextual_button.xml b/quickstep/res/layout/taskbar_contextual_button.xml
index cbbbfab..4ffb8d8 100644
--- a/quickstep/res/layout/taskbar_contextual_button.xml
+++ b/quickstep/res/layout/taskbar_contextual_button.xml
@@ -15,9 +15,7 @@
-->
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="@dimen/taskbar_contextual_buttons_size"
- android:layout_height="@dimen/taskbar_contextual_buttons_size"
- android:layout_marginTop="@dimen/taskbar_contextual_button_margin"
- android:paddingStart="@dimen/taskbar_nav_buttons_spacing"
+ android:layout_width="@dimen/taskbar_nav_buttons_size"
+ android:layout_height="@dimen/taskbar_nav_buttons_size"
android:background="@drawable/taskbar_icon_click_feedback_roundrect"
android:scaleType="center"/>
\ No newline at end of file
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 02479bf..e08eda8 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -196,8 +196,10 @@
<dimen name="taskbar_icon_drag_icon_size">54dp</dimen>
<dimen name="taskbar_folder_margin">16dp</dimen>
<dimen name="taskbar_nav_buttons_spacing">16dp</dimen>
- <dimen name="taskbar_nav_buttons_size">48dp</dimen>
- <dimen name="taskbar_contextual_button_margin">16dp</dimen>
+ <dimen name="taskbar_contextual_padding_top">8dp</dimen>
+ <dimen name="taskbar_nav_buttons_size">44dp</dimen>
+ <dimen name="taskbar_contextual_button_margin">40dp</dimen>
+ <dimen name="taskbar_hotseat_nav_spacing">42dp</dimen>
<dimen name="taskbar_contextual_buttons_size">35dp</dimen>
<dimen name="taskbar_stashed_size">24dp</dimen>
<dimen name="taskbar_stashed_handle_width">220dp</dimen>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 52bd48b..6af0d60 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -53,8 +53,6 @@
<!-- Accessibility title for the row of all-apps containing app predictions. [CHAR LIMIT=50] -->
<string name="title_app_suggestions">App suggestions</string>
- <!-- Label for the header text of the All Apps section in All Apps view, used to separate Predicted Apps and Actions section from All Apps section. [CHAR_LIMIT=50] -->
- <string name="all_apps_label">All apps</string>
<!-- Text of the tip when user lands in all apps view for the first time, indicating where the tip toast points to is the predicted apps section. [CHAR_LIMIT=50] -->
<string name="all_apps_prediction_tip">Your predicted apps</string>
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 6bc49ed..9d10e1e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -16,8 +16,11 @@
package com.android.launcher3.taskbar;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
+import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
+import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_APP_SETUP;
+import static com.android.launcher3.taskbar.TaskbarStashController.TASKBAR_STASH_DURATION;
import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME;
import android.animation.Animator;
@@ -37,6 +40,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorListeners;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence;
@@ -54,6 +58,7 @@
import com.android.systemui.shared.recents.model.ThumbnailData;
import java.util.Arrays;
+import java.util.function.Supplier;
import java.util.stream.Stream;
/**
@@ -62,7 +67,6 @@
public class LauncherTaskbarUIController extends TaskbarUIController {
private final BaseQuickstepLauncher mLauncher;
- private final TaskbarStateHandler mTaskbarStateHandler;
private final TaskbarActivityContext mContext;
private final TaskbarDragLayer mTaskbarDragLayer;
@@ -72,17 +76,64 @@
new AnimatedFloat(this::onIconAlignmentRatioChanged);
private final AnimatedFloat mIconAlignmentForGestureState =
new AnimatedFloat(this::onIconAlignmentRatioChanged);
+ private final AnimatedFloat mIconAlignmentForLauncherState =
+ new AnimatedFloat(this::onIconAlignmentRatioChangedForStateTransition);
private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
this::onStashedInAppChanged;
private final StateManager.StateListener<LauncherState> mStateListener =
new StateManager.StateListener<LauncherState>() {
+ private Animator mAnimator;
+
+ @Override
+ public void onStateTransitionStart(LauncherState toState) {
+ // Stash animation from going to launcher should be already handled in
+ // createAnimToLauncher.
+ TaskbarStashController controller = mControllers.taskbarStashController;
+ long duration = TASKBAR_STASH_DURATION;
+ controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
+ toState.isTaskbarStashed());
+ Animator stashAnimator = controller.applyStateWithoutStart(duration);
+ if (stashAnimator != null) {
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+ PendingAnimation pendingAnimation = new PendingAnimation(duration);
+ pendingAnimation.add(stashAnimator);
+ pendingAnimation.setFloat(mIconAlignmentForLauncherState,
+ AnimatedFloat.VALUE, toState.isTaskbarStashed() ? 0 : 1,
+ FAST_OUT_SLOW_IN);
+ pendingAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+ mTargetStateOverrideForStateTransition = toState;
+ // Copy hotseat alpha over to taskbar icons
+ mIconAlphaForHome.setValue(mLauncher.getHotseat().getIconsAlpha());
+ mLauncher.getHotseat().setIconsAlpha(0);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ if (toState.isTaskbarStashed()) {
+ // Reset hotseat alpha to default
+ mLauncher.getHotseat().setIconsAlpha(1);
+ }
+ mTargetStateOverrideForStateTransition = null;
+ mAnimator = null;
+ }
+ });
+ mAnimator = pendingAnimation.buildAnim();
+ mAnimator.start();
+ }
+ }
+
@Override
public void onStateTransitionComplete(LauncherState finalState) {
TaskbarStashController controller = mControllers.taskbarStashController;
controller.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
finalState.isTaskbarStashed());
+ controller.applyState();
}
};
@@ -96,6 +147,16 @@
private TaskbarKeyguardController mKeyguardController;
private LauncherState mTargetStateOverride = null;
+ private LauncherState mTargetStateOverrideForStateTransition = null;
+
+ private final DeviceProfile.OnDeviceProfileChangeListener mProfileChangeListener =
+ new DeviceProfile.OnDeviceProfileChangeListener() {
+ @Override
+ public void onDeviceProfileChanged(DeviceProfile dp) {
+ mControllers.taskbarViewController.onRotationChanged(
+ mLauncher.getDeviceProfile());
+ }
+ };
public LauncherTaskbarUIController(
BaseQuickstepLauncher launcher, TaskbarActivityContext context) {
@@ -104,7 +165,6 @@
mTaskbarView = mTaskbarDragLayer.findViewById(R.id.taskbar_view);
mLauncher = launcher;
- mTaskbarStateHandler = mLauncher.getTaskbarStateHandler();
}
@Override
@@ -122,13 +182,14 @@
mLauncher.setTaskbarUIController(this);
mKeyguardController = taskbarControllers.taskbarKeyguardController;
- onLauncherResumedOrPaused(mLauncher.hasBeenResumed());
+ onLauncherResumedOrPaused(mLauncher.hasBeenResumed(), true /* fromInit */);
mIconAlignmentForResumedState.finishAnimation();
onIconAlignmentRatioChanged();
onStashedInAppChanged(mLauncher.getDeviceProfile());
mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
mLauncher.getStateManager().addStateListener(mStateListener);
+ mLauncher.addOnDeviceProfileChangeListener(mProfileChangeListener);
}
@Override
@@ -136,11 +197,13 @@
onLauncherResumedOrPaused(false);
mIconAlignmentForResumedState.finishAnimation();
mIconAlignmentForGestureState.finishAnimation();
+ mIconAlignmentForLauncherState.finishAnimation();
mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
mLauncher.getStateManager().removeStateListener(mStateListener);
mLauncher.getHotseat().setIconsAlpha(1f);
mLauncher.setTaskbarUIController(null);
+ mLauncher.removeOnDeviceProfileChangeListener(mProfileChangeListener);
}
@Override
@@ -162,6 +225,10 @@
* Should be called from onResume() and onPause(), and animates the Taskbar accordingly.
*/
public void onLauncherResumedOrPaused(boolean isResumed) {
+ onLauncherResumedOrPaused(isResumed, false /* fromInit */);
+ }
+
+ private void onLauncherResumedOrPaused(boolean isResumed, boolean fromInit) {
if (mKeyguardController.isScreenOff()) {
if (!isResumed) {
return;
@@ -172,6 +239,11 @@
}
long duration = QuickstepTransitionManager.CONTENT_ALPHA_DURATION;
+ if (fromInit) {
+ // Since we are creating the starting state, we don't have a state to animate from, so
+ // set our state immediately.
+ duration = 0;
+ }
ObjectAnimator anim = mIconAlignmentForResumedState.animateToValue(
getCurrentIconAlignmentRatio(), isResumed ? 1 : 0)
.setDuration(duration);
@@ -183,6 +255,10 @@
TaskbarStashController stashController = mControllers.taskbarStashController;
stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
+ if (isResumed) {
+ // Launcher is resumed, meaning setup must be finished.
+ stashController.updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, false);
+ }
stashController.applyState(duration);
}
@@ -236,25 +312,35 @@
return Math.max(mIconAlignmentForResumedState.value, mIconAlignmentForGestureState.value);
}
+ private float getCurrentIconAlignmentRatioForLauncherState() {
+ return mIconAlignmentForLauncherState.value;
+ }
+
+ private void onIconAlignmentRatioChangedForStateTransition() {
+ onIconAlignmentRatioChanged(
+ mTargetStateOverrideForStateTransition != null
+ ? mTargetStateOverrideForStateTransition
+ : mLauncher.getStateManager().getState(),
+ this::getCurrentIconAlignmentRatioForLauncherState);
+ }
+
private void onIconAlignmentRatioChanged() {
+ onIconAlignmentRatioChanged(mTargetStateOverride != null ? mTargetStateOverride
+ : mLauncher.getStateManager().getState(), this::getCurrentIconAlignmentRatio);
+ }
+
+ private void onIconAlignmentRatioChanged(LauncherState state,
+ Supplier<Float> alignmentSupplier) {
if (mControllers == null) {
return;
}
- float alignment = getCurrentIconAlignmentRatio();
+ float alignment = alignmentSupplier.get();
mControllers.taskbarViewController.setLauncherIconAlignment(
alignment, mLauncher.getDeviceProfile());
mTaskbarBackgroundAlpha.updateValue(1 - alignment);
- LauncherState state = mTargetStateOverride != null ? mTargetStateOverride
- : mLauncher.getStateManager().getState();
- if ((state.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
- // If the hotseat icons are visible, then switch taskbar in last frame
- setTaskbarViewVisible(alignment < 1);
- } else {
- mLauncher.getHotseat().setIconsAlpha(1);
- mIconAlphaForHome.setValue(1 - alignment);
- }
+ setIconAlpha(state, alignment);
}
/**
@@ -273,6 +359,15 @@
return mTaskbarDragLayer;
}
+ private void setIconAlpha(LauncherState state, float progress) {
+ if ((state.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
+ // If the hotseat icons are visible, then switch taskbar in last frame
+ setTaskbarViewVisible(progress < 1);
+ } else {
+ mIconAlphaForHome.setValue(1 - progress);
+ }
+ }
+
private void setTaskbarViewVisible(boolean isVisible) {
mIconAlphaForHome.setValue(isVisible ? 1 : 0);
mLauncher.getHotseat().setIconsAlpha(isVisible ? 0f : 1f);
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 4b75db4..f2ca711 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -36,12 +36,14 @@
import android.annotation.DrawableRes;
import android.annotation.IdRes;
import android.annotation.LayoutRes;
+import android.content.res.ColorStateList;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region.Op;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.provider.Settings;
import android.util.Property;
+import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnHoverListener;
@@ -58,6 +60,7 @@
import com.android.launcher3.taskbar.contextual.RotationButtonController;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.SettingsCache;
+import com.android.launcher3.util.Themes;
import com.android.quickstep.AnimatedFloat;
import java.util.ArrayList;
@@ -95,6 +98,9 @@
private final ViewGroup mEndContextualContainer;
private final ViewGroup mStartContextualContainer;
+ private final AnimatedFloat mTaskbarNavButtonTranslationY = new AnimatedFloat(
+ this::updateNavButtonTranslationY);
+
// Initialized in init.
private TaskbarControllers mControllers;
private View mA11yButton;
@@ -133,8 +139,7 @@
mControllers.navButtonController, R.id.ime_switcher);
mPropertyHolders.add(new StatePropertyHolder(imeSwitcherButton,
flags -> ((flags & MASK_IME_SWITCHER_VISIBLE) == MASK_IME_SWITCHER_VISIBLE)
- && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)
- && ((flags & FLAG_A11Y_VISIBLE) == 0)));
+ && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)));
mPropertyHolders.add(new StatePropertyHolder(
mControllers.taskbarViewController.getTaskbarIconAlpha()
@@ -146,12 +151,33 @@
flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0, AnimatedFloat.VALUE, 1, 0));
// Force nav buttons (specifically back button) to be visible during setup wizard.
- boolean areButtonsForcedVisible = !SettingsCache.INSTANCE.get(mContext).getValue(
+ boolean isInSetup = !SettingsCache.INSTANCE.get(mContext).getValue(
Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0);
- if (isThreeButtonNav || areButtonsForcedVisible) {
+ if (isThreeButtonNav || isInSetup) {
initButtons(mNavButtonContainer, mEndContextualContainer,
mControllers.navButtonController);
+ if (isInSetup) {
+ // Since setup wizard only has back button enabled, it looks strange to be
+ // end-aligned, so start-align instead.
+ FrameLayout.LayoutParams navButtonsLayoutParams = (FrameLayout.LayoutParams)
+ mNavButtonContainer.getLayoutParams();
+ navButtonsLayoutParams.setMarginStart(navButtonsLayoutParams.getMarginEnd());
+ navButtonsLayoutParams.setMarginEnd(0);
+ navButtonsLayoutParams.gravity = Gravity.START;
+ mNavButtonContainer.requestLayout();
+
+ if (!isThreeButtonNav) {
+ // Tint all the nav buttons since there's no taskbar background in SUW.
+ for (int i = 0; i < mNavButtonContainer.getChildCount(); i++) {
+ if (!(mNavButtonContainer.getChildAt(i) instanceof ImageView)) continue;
+ ImageView button = (ImageView) mNavButtonContainer.getChildAt(i);
+ button.setImageTintList(ColorStateList.valueOf(Themes.getAttrColor(
+ button.getContext(), android.R.attr.textColorPrimary)));
+ }
+ }
+ }
+
// Animate taskbar background when IME shows
mPropertyHolders.add(new StatePropertyHolder(
mControllers.taskbarDragLayerController.getNavbarBackgroundAlpha(),
@@ -285,6 +311,13 @@
}
/**
+ * Returns true if the home button is disabled
+ */
+ public boolean isHomeDisabled() {
+ return (mState & FLAG_DISABLE_HOME) != 0;
+ }
+
+ /**
* Returns true if the recents (overview) button is disabled
*/
public boolean isRecentsDisabled() {
@@ -305,6 +338,11 @@
}
}
+ /** Use to set the translationY for the all nav+contextual buttons */
+ public AnimatedFloat getTaskbarNavButtonTranslationY() {
+ return mTaskbarNavButtonTranslationY;
+ }
+
/**
* Does not call {@link #applyState()}. Don't forget to!
*/
@@ -323,6 +361,10 @@
}
}
+ private void updateNavButtonTranslationY() {
+ mNavButtonsView.setTranslationY(mTaskbarNavButtonTranslationY.value);
+ }
+
private ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
ViewGroup parent, TaskbarNavButtonController navButtonController, @IdRes int id) {
return addButton(drawableId, buttonType, parent, navButtonController, id,
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 10da826..2c80f06 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -30,6 +30,7 @@
import com.android.launcher3.anim.RevealOutlineAnimation;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.MultiValueAlpha;
import com.android.quickstep.AnimatedFloat;
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
@@ -38,6 +39,10 @@
*/
public class StashedHandleViewController {
+ public static final int ALPHA_INDEX_STASHED = 0;
+ public static final int ALPHA_INDEX_HOME_DISABLED = 1;
+ private static final int NUM_ALPHA_CHANNELS = 2;
+
/**
* The SharedPreferences key for whether the stashed handle region is dark.
*/
@@ -50,8 +55,7 @@
private final int mStashedHandleWidth;
private final int mStashedHandleHeight;
private final RegionSamplingHelper mRegionSamplingHelper;
- private final AnimatedFloat mTaskbarStashedHandleAlpha = new AnimatedFloat(
- this::updateStashedHandleAlpha);
+ private final MultiValueAlpha mTaskbarStashedHandleAlpha;
private final AnimatedFloat mTaskbarStashedHandleHintScale = new AnimatedFloat(
this::updateStashedHandleHintScale);
@@ -69,6 +73,8 @@
mActivity = activity;
mPrefs = Utilities.getPrefs(mActivity);
mStashedHandleView = stashedHandleView;
+ mTaskbarStashedHandleAlpha = new MultiValueAlpha(mStashedHandleView, NUM_ALPHA_CHANNELS);
+ mTaskbarStashedHandleAlpha.setUpdateVisibility(true);
mStashedHandleView.updateHandleColor(
mPrefs.getBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY, false),
false /* animate */);
@@ -96,7 +102,7 @@
mControllers = controllers;
mStashedHandleView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
- updateStashedHandleAlpha();
+ mTaskbarStashedHandleAlpha.getProperty(ALPHA_INDEX_STASHED).setValue(0);
mTaskbarStashedHandleHintScale.updateValue(1f);
final int stashedTaskbarHeight = mControllers.taskbarStashController.getStashedHeight();
@@ -129,7 +135,7 @@
mRegionSamplingHelper.stopAndDestroy();
}
- public AnimatedFloat getStashedHandleAlpha() {
+ public MultiValueAlpha getStashedHandleAlpha() {
return mTaskbarStashedHandleAlpha;
}
@@ -163,12 +169,20 @@
}
}
- protected void updateStashedHandleAlpha() {
- mStashedHandleView.setAlpha(mTaskbarStashedHandleAlpha.value);
- }
-
protected void updateStashedHandleHintScale() {
mStashedHandleView.setScaleX(mTaskbarStashedHandleHintScale.value);
mStashedHandleView.setScaleY(mTaskbarStashedHandleHintScale.value);
}
+
+ /**
+ * Should be called when the home button is disabled, so we can hide this handle as well.
+ */
+ public void setIsHomeButtonDisabled(boolean homeDisabled) {
+ mTaskbarStashedHandleAlpha.getProperty(ALPHA_INDEX_HOME_DISABLED).setValue(
+ homeDisabled ? 0 : 1);
+ }
+
+ public boolean isStashedHandleVisible() {
+ return mStashedHandleView.getVisibility() == View.VISIBLE;
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index a8c94ce..973c52b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -125,6 +125,7 @@
mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate(
R.layout.taskbar, null, false);
TaskbarView taskbarView = mDragLayer.findViewById(R.id.taskbar_view);
+ TaskbarScrimView taskbarScrimView = mDragLayer.findViewById(R.id.taskbar_scrim);
FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
@@ -145,6 +146,7 @@
R.color.popup_color_primary_light),
new TaskbarDragLayerController(this, mDragLayer),
new TaskbarViewController(this, taskbarView),
+ new TaskbarScrimViewController(this, taskbarScrimView),
new TaskbarUnfoldAnimationController(unfoldTransitionProgressProvider,
mWindowManager),
new TaskbarKeyguardController(this),
@@ -321,8 +323,11 @@
panelExpanded || inSettings);
mControllers.taskbarViewController.setRecentsButtonDisabled(
mControllers.navbarButtonsViewController.isRecentsDisabled());
+ mControllers.stashedHandleViewController.setIsHomeButtonDisabled(
+ mControllers.navbarButtonsViewController.isHomeDisabled());
mControllers.taskbarKeyguardController.updateStateForSysuiFlags(systemUiStateFlags);
mControllers.taskbarStashController.updateStateForSysuiFlags(systemUiStateFlags);
+ mControllers.taskbarScrimViewController.updateStateForSysuiFlags(systemUiStateFlags);
}
public void onRotationProposal(int rotation, boolean isValid) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index e49c6ae..e13f849 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -30,6 +30,7 @@
public final NavbarButtonsViewController navbarButtonsViewController;
public final RotationButtonController rotationButtonController;
public final TaskbarDragLayerController taskbarDragLayerController;
+ public final TaskbarScrimViewController taskbarScrimViewController;
public final TaskbarViewController taskbarViewController;
public final TaskbarUnfoldAnimationController taskbarUnfoldAnimationController;
public final TaskbarKeyguardController taskbarKeyguardController;
@@ -47,6 +48,7 @@
RotationButtonController rotationButtonController,
TaskbarDragLayerController taskbarDragLayerController,
TaskbarViewController taskbarViewController,
+ TaskbarScrimViewController taskbarScrimViewController,
TaskbarUnfoldAnimationController taskbarUnfoldAnimationController,
TaskbarKeyguardController taskbarKeyguardController,
StashedHandleViewController stashedHandleViewController,
@@ -59,6 +61,7 @@
this.rotationButtonController = rotationButtonController;
this.taskbarDragLayerController = taskbarDragLayerController;
this.taskbarViewController = taskbarViewController;
+ this.taskbarScrimViewController = taskbarScrimViewController;
this.taskbarUnfoldAnimationController = taskbarUnfoldAnimationController;
this.taskbarKeyguardController = taskbarKeyguardController;
this.stashedHandleViewController = stashedHandleViewController;
@@ -78,6 +81,7 @@
}
taskbarDragLayerController.init(this);
taskbarViewController.init(this);
+ taskbarScrimViewController.init(this);
taskbarUnfoldAnimationController.init(this);
taskbarKeyguardController.init(navbarButtonsViewController);
stashedHandleViewController.init(this);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
new file mode 100644
index 0000000..94a3307
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimView.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 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.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * View that handles scrimming the taskbar and the inverted corners it draws. The scrim is used
+ * when bubbles is expanded.
+ */
+public class TaskbarScrimView extends View {
+ private final Paint mTaskbarScrimPaint;
+ private final Path mInvertedLeftCornerPath, mInvertedRightCornerPath;
+
+ private boolean mShowScrim;
+ private float mLeftCornerRadius, mRightCornerRadius;
+ private float mBackgroundHeight;
+
+ public TaskbarScrimView(Context context) {
+ this(context, null);
+ }
+
+ public TaskbarScrimView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TaskbarScrimView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public TaskbarScrimView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ mTaskbarScrimPaint = new Paint();
+ mTaskbarScrimPaint.setColor(getResources().getColor(android.R.color.system_neutral1_1000));
+ mTaskbarScrimPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+ mTaskbarScrimPaint.setStyle(Paint.Style.FILL);
+
+ mInvertedLeftCornerPath = new Path();
+ mInvertedRightCornerPath = new Path();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (mShowScrim) {
+ canvas.save();
+ canvas.translate(0, canvas.getHeight() - mBackgroundHeight);
+
+ // Scrim the taskbar itself.
+ canvas.drawRect(0, 0, canvas.getWidth(), mBackgroundHeight, mTaskbarScrimPaint);
+
+ // Scrim the inverted rounded corners above the taskbar.
+ canvas.translate(0, -mLeftCornerRadius);
+ canvas.drawPath(mInvertedLeftCornerPath, mTaskbarScrimPaint);
+ canvas.translate(0, mLeftCornerRadius);
+ canvas.translate(canvas.getWidth() - mRightCornerRadius, -mRightCornerRadius);
+ canvas.drawPath(mInvertedRightCornerPath, mTaskbarScrimPaint);
+
+ canvas.restore();
+ }
+ }
+
+ /**
+ * Sets the height of the taskbar background.
+ * @param height the height of the background.
+ */
+ protected void setBackgroundHeight(float height) {
+ mBackgroundHeight = height;
+ if (mShowScrim) {
+ invalidate();
+ }
+ }
+
+ /**
+ * Sets the alpha of the taskbar scrim.
+ * @param alpha the alpha of the scrim.
+ */
+ protected void setScrimAlpha(float alpha) {
+ mShowScrim = alpha > 0f;
+ mTaskbarScrimPaint.setAlpha((int) (alpha * 255));
+ invalidate();
+ }
+
+ /**
+ * Sets the radius of the left and right corners above the taskbar.
+ * @param leftCornerRadius the radius of the left corner.
+ * @param rightCornerRadius the radius of the right corner.
+ */
+ protected void setCornerSizes(float leftCornerRadius, float rightCornerRadius) {
+ mLeftCornerRadius = leftCornerRadius;
+ mRightCornerRadius = rightCornerRadius;
+
+ Path square = new Path();
+ square.addRect(0, 0, mLeftCornerRadius, mLeftCornerRadius, Path.Direction.CW);
+ Path circle = new Path();
+ circle.addCircle(mLeftCornerRadius, 0, mLeftCornerRadius, Path.Direction.CW);
+ mInvertedLeftCornerPath.op(square, circle, Path.Op.DIFFERENCE);
+ square.reset();
+ square.addRect(0, 0, mRightCornerRadius, mRightCornerRadius, Path.Direction.CW);
+ circle.reset();
+ circle.addCircle(0, 0, mRightCornerRadius, Path.Direction.CW);
+ mInvertedRightCornerPath.op(square, circle, Path.Op.DIFFERENCE);
+
+ if (mShowScrim) {
+ invalidate();
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
new file mode 100644
index 0000000..e7e55ef
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 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 static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED;
+
+import android.animation.ObjectAnimator;
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
+
+import com.android.quickstep.AnimatedFloat;
+import com.android.quickstep.SystemUiProxy;
+
+/**
+ * Handles properties/data collection, and passes the results to {@link TaskbarScrimView} to render.
+ */
+public class TaskbarScrimViewController {
+
+ private static final float SCRIM_ALPHA = 0.6f;
+
+ private static final Interpolator SCRIM_ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
+ private static final Interpolator SCRIM_ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
+
+ private final TaskbarActivityContext mActivity;
+ private final TaskbarScrimView mScrimView;
+
+ // Alpha property for the scrim.
+ private final AnimatedFloat mScrimAlpha = new AnimatedFloat(this::updateScrimAlpha);
+
+ // Initialized in init.
+ private TaskbarControllers mControllers;
+
+ public TaskbarScrimViewController(TaskbarActivityContext activity, TaskbarScrimView scrimView) {
+ mActivity = activity;
+ mScrimView = scrimView;
+ mScrimView.setCornerSizes(mActivity.getLeftCornerRadius(),
+ mActivity.getRightCornerRadius());
+ mScrimView.setBackgroundHeight(mActivity.getDeviceProfile().taskbarSize);
+ }
+
+ /**
+ * Initializes the controller
+ */
+ public void init(TaskbarControllers controllers) {
+ mControllers = controllers;
+ }
+
+ /**
+ * Updates the scrim state based on the flags.
+ */
+ public void updateStateForSysuiFlags(int stateFlags) {
+ final boolean bubblesExpanded = (stateFlags & SYSUI_STATE_BUBBLES_EXPANDED) != 0;
+ final boolean manageMenuExpanded =
+ (stateFlags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0;
+ final boolean showScrim = !mControllers.navbarButtonsViewController.isImeVisible()
+ && bubblesExpanded && mControllers.taskbarStashController.isInAppAndNotStashed();
+ final float scrimAlpha = manageMenuExpanded
+ // When manage menu shows there's the first scrim and second scrim so figure out
+ // what the total transparency would be.
+ ? (SCRIM_ALPHA + (SCRIM_ALPHA * (1 - SCRIM_ALPHA)))
+ : showScrim ? SCRIM_ALPHA : 0;
+ showScrim(showScrim, scrimAlpha);
+ }
+
+ private void showScrim(boolean showScrim, float alpha) {
+ mScrimView.setOnClickListener(showScrim ? (view) -> onClick() : null);
+ mScrimView.setClickable(showScrim);
+ ObjectAnimator anim = mScrimAlpha.animateToValue(showScrim ? alpha : 0);
+ anim.setInterpolator(showScrim ? SCRIM_ALPHA_IN : SCRIM_ALPHA_OUT);
+ anim.start();
+ }
+
+ private void updateScrimAlpha() {
+ mScrimView.setScrimAlpha(mScrimAlpha.value);
+ }
+
+ private void onClick() {
+ SystemUiProxy.INSTANCE.get(mActivity).onBackPressed();
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 6d6f0f2..7a89224 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -25,15 +25,21 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.ComponentName;
import android.content.SharedPreferences;
import android.content.res.Resources;
+import android.provider.Settings;
import android.view.ViewConfiguration;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
+import com.android.launcher3.util.SettingsCache;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.interaction.AllSetActivity;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
import java.util.function.IntPredicate;
@@ -47,16 +53,17 @@
public static final int FLAG_STASHED_IN_APP_MANUAL = 1 << 1; // long press, persisted
public static final int FLAG_STASHED_IN_APP_PINNED = 1 << 2; // app pinning
public static final int FLAG_STASHED_IN_APP_EMPTY = 1 << 3; // no hotseat icons
- public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 4;
+ public static final int FLAG_STASHED_IN_APP_SETUP = 1 << 4; // setup wizard and AllSetActivity
+ public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 5;
// If we're in an app and any of these flags are enabled, taskbar should be stashed.
public static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
- | FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY;
+ | FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP;
/**
* How long to stash/unstash when manually invoked via long press.
*/
- private static final long TASKBAR_STASH_DURATION = 300;
+ public static final long TASKBAR_STASH_DURATION = 300;
/**
* The scale TaskbarView animates to when being stashed.
@@ -103,7 +110,7 @@
private AnimatedFloat mIconScaleForStash;
private AnimatedFloat mIconTranslationYForStash;
// Stashed handle properties.
- private AnimatedFloat mTaskbarStashedHandleAlpha;
+ private AlphaProperty mTaskbarStashedHandleAlpha;
private AnimatedFloat mTaskbarStashedHandleHintScale;
/** Whether we are currently visually stashed (might change based on launcher state). */
@@ -143,12 +150,14 @@
StashedHandleViewController stashedHandleController =
controllers.stashedHandleViewController;
- mTaskbarStashedHandleAlpha = stashedHandleController.getStashedHandleAlpha();
+ mTaskbarStashedHandleAlpha = stashedHandleController.getStashedHandleAlpha().getProperty(
+ StashedHandleViewController.ALPHA_INDEX_STASHED);
mTaskbarStashedHandleHintScale = stashedHandleController.getStashedHandleHintScale();
boolean isManuallyStashedInApp = supportsManualStashing()
&& mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
+ updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup());
applyState();
SystemUiProxy.INSTANCE.get(mActivity)
@@ -177,6 +186,23 @@
}
/**
+ * Returns whether we are in Setup Wizard or the corresponding AllSetActivity that follows it.
+ */
+ private boolean isInSetup() {
+ boolean isInSetup = !SettingsCache.INSTANCE.get(mActivity).getValue(
+ Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0);
+ if (isInSetup) {
+ return true;
+ }
+ ActivityManager.RunningTaskInfo runningTask =
+ ActivityManagerWrapper.getInstance().getRunningTask();
+ if (runningTask == null || runningTask.baseActivity == null) {
+ return false;
+ }
+ return runningTask.baseActivity.equals(new ComponentName(mActivity, AllSetActivity.class));
+ }
+
+ /**
* Returns whether the taskbar is currently visually stashed.
*/
public boolean isStashed() {
@@ -198,8 +224,21 @@
return (flags & flagMask) != 0;
}
+
+ /**
+ * Returns whether the taskbar is currently visible and in an app.
+ */
+ public boolean isInAppAndNotStashed() {
+ return !mIsStashed && (mState & FLAG_IN_APP) != 0;
+ }
+
public int getContentHeight() {
- return isStashed() ? mStashedHeight : mUnstashedHeight;
+ if (isStashed()) {
+ boolean isAnimating = mAnimator != null && mAnimator.isStarted();
+ return mControllers.stashedHandleViewController.isStashedHandleVisible() || isAnimating
+ ? mStashedHeight : 0;
+ }
+ return mUnstashedHeight;
}
public int getStashedHeight() {
@@ -240,7 +279,12 @@
return false;
}
- private Animator createAnimToIsStashed(boolean isStashed, long duration) {
+ /**
+ * Create a stash animation and save to {@link #mAnimator}.
+ * @param isStashed whether it's a stash animation or an unstash animation
+ * @param duration duration of the animation
+ */
+ private void createAnimToIsStashed(boolean isStashed, long duration) {
if (mAnimator != null) {
mAnimator.cancel();
}
@@ -250,7 +294,7 @@
// Just hide/show the icons instead of stashing into a handle.
mAnimator.play(mIconAlphaForStash.animateToValue(isStashed ? 0 : 1)
.setDuration(duration));
- return mAnimator;
+ return;
}
AnimatorSet fullLengthAnimatorSet = new AnimatorSet();
@@ -322,7 +366,6 @@
mAnimator = null;
}
});
- return mAnimator;
}
/**
@@ -442,12 +485,13 @@
boolean isStashed = mStashCondition.test(flags);
if (mIsStashed != isStashed) {
mIsStashed = isStashed;
- Animator animator = createAnimToIsStashed(mIsStashed, duration);
+ createAnimToIsStashed(mIsStashed, duration);
if (start) {
- animator.start();
+ mAnimator.start();
}
+ return mAnimator;
}
- return mAnimator;
+ return null;
}
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index ed09fa5..ff04799 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -60,6 +60,7 @@
this::updateTranslationY);
private final AnimatedFloat mTaskbarIconTranslationYForStash = new AnimatedFloat(
this::updateTranslationY);
+ private AnimatedFloat mTaskbarNavButtonTranslationY;
private final TaskbarModelCallbacks mModelCallbacks;
@@ -88,6 +89,8 @@
mModelCallbacks.init(controllers);
LauncherAppState.getInstance(mActivity).getModel().addCallbacksAndLoad(mModelCallbacks);
+ mTaskbarNavButtonTranslationY =
+ controllers.navbarButtonsViewController.getTaskbarNavButtonTranslationY();
}
public void onDestroy() {
@@ -214,6 +217,7 @@
int offsetY = launcherDp.getTaskbarOffsetY();
setter.setFloat(mTaskbarIconTranslationYForHome, VALUE, -offsetY, LINEAR);
+ setter.setFloat(mTaskbarNavButtonTranslationY, VALUE, -offsetY, LINEAR);
int collapsedHeight = mActivity.getDefaultTaskbarWindowHeight();
int expandedHeight = Math.max(collapsedHeight,
@@ -238,6 +242,14 @@
return controller;
}
+ public void onRotationChanged(DeviceProfile deviceProfile) {
+ if (areIconsVisible()) {
+ // We only translate on rotation when on home
+ return;
+ }
+ mTaskbarNavButtonTranslationY.updateValue(-deviceProfile.getTaskbarOffsetY());
+ }
+
/**
* Callbacks for {@link TaskbarView} to interact with its controller.
*/
diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
index c9909cc..aa26645 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
@@ -57,13 +57,13 @@
if (SysUINavigationMode.INSTANCE.get(context).getMode() == Mode.THREE_BUTTONS) {
Resources res = context.getResources();
/*
- * 2 (left + right) x Padding +
* 3 nav buttons +
- * Little space at the end for contextual buttons
+ * Little space at the end for contextual buttons +
+ * Little space between icons and nav buttons
*/
- return 2 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_spacing)
- + 3 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
- + res.getDimensionPixelSize(R.dimen.taskbar_contextual_button_margin);
+ return 3 * res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size)
+ + res.getDimensionPixelSize(R.dimen.taskbar_contextual_button_margin)
+ + res.getDimensionPixelSize(R.dimen.taskbar_hotseat_nav_spacing);
} else {
return 0;
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index f8c9fd1..c554fd0 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -69,6 +69,11 @@
}
@Override
+ public boolean isTaskbarStashed() {
+ return true;
+ }
+
+ @Override
protected float getDepthUnchecked(Context context) {
// The scrim fades in at approximately 50% of the swipe gesture.
// This means that the depth should be greater than 1, in order to fully zoom out.
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index aabba66..99f1dc7 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -122,10 +122,6 @@
public static final int STATE_RECENTS_ANIMATION_ENDED =
getFlagForIndex("STATE_RECENTS_ANIMATION_ENDED");
- // Called when we create an overscroll window when swiping right to left on the most recent app
- public static final int STATE_OVERSCROLL_WINDOW_CREATED =
- getFlagForIndex("STATE_OVERSCROLL_WINDOW_CREATED");
-
// Called when RecentsView stops scrolling and settles on a TaskView.
public static final int STATE_RECENTS_SCROLLING_FINISHED =
getFlagForIndex("STATE_RECENTS_SCROLLING_FINISHED");
diff --git a/quickstep/src/com/android/quickstep/OverscrollPluginFactory.java b/quickstep/src/com/android/quickstep/OverscrollPluginFactory.java
deleted file mode 100644
index 4c261ab..0000000
--- a/quickstep/src/com/android/quickstep/OverscrollPluginFactory.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 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.quickstep;
-
-import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
-
-import com.android.launcher3.R;
-import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.launcher3.util.ResourceBasedOverride;
-import com.android.systemui.plugins.OverscrollPlugin;
-
-/**
- * Resource overrideable factory for forcing a local overscroll plugin.
- * Override {@link R.string#overscroll_plugin_factory_class} to set a different class.
- */
-public class OverscrollPluginFactory implements ResourceBasedOverride {
- public static final MainThreadInitializedObject<OverscrollPluginFactory> INSTANCE = forOverride(
- OverscrollPluginFactory.class,
- R.string.overscroll_plugin_factory_class);
-
- /**
- * Get the plugin that is defined locally in launcher, as opposed to a dynamic side loaded one.
- */
- public OverscrollPlugin getLocalOverscrollPlugin() {
- return null;
- }
-}
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index dc04016..7ef4d19 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -16,9 +16,8 @@
package com.android.quickstep;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-
import android.content.Context;
+import android.util.Log;
import androidx.annotation.Nullable;
@@ -34,7 +33,9 @@
* {@link TaskViewSimulator}
*/
public class RemoteTargetGluer {
- private final RemoteTargetHandle[] mRemoteTargetHandles;
+ private static final String TAG = "RemoteTargetGluer";
+
+ private RemoteTargetHandle[] mRemoteTargetHandles;
private SplitConfigurationOptions.StagedSplitBounds mStagedSplitBounds;
/**
@@ -93,6 +94,13 @@
public RemoteTargetHandle[] assignTargetsForSplitScreen(RemoteAnimationTargets targets) {
int[] splitIds = LauncherSplitScreenListener.INSTANCE.getNoCreate()
.getRunningSplitTaskIds();
+ if (splitIds.length == 0 && mRemoteTargetHandles.length > 1) {
+ // There's a chance that between the creation of this class and assigning targets,
+ // LauncherSplitScreenListener may have received callback that removes split
+ mRemoteTargetHandles = new RemoteTargetHandle[]{mRemoteTargetHandles[0]};
+ Log.w(TAG, "splitTaskIds changed between creation and assignment");
+ }
+
RemoteAnimationTargetCompat primaryTaskTarget;
RemoteAnimationTargetCompat secondaryTaskTarget;
if (mRemoteTargetHandles.length == 1) {
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 284bc03..12b071d 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -170,7 +170,7 @@
RemoteTargetHandle[] remoteTargetHandles;
RemoteTargetHandle[] recentsViewHandles = recentsView.getRemoteTargetHandles();
- if (v.isRunningTask()) {
+ if (v.isRunningTask() && recentsViewHandles != null) {
// Re-use existing handles
remoteTargetHandles = recentsViewHandles;
} else {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index bb8473b..46b228e 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -40,7 +40,6 @@
import android.app.RemoteAction;
import android.app.Service;
import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
@@ -90,7 +89,6 @@
import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
import com.android.quickstep.inputconsumers.OneHandedModeInputConsumer;
import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
-import com.android.quickstep.inputconsumers.OverscrollInputConsumer;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
@@ -103,8 +101,6 @@
import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.ProxyScreenStatusProvider;
import com.android.quickstep.util.SplitScreenBounds;
-import com.android.systemui.plugins.OverscrollPlugin;
-import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -129,8 +125,8 @@
* Service connected by system-UI for handling touch interaction.
*/
@TargetApi(Build.VERSION_CODES.R)
-public class TouchInteractionService extends Service implements PluginListener<OverscrollPlugin>,
- ProtoTraceable<LauncherTraceProto.Builder> {
+public class TouchInteractionService extends Service
+ implements ProtoTraceable<LauncherTraceProto.Builder> {
private static final String TAG = "TouchInteractionService";
@@ -149,8 +145,6 @@
SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
private int mBackGestureNotificationCounter = -1;
- @Nullable
- private OverscrollPlugin mOverscrollPlugin;
/**
* Local IOverviewProxy implementation with some methods for local components
@@ -423,9 +417,6 @@
.getInt(KEY_BACK_NOTIFICATION_COUNT, MAX_BACK_NOTIFICATION_COUNT));
resetHomeBounceSeenOnQuickstepEnabledFirstTime();
- PluginManagerWrapper.INSTANCE.get(getBaseContext()).addPluginListener(this,
- OverscrollPlugin.class, false /* allowMultiple */);
-
mOverviewComponentObserver.setOverviewChangeListener(this::onOverviewTargetChange);
onOverviewTargetChange(mOverviewComponentObserver.isHomeAndOverviewSame());
}
@@ -507,7 +498,6 @@
if (mDeviceState.isUserUnlocked()) {
mInputConsumer.unregisterInputConsumer();
mOverviewComponentObserver.onDestroy();
- PluginManagerWrapper.INSTANCE.get(getBaseContext()).removePluginListener(this);
}
disposeEventHandlers();
mDeviceState.destroy();
@@ -691,26 +681,6 @@
mTaskbarManager.getCurrentActivityContext());
}
- if (FeatureFlags.ENABLE_QUICK_CAPTURE_GESTURE.get()) {
- OverscrollPlugin plugin = null;
- if (FeatureFlags.FORCE_LOCAL_OVERSCROLL_PLUGIN.get()) {
- plugin = OverscrollPluginFactory.INSTANCE.get(
- getApplicationContext()).getLocalOverscrollPlugin();
- }
-
- // If not local plugin was forced, use the actual overscroll plugin if available.
- if (plugin == null && mOverscrollPlugin != null && mOverscrollPlugin.isActive()) {
- plugin = mOverscrollPlugin;
- }
-
- if (plugin != null) {
- // Put the overscroll gesture as higher priority than the Assistant or base
- // gestures
- base = new OverscrollInputConsumer(this, newGestureState, base,
- mInputMonitorCompat, plugin);
- }
- }
-
// If Bubbles is expanded, use the overlay input consumer, which will close Bubbles
// instead of going all the way home when a swipe up is detected.
if (mDeviceState.isBubblesExpanded() || mDeviceState.isGlobalActionsShowing()) {
@@ -1019,16 +989,6 @@
}
@Override
- public void onPluginConnected(OverscrollPlugin overscrollPlugin, Context context) {
- mOverscrollPlugin = overscrollPlugin;
- }
-
- @Override
- public void onPluginDisconnected(OverscrollPlugin overscrollPlugin) {
- mOverscrollPlugin = null;
- }
-
- @Override
public void writeToProto(LauncherTraceProto.Builder proto) {
TouchInteractionServiceProto.Builder serviceProto =
TouchInteractionServiceProto.newBuilder();
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 725c7c4..0bd8832 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -29,7 +29,6 @@
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.util.TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS;
import static com.android.launcher3.util.VelocityUtils.PX_PER_MS;
-import static com.android.quickstep.GestureState.STATE_OVERSCROLL_WINDOW_CREATED;
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
import android.annotation.TargetApi;
@@ -490,7 +489,7 @@
@Override
public boolean allowInterceptByParent() {
- return !mPassedPilferInputSlop || mGestureState.hasState(STATE_OVERSCROLL_WINDOW_CREATED);
+ return !mPassedPilferInputSlop;
}
@Override
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
deleted file mode 100644
index e984b4f..0000000
--- a/quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2019 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.quickstep.inputconsumers;
-
-import static android.view.MotionEvent.ACTION_CANCEL;
-import static android.view.MotionEvent.ACTION_DOWN;
-import static android.view.MotionEvent.ACTION_MOVE;
-import static android.view.MotionEvent.ACTION_POINTER_DOWN;
-import static android.view.MotionEvent.ACTION_POINTER_UP;
-import static android.view.MotionEvent.ACTION_UP;
-
-import static com.android.launcher3.Utilities.squaredHypot;
-
-import static java.lang.Math.abs;
-
-import android.content.Context;
-import android.graphics.PointF;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.ViewConfiguration;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.R;
-import com.android.quickstep.GestureState;
-import com.android.quickstep.InputConsumer;
-import com.android.quickstep.views.RecentsView;
-import com.android.systemui.plugins.OverscrollPlugin;
-import com.android.systemui.shared.system.InputMonitorCompat;
-
-/**
- * Input consumer for handling events to pass to an {@code OverscrollPlugin}.
- */
-public class OverscrollInputConsumer extends DelegateInputConsumer {
- private static final String TAG = "OverscrollInputConsumer";
- private static final boolean DEBUG_LOGS_ENABLED = false;
- private static void debugPrint(String log) {
- if (DEBUG_LOGS_ENABLED) {
- Log.v(TAG, log);
- }
- }
-
- private final PointF mDownPos = new PointF();
- private final PointF mLastPos = new PointF();
- private final PointF mStartDragPos = new PointF();
- private final int mAngleThreshold;
-
- private final int mFlingDistanceThresholdPx;
- private final int mFlingVelocityThresholdPx;
- private int mActivePointerId = -1;
- private boolean mPassedSlop = false;
- // True if we set ourselves as active, meaning we no longer pass events to the delegate.
- private boolean mPassedActiveThreshold = false;
- // When a gesture crosses this length, this recognizer will attempt to interpret touch events.
- private final float mSquaredSlop;
- // When a gesture crosses this length, this recognizer will become the sole active recognizer.
- private final float mSquaredActiveThreshold;
- // When a gesture crosses this length, the overscroll view should be shown.
- private final float mSquaredFinishThreshold;
- private boolean mThisDownIsIgnored = false;
-
- private final GestureState mGestureState;
- @Nullable
- private final OverscrollPlugin mPlugin;
-
- @Nullable
- private RecentsView mRecentsView;
-
- public OverscrollInputConsumer(Context context, GestureState gestureState,
- InputConsumer delegate, InputMonitorCompat inputMonitor, OverscrollPlugin plugin) {
- super(delegate, inputMonitor);
-
- mAngleThreshold = context.getResources()
- .getInteger(R.integer.assistant_gesture_corner_deg_threshold);
- mFlingDistanceThresholdPx = (int) context.getResources()
- .getDimension(R.dimen.gestures_overscroll_fling_threshold);
- mFlingVelocityThresholdPx = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
- mGestureState = gestureState;
- mPlugin = plugin;
-
- float slop = ViewConfiguration.get(context).getScaledTouchSlop();
-
- mSquaredSlop = slop * slop;
-
-
- float finishGestureThreshold = (int) context.getResources()
- .getDimension(R.dimen.gestures_overscroll_finish_threshold);
- mSquaredFinishThreshold = finishGestureThreshold * finishGestureThreshold;
-
- float activeThreshold = (int) context.getResources()
- .getDimension(R.dimen.gestures_overscroll_active_threshold);
- mSquaredActiveThreshold = activeThreshold * activeThreshold;
- }
-
- @Override
- public int getType() {
- return TYPE_OVERSCROLL | mDelegate.getType();
- }
-
- @Override
- public void onMotionEvent(MotionEvent ev) {
- if (mPlugin == null) {
- return;
- }
-
- debugPrint("got event, underlying activity is " + getUnderlyingActivity());
- switch (ev.getActionMasked()) {
- case ACTION_DOWN: {
- debugPrint("ACTION_DOWN");
- mActivePointerId = ev.getPointerId(0);
- mDownPos.set(ev.getX(), ev.getY());
- mLastPos.set(mDownPos);
- if (mPlugin.blockOtherGestures()) {
- debugPrint("mPlugin.blockOtherGestures(), becoming active on ACTION_DOWN");
- // Otherwise, if an appear gesture is performed when the Activity is visible,
- // the Activity will dismiss its keyboard.
- mPassedActiveThreshold = true;
- mPassedSlop = true;
- mStartDragPos.set(mLastPos.x, mLastPos.y);
- setActive(ev);
- }
- break;
- }
- case ACTION_POINTER_DOWN: {
- if (mState != STATE_ACTIVE) {
- mState = STATE_DELEGATE_ACTIVE;
- }
- break;
- }
- case ACTION_POINTER_UP: {
- int ptrIdx = ev.getActionIndex();
- int ptrId = ev.getPointerId(ptrIdx);
- if (ptrId == mActivePointerId) {
- final int newPointerIdx = ptrIdx == 0 ? 1 : 0;
- mDownPos.set(
- ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x),
- ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y));
- mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
- mActivePointerId = ev.getPointerId(newPointerIdx);
- }
- break;
- }
- case ACTION_MOVE: {
- if (mState == STATE_DELEGATE_ACTIVE) {
- break;
- }
-
- if (!mDelegate.allowInterceptByParent()) {
- mState = STATE_DELEGATE_ACTIVE;
- break;
- }
-
- // Update last touch position.
- int pointerIndex = ev.findPointerIndex(mActivePointerId);
- if (pointerIndex == -1) {
- break;
- }
- mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
-
- float squaredDist = squaredHypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y);
- if ((!mPassedSlop) && (squaredDist > mSquaredSlop)) {
- mPassedSlop = true;
- mStartDragPos.set(mLastPos.x, mLastPos.y);
- mGestureState.setState(GestureState.STATE_OVERSCROLL_WINDOW_CREATED);
- }
-
- boolean becomeActive = mPassedSlop && !mPassedActiveThreshold && isOverscrolled()
- && (squaredDist > mSquaredActiveThreshold);
- if (becomeActive) {
- debugPrint("Past slop and past threshold, set active");
- mPassedActiveThreshold = true;
- setActive(ev);
- }
-
- if (mPassedActiveThreshold) {
- debugPrint("ACTION_MOVE Relaying touch event");
- mPlugin.onTouchEvent(ev, getHorizontalDistancePx(), getVerticalDistancePx(),
- (int) Math.sqrt(mSquaredFinishThreshold), mFlingDistanceThresholdPx,
- mFlingVelocityThresholdPx, getDeviceState(), getUnderlyingActivity());
- }
-
- break;
- }
- case ACTION_CANCEL:
- case ACTION_UP:
- debugPrint("ACTION_UP");
- if (mPassedActiveThreshold) {
- debugPrint("ACTION_UP Relaying touch event");
-
- mPlugin.onTouchEvent(ev, getHorizontalDistancePx(), getVerticalDistancePx(),
- (int) Math.sqrt(mSquaredFinishThreshold), mFlingDistanceThresholdPx,
- mFlingVelocityThresholdPx, getDeviceState(), getUnderlyingActivity());
- }
-
-
- mPassedSlop = false;
- mPassedActiveThreshold = false;
- mState = STATE_INACTIVE;
- break;
- }
-
- if (mState != STATE_ACTIVE) {
- mDelegate.onMotionEvent(ev);
- }
- }
-
- private boolean isOverscrolled() {
- if (mRecentsView == null) {
- BaseDraggingActivity activity = mGestureState.getActivityInterface()
- .getCreatedActivity();
- if (activity != null) {
- mRecentsView = activity.getOverviewPanel();
- }
- }
-
- // Make sure there isn't an app to quick switch to on our right
- int maxIndex = 0;
-
- boolean atRightMostApp = mRecentsView == null
- || (mRecentsView.getRunningTaskIndex() <= maxIndex);
-
- // Check if the gesture is within our angle threshold of horizontal
- float deltaY = abs(mLastPos.y - mDownPos.y);
- float deltaX = mLastPos.x - mDownPos.x;
-
- boolean angleInBounds = (Math.toDegrees(Math.atan2(deltaY, abs(deltaX))) < mAngleThreshold);
-
- boolean overscrollVisible = mPlugin.blockOtherGestures();
- boolean overscrollInvisibleAndLeftSwipe = !overscrollVisible && deltaX < 0;
- boolean gestureDirectionMatchesVisibility = overscrollVisible
- || overscrollInvisibleAndLeftSwipe;
- return atRightMostApp && angleInBounds && gestureDirectionMatchesVisibility;
- }
-
- private String getDeviceState() {
- String deviceState = OverscrollPlugin.DEVICE_STATE_UNKNOWN;
- int consumerType = mDelegate.getType();
- if (((consumerType & InputConsumer.TYPE_OVERVIEW) > 0)
- || ((consumerType & InputConsumer.TYPE_OVERVIEW_WITHOUT_FOCUS)) > 0) {
- deviceState = OverscrollPlugin.DEVICE_STATE_LAUNCHER;
- } else if ((consumerType & InputConsumer.TYPE_OTHER_ACTIVITY) > 0) {
- deviceState = OverscrollPlugin.DEVICE_STATE_APP;
- } else if (((consumerType & InputConsumer.TYPE_RESET_GESTURE) > 0)
- || ((consumerType & InputConsumer.TYPE_DEVICE_LOCKED) > 0)) {
- deviceState = OverscrollPlugin.DEVICE_STATE_LOCKED;
- }
-
- return deviceState;
- }
-
- private int getHorizontalDistancePx() {
- return (int) (mLastPos.x - mDownPos.x);
- }
-
- private int getVerticalDistancePx() {
- return (int) (mLastPos.y - mDownPos.y);
- }
-
- private @NonNull String getUnderlyingActivity() {
- // Overly defensive, got guidance on code review that something in the chain of
- // `mGestureState.getRunningTask().topActivity` can be null and thus cause a null pointer
- // exception to be thrown, but we aren't sure which part can be null.
- if ((mGestureState == null) || (mGestureState.getRunningTask() == null)
- || (mGestureState.getRunningTask().topActivity == null)) {
- return "";
- }
- return mGestureState.getRunningTask().topActivity.flattenToString();
- }
-}
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index 9ac6ed0..a34baef 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -42,10 +42,19 @@
<include layout="@layout/floating_header_content" />
<include layout="@layout/all_apps_personal_work_tabs" />
+
+ <Button
+ android:id="@+id/all_apps_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/all_apps_label"
+ android:background="@drawable/padded_rounded_action_button"
+ android:visibility="gone"/>
+
</com.android.launcher3.allapps.FloatingHeaderView>
- <include
- layout="@layout/search_container_all_apps"/>
+ <include layout="@layout/search_container_all_apps" />
<include layout="@layout/all_apps_fast_scroller" />
</com.android.launcher3.allapps.LauncherAllAppsContainerView>
\ No newline at end of file
diff --git a/res/layout/system_shortcut_content.xml b/res/layout/system_shortcut_content.xml
index 3ef0b94..e693dbd 100644
--- a/res/layout/system_shortcut_content.xml
+++ b/res/layout/system_shortcut_content.xml
@@ -32,6 +32,7 @@
android:minLines="1"
android:maxLines="2"
android:ellipsize="end"
+ android:hyphenationFrequency="full"
android:textColor="?android:attr/textColorPrimary"
launcher:iconDisplay="shortcut_popup"
launcher:layoutHorizontal="true"
@@ -44,4 +45,4 @@
android:layout_marginStart="@dimen/system_shortcut_margin_start"
android:layout_gravity="start|center_vertical"
android:backgroundTint="?android:attr/textColorPrimary"/>
-</merge>
\ No newline at end of file
+</merge>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index b6acb97..d56d898 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -41,7 +41,7 @@
<string name="widgets_and_shortcuts_count" msgid="7209136747878365116">"<xliff:g id="WIDGETS_COUNT">%1$s</xliff:g>, <xliff:g id="SHORTCUTS_COUNT">%2$s</xliff:g>"</string>
<string name="widget_button_text" msgid="2880537293434387943">"ਵਿਜੇਟ"</string>
<string name="widgets_full_sheet_search_bar_hint" msgid="8484659090860596457">"ਖੋਜੋ"</string>
- <string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"ਖੋਜ ਬਾਕਸ ਤੋਂ ਸਪੱਸ਼ਟ ਲਿਖਤ"</string>
+ <string name="widgets_full_sheet_cancel_button_description" msgid="5766167035728653605">"ਖੋਜ ਬਾਕਸ ਤੋਂ ਲਿਖਤ ਕਲੀਅਰ ਕਰੋ"</string>
<string name="no_widgets_available" msgid="4337693382501046170">"ਵਿਜੇਟ ਜਾਂ ਸ਼ਾਰਟਕੱਟ ਉਪਲਬਧ ਨਹੀਂ ਹਨ"</string>
<string name="no_search_results" msgid="3787956167293097509">"ਕੋਈ ਵੀ ਵਿਜੇਟ ਜਾਂ ਸ਼ਾਰਟਕੱਟ ਨਹੀਂ ਮਿਲਿਆ"</string>
<string name="widgets_full_sheet_personal_tab" msgid="2743540105607120182">"ਨਿੱਜੀ"</string>
@@ -115,7 +115,7 @@
<string name="abandoned_clean_this" msgid="7610119707847920412">"ਹਟਾਓ"</string>
<string name="abandoned_search" msgid="891119232568284442">"ਖੋਜੋ"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"ਇਹ ਐਪ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
- <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ਇਸ ਪ੍ਰਤੀਕ ਲਈ ਐਪ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ। ਤੁਸੀਂ ਇਸਨੂੰ ਹਟਾ ਸਕਦੇ ਹੋ ਜਾਂ ਐਪ ਖੋਜ ਸਕਦੇ ਹੋ ਅਤੇ ਇਸਨੂੰ ਮੈਨੂਅਲੀ ਸਥਾਪਤ ਕਰ ਸਕਦੇ ਹੋ।"</string>
+ <string name="abandoned_promise_explanation" msgid="3990027586878167529">"ਇਸ ਪ੍ਰਤੀਕ ਲਈ ਐਪ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤੀ ਹੋਈ ਹੈ। ਤੁਸੀਂ ਇਸਨੂੰ ਹਟਾ ਸਕਦੇ ਹੋ ਜਾਂ ਐਪ ਨੂੰ ਹੱਥੀਂ ਖੋਜ ਕੇ ਉਸਨੂੰ ਸਥਾਪਤ ਕਰ ਸਕਦੇ ਹੋ।"</string>
<string name="app_installing_title" msgid="5864044122733792085">"<xliff:g id="NAME">%1$s</xliff:g> ਨੂੰ ਸਥਾਪਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ, <xliff:g id="PROGRESS">%2$s</xliff:g> ਪੂਰਾ ਹੋਇਆ"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> ਡਾਉਨਲੋਡ ਹੋਰ ਰਿਹਾ ਹੈ, <xliff:g id="PROGRESS">%2$s</xliff:g> ਸੰਪੂਰਣ"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> ਸਥਾਪਤ ਕਰਨ ਦੀ ਉਡੀਕ ਕਰ ਰਿਹਾ ਹੈ"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 92aa678..08f0089 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -154,12 +154,7 @@
<attr name="demoModeLayoutId" format="reference" />
<attr name="isScalable" format="boolean" />
<attr name="devicePaddingId" format="reference" />
- <attr name="gridEnabled" format="integer" >
- <!-- Enable on all devices; default value -->
- <enum name="all_displays" value="0" />
- <!-- Enable on single display devices only -->
- <enum name="single_display" value="1" />
- </attr>
+ <attr name="gridEnabled" format="boolean" />
</declare-styleable>
@@ -241,10 +236,7 @@
<attr name="twoPanelLandscapeIconTextSize" format="float" />
<!-- If set, this display option is used to determine the default grid -->
- <attr name="canBeDefault" format="boolean|integer" >
- <!-- The profile can be default on split display devices -->
- <flag name="split_display" value="0x2" />
- </attr>
+ <attr name="canBeDefault" format="boolean" />
<!-- Margin on left and right of the workspace when GridDisplayOption#isScalable is true -->
<attr name="horizontalMargin" format="float"/>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b1294b4..4d137c8 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -103,6 +103,7 @@
<dimen name="all_apps_tabs_vertical_padding">6dp</dimen>
<dimen name="all_apps_divider_height">2dp</dimen>
<dimen name="all_apps_divider_width">128dp</dimen>
+ <dimen name="all_apps_content_fade_in_offset">150dp</dimen>
<dimen name="all_apps_tip_bottom_margin">8dp</dimen>
<!-- The size of corner radius of the arrow in the arrow toast. -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f315725..d7a1506 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
/*
* Copyright (C) 2008 The Android Open Source Project
*
@@ -132,6 +131,8 @@
<string name="all_apps_search_market_message">Search for more apps</string>
<!-- Label for an icon representing any generic app. [CHAR_LIMIT=50] -->
<string name="label_application">App</string>
+ <!-- Label for the header text of the All Apps section in All Apps view, used to separate Predicted Apps and Actions section from All Apps section. [CHAR_LIMIT=50] -->
+ <string name="all_apps_label">All apps</string>
<!-- Popup items -->
<!-- Text to display as the header above notifications. [CHAR_LIMIT=30] -->
@@ -193,7 +194,7 @@
<string name="msg_no_phone_permission"><xliff:g id="app_name" example="Launcher3">%1$s</xliff:g> is not allowed to make phone calls</string>
<!-- Widgets: -->
- <skip />
+ <skip />
<!-- Error text that lets a user know that the widget can't load. -->
<string name="gadget_error_text">Can\'t load widget</string>
@@ -308,7 +309,7 @@
<!-- Text announced by accessibility when the popup containing the list of widgets is closed. [CHAR_LIMIT=100] -->
<string name="widgets_list_closed">Widgets list closed</string>
-<!-- Strings for accessibility actions -->
+ <!-- Strings for accessibility actions -->
<!-- Accessibility action to add an app to workspace. [CHAR_LIMIT=30] -->
<string name="action_add_to_workspace">Add to Home screen</string>
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
index 256999c..e030f81 100644
--- a/res/xml/device_profiles.xml
+++ b/res/xml/device_profiles.xml
@@ -121,7 +121,7 @@
launcher:minHeightDps="694"
launcher:iconImageSize="56"
launcher:iconTextSize="14.4"
- launcher:canBeDefault="split_display" />
+ launcher:canBeDefault="true" />
<display-option
launcher:name="Shorter Stubby"
diff --git a/res/xml/device_profiles_split.xml b/res/xml/device_profiles_split.xml
new file mode 100644
index 0000000..2fad0c9
--- /dev/null
+++ b/res/xml/device_profiles_split.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 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.
+-->
+
+<profiles xmlns:launcher="http://schemas.android.com/apk/res-auto" >
+
+ <grid-option
+ launcher:name="3_by_3"
+ launcher:numRows="3"
+ launcher:numColumns="3"
+ launcher:numFolderRows="2"
+ launcher:numFolderColumns="3"
+ launcher:numHotseatIcons="3"
+ launcher:dbFile="launcher_3_by_3.db"
+ launcher:defaultLayoutId="@xml/default_workspace_3x3" >
+
+ <display-option
+ launcher:name="Super Short Stubby"
+ launcher:minWidthDps="255"
+ launcher:minHeightDps="300"
+ launcher:iconImageSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
+
+ <display-option
+ launcher:name="Shorter Stubby"
+ launcher:minWidthDps="255"
+ launcher:minHeightDps="400"
+ launcher:iconImageSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
+
+ </grid-option>
+
+ <grid-option
+ launcher:name="4_by_4"
+ launcher:numRows="4"
+ launcher:numColumns="4"
+ launcher:numFolderRows="3"
+ launcher:numFolderColumns="4"
+ launcher:numHotseatIcons="4"
+ launcher:dbFile="launcher_4_by_4.db"
+ launcher:defaultLayoutId="@xml/default_workspace_4x4" >
+
+ <display-option
+ launcher:name="Short Stubby"
+ launcher:minWidthDps="275"
+ launcher:minHeightDps="420"
+ launcher:iconImageSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
+
+ <display-option
+ launcher:name="Stubby"
+ launcher:minWidthDps="255"
+ launcher:minHeightDps="450"
+ launcher:iconImageSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
+
+ <display-option
+ launcher:name="Nexus S"
+ launcher:minWidthDps="296"
+ launcher:minHeightDps="491.33"
+ launcher:iconImageSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
+
+ <display-option
+ launcher:name="Nexus 4"
+ launcher:minWidthDps="359"
+ launcher:minHeightDps="567"
+ launcher:iconImageSize="54"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
+
+ <display-option
+ launcher:name="Nexus 5"
+ launcher:minWidthDps="335"
+ launcher:minHeightDps="567"
+ launcher:iconImageSize="54"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
+
+ </grid-option>
+
+ <grid-option
+ launcher:name="5_by_5"
+ launcher:numRows="5"
+ launcher:numColumns="5"
+ launcher:numFolderRows="4"
+ launcher:numFolderColumns="4"
+ launcher:numHotseatIcons="5"
+ launcher:numExtendedHotseatIcons="8"
+ launcher:dbFile="launcher.db"
+ launcher:defaultLayoutId="@xml/default_workspace_5x5" >
+
+ <display-option
+ launcher:name="Large Phone"
+ launcher:minWidthDps="406"
+ launcher:minHeightDps="694"
+ launcher:iconImageSize="56"
+ launcher:iconTextSize="14.4"
+ launcher:canBeDefault="true" />
+
+ <display-option
+ launcher:name="Large Phone Split Display"
+ launcher:minWidthDps="406"
+ launcher:minHeightDps="694"
+ launcher:iconImageSize="56"
+ launcher:iconTextSize="14.4"
+ launcher:canBeDefault="true" />
+
+ <display-option
+ launcher:name="Shorter Stubby"
+ launcher:minWidthDps="255"
+ launcher:minHeightDps="400"
+ launcher:iconImageSize="48"
+ launcher:iconTextSize="13.0"
+ launcher:canBeDefault="true" />
+
+ </grid-option>
+
+</profiles>
\ No newline at end of file
diff --git a/res/xml/size_limits_80x104.xml b/res/xml/size_limits_80x104.xml
deleted file mode 100644
index 4178664..0000000
--- a/res/xml/size_limits_80x104.xml
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 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.
--->
-
-<device-paddings xmlns:launcher="http://schemas.android.com/apk/res-auto" >
-
- <device-padding
- launcher:maxEmptySpace="88dp">
- <workspaceTopPadding
- launcher:a="0"
- launcher:b="0"/>
- <workspaceBottomPadding
- launcher:a="0.52"
- launcher:b="0"/>
- <hotseatBottomPadding
- launcher:a="0.48"
- launcher:b="0"/>
- </device-padding>
-
- <device-padding
- launcher:maxEmptySpace="100dp">
- <workspaceTopPadding
- launcher:a="0"
- launcher:b="9dp"/>
- <workspaceBottomPadding
- launcher:a="0.40"
- launcher:b="0"
- launcher:c="9dp"/>
- <hotseatBottomPadding
- launcher:a="0.60"
- launcher:b="0"
- launcher:c="9dp"/>
- </device-padding>
-
- <device-padding
- launcher:maxEmptySpace="103dp">
- <workspaceTopPadding
- launcher:a="0"
- launcher:b="26dp"/>
- <workspaceBottomPadding
- launcher:a="0"
- launcher:b="20dp"/>
- <hotseatBottomPadding
- launcher:a="1"
- launcher:b="0"
- launcher:c="46dp"/>
- </device-padding>
-
- <device-padding
- launcher:maxEmptySpace="107dp">
- <workspaceTopPadding
- launcher:a="0"
- launcher:b="9dp"/>
- <workspaceBottomPadding
- launcher:a="0"
- launcher:b="34dp"/>
- <hotseatBottomPadding
- launcher:a="1"
- launcher:b="0"
- launcher:c="43dp"/>
- </device-padding>
-
- <device-padding
- launcher:maxEmptySpace="120dp">
- <workspaceTopPadding
- launcher:a="0"
- launcher:b="16dp"/>
- <workspaceBottomPadding
- launcher:a="1"
- launcher:c="72dp"/>
- <hotseatBottomPadding
- launcher:a="0"
- launcher:b="56dp"/>
- </device-padding>
-
- <device-padding
- launcher:maxEmptySpace="135dp">
- <workspaceTopPadding
- launcher:a="0"
- launcher:b="39dp"/>
- <workspaceBottomPadding
- launcher:a="1"
- launcher:c="95dp"/>
- <hotseatBottomPadding
- launcher:a="0"
- launcher:b="56dp"/>
- </device-padding>
-
- <device-padding
- launcher:maxEmptySpace="9999dp">
- <workspaceTopPadding
- launcher:a="0.40"
- launcher:c="36dp"/>
- <workspaceBottomPadding
- launcher:a="0.60"
- launcher:c="36dp"/>
- <hotseatBottomPadding
- launcher:a="0"
- launcher:b="36dp"/>
- </device-padding>
-</device-paddings>
\ No newline at end of file
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 9da2b79..521d8f4 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -66,7 +66,6 @@
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.SafeCloseable;
import com.android.launcher3.views.ActivityContext;
-import com.android.launcher3.views.BubbleTextHolder;
import com.android.launcher3.views.IconLabelDotView;
import java.text.NumberFormat;
@@ -163,6 +162,7 @@
private HandlerRunnable mIconLoadRequest;
private boolean mEnableIconUpdateAnimation = false;
+ private ItemInfoUpdateReceiver mItemInfoUpdateReceiver;
public BubbleTextView(Context context) {
this(context, null, 0);
@@ -240,6 +240,7 @@
mDotParams.scale = 0f;
mForceHideDot = false;
setBackground(null);
+ mItemInfoUpdateReceiver = null;
}
private void cancelDotScaleAnim() {
@@ -337,13 +338,18 @@
setDownloadStateContentDescription(info, info.getProgressLevel());
}
- private void setItemInfo(ItemInfo itemInfo) {
+ private void setItemInfo(ItemInfoWithIcon itemInfo) {
setTag(itemInfo);
- if (getParent() instanceof BubbleTextHolder) {
- ((BubbleTextHolder) getParent()).onItemInfoChanged(itemInfo);
+ if (mItemInfoUpdateReceiver != null) {
+ mItemInfoUpdateReceiver.reapplyItemInfo(itemInfo);
}
}
+ public void setItemInfoUpdateReceiver(
+ ItemInfoUpdateReceiver itemInfoUpdateReceiver) {
+ mItemInfoUpdateReceiver = itemInfoUpdateReceiver;
+ }
+
@UiThread
protected void applyIconAndLabel(ItemInfoWithIcon info) {
boolean useTheme = mDisplay == DISPLAY_WORKSPACE || mDisplay == DISPLAY_FOLDER
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index e86c02c..ffe3816 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -198,6 +198,10 @@
getShortcutsAndWidgets().setAlpha(alpha);
}
+ public float getIconsAlpha() {
+ return getShortcutsAndWidgets().getAlpha();
+ }
+
/**
* Returns the QSB inside hotseat
*/
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 1b2f177..d844b87 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 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.
@@ -70,11 +70,6 @@
public static final MainThreadInitializedObject<InvariantDeviceProfile> INSTANCE =
new MainThreadInitializedObject<>(InvariantDeviceProfile::new);
- private static final int DEFAULT_TRUE = -1;
- private static final int DEFAULT_SPLIT_DISPLAY = 2;
- private static final int GRID_ENABLED_ALL_DISPLAYS = 0;
- private static final int GRID_ENABLED_SINGLE_DISPLAY = 1;
-
private static final String KEY_IDP_GRID_NAME = "idp_grid_name";
private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48;
@@ -393,7 +388,9 @@
private static ArrayList<DisplayOption> getPredefinedDeviceProfiles(
Context context, String gridName, boolean isSplitDisplay, boolean allowDisabledGrid) {
ArrayList<DisplayOption> profiles = new ArrayList<>();
- try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
+ int xmlResource = isSplitDisplay ? R.xml.device_profiles_split : R.xml.device_profiles;
+
+ try (XmlResourceParser parser = context.getResources().getXml(xmlResource)) {
final int depth = parser.getDepth();
int type;
while (((type = parser.next()) != XmlPullParser.END_TAG ||
@@ -411,8 +408,7 @@
if ((type == XmlPullParser.START_TAG) && "display-option".equals(
parser.getName())) {
profiles.add(new DisplayOption(gridOption, context,
- Xml.asAttributeSet(parser),
- isSplitDisplay ? DEFAULT_SPLIT_DISPLAY : DEFAULT_TRUE));
+ Xml.asAttributeSet(parser)));
}
}
}
@@ -450,7 +446,9 @@
*/
public List<GridOption> parseAllGridOptions(Context context) {
List<GridOption> result = new ArrayList<>();
- try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
+ int xmlResource = isSplitDisplay ? R.xml.device_profiles_split : R.xml.device_profiles;
+
+ try (XmlResourceParser parser = context.getResources().getXml(xmlResource)) {
final int depth = parser.getDepth();
int type;
while (((type = parser.next()) != XmlPullParser.END_TAG
@@ -702,11 +700,7 @@
devicePaddingId = a.getResourceId(
R.styleable.GridDisplayOption_devicePaddingId, 0);
- final int enabledInt =
- a.getInteger(R.styleable.GridDisplayOption_gridEnabled,
- GRID_ENABLED_ALL_DISPLAYS);
- isEnabled = enabledInt == GRID_ENABLED_ALL_DISPLAYS
- || enabledInt == GRID_ENABLED_SINGLE_DISPLAY && !isSplitDisplay;
+ isEnabled = a.getBoolean(R.styleable.GridDisplayOption_gridEnabled, true);
a.recycle();
extraAttrs = Themes.createValueMap(context, attrs,
@@ -732,17 +726,15 @@
private final float[] iconSizes = new float[COUNT_SIZES];
private final float[] textSizes = new float[COUNT_SIZES];
- DisplayOption(GridOption grid, Context context, AttributeSet attrs, int defaultFlagValue) {
+ DisplayOption(GridOption grid, Context context, AttributeSet attrs) {
this.grid = grid;
- TypedArray a = context.obtainStyledAttributes(
- attrs, R.styleable.ProfileDisplayOption);
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ProfileDisplayOption);
minWidthDps = a.getFloat(R.styleable.ProfileDisplayOption_minWidthDps, 0);
minHeightDps = a.getFloat(R.styleable.ProfileDisplayOption_minHeightDps, 0);
- canBeDefault = a.getInt(R.styleable.ProfileDisplayOption_canBeDefault, 0)
- == defaultFlagValue;
+ canBeDefault = a.getBoolean(R.styleable.ProfileDisplayOption_canBeDefault, false);
float x;
float y;
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index f38f662..ee6f51e 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -60,6 +60,7 @@
import com.android.launcher3.pm.PackageInstallInfo;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.shortcuts.ShortcutRequest;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.PackageUserKey;
@@ -346,6 +347,12 @@
public void addCallbacks(Callbacks callbacks) {
Preconditions.assertUIThread();
synchronized (mCallbacksList) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.NULL_INT_SET, "addCallbacks pointer: "
+ + callbacks
+ + ", name: "
+ + callbacks.getClass().getName(), new Exception());
+ }
mCallbacksList.add(callbacks);
}
}
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index df09f29..7ba9935 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -461,6 +461,13 @@
app.getModel().forceReload();
return null;
}
+ case LauncherSettings.Settings.METHOD_CLEAR_WORKSPACE:
+ {
+ Bundle result = new Bundle();
+ result.putIntArray(LauncherSettings.Settings.EXTRA_VALUE, clearWorkspace()
+ .toArray());
+ return result;
+ }
}
return null;
}
@@ -497,6 +504,30 @@
}
}
+ /**
+ * Deletes any items from the DB apart from hotseat.
+ * @return Ids of deleted items.
+ */
+ private IntArray clearWorkspace() {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ try (SQLiteTransaction t = new SQLiteTransaction(db)) {
+ String selection = LauncherSettings.Favorites.CONTAINER + " <> "
+ + LauncherSettings.Favorites.CONTAINER_HOTSEAT;
+
+ IntArray itemIds = LauncherDbUtils.queryIntArray(db, Favorites.TABLE_NAME,
+ Favorites._ID, selection, null, null);
+ if (!itemIds.isEmpty()) {
+ db.delete(Favorites.TABLE_NAME, Utilities.createDbSelectionQuery(
+ LauncherSettings.Favorites._ID, itemIds), null);
+ }
+ t.commit();
+ return itemIds;
+ } catch (SQLException ex) {
+ Log.e(TAG, ex.getMessage(), ex);
+ return new IntArray();
+ }
+ }
+
@Thunk static void addModifiedTime(ContentValues values) {
values.put(LauncherSettings.Favorites.MODIFIED, System.currentTimeMillis());
}
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index 7de2ee4..5ef3690 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -1,5 +1,6 @@
package com.android.launcher3;
+import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
import android.annotation.TargetApi;
@@ -99,7 +100,11 @@
oldNavInsets.bottom);
if (dp.isLandscape) {
- if (dp.isTablet) {
+ boolean isGesturalMode = ResourceUtils.getIntegerByName(
+ "config_navBarInteractionMode",
+ resources,
+ INVALID_RESOURCE_HANDLE) == 2;
+ if (dp.isTablet || isGesturalMode) {
newNavInsets.bottom = ResourceUtils.getNavbarSize(
"navigation_bar_height_landscape", resources);
} else {
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 048aaaa..bf9cd92 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -392,6 +392,8 @@
public static final String METHOD_SWITCH_DATABASE = "switch_database";
+ public static final String METHOD_CLEAR_WORKSPACE = "clear_workspace";
+
public static final String EXTRA_VALUE = "value";
public static final String EXTRA_DB_NAME = "db_name";
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index debb5b2..3ca0303 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -47,6 +47,7 @@
ValueAnimator.AnimatorUpdateListener, PluginListener<AllAppsRow>, Insettable,
OnHeightUpdatedListener {
+ private static final long ALL_APPS_CONTENT_ANIM_DURATION = 150;
private final Rect mRVClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
private final Rect mHeaderClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0);
@@ -108,6 +109,14 @@
// enabled or disabled, and represent the current set of all rows.
private FloatingHeaderRow[] mAllRows = FloatingHeaderRow.NO_ROWS;
+
+ // members for handling suggestion state
+ private final ValueAnimator mAllAppsContentAnimator = ValueAnimator.ofFloat(0, 0);
+ private View mAllAppsButton;
+ private int mAllAppsContentFadeInOffset;
+ private boolean mInSuggestionMode = false;
+
+
public FloatingHeaderView(@NonNull Context context) {
this(context, null);
}
@@ -118,12 +127,20 @@
.getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
mHeaderProtectionSupported = context.getResources().getBoolean(
R.bool.config_header_protection_supported);
+ mAllAppsContentFadeInOffset = context.getResources()
+ .getDimensionPixelSize(R.dimen.all_apps_content_fade_in_offset);
+ mAllAppsContentAnimator.setDuration(ALL_APPS_CONTENT_ANIM_DURATION);
+ mAllAppsContentAnimator.addUpdateListener(this::onAllAppsContentAnimationUpdate);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mTabLayout = findViewById(R.id.tabs);
+ mAllAppsButton = findViewById(R.id.all_apps_button);
+ if (mAllAppsButton != null) {
+ mAllAppsButton.setOnClickListener(this::onAllAppsButtonClicked);
+ }
// Find all floating header rows.
ArrayList<FloatingHeaderRow> rows = new ArrayList<>();
@@ -312,6 +329,7 @@
}
mTabLayout.setTranslationY(mTranslationY);
+ setSuggestionMode(false);
int clipHeight = mHeaderTopPadding - getPaddingBottom();
mRVClip.top = mTabsHidden ? clipHeight : 0;
@@ -347,6 +365,7 @@
mTranslationY = 0;
applyVerticalMove();
}
+ setSuggestionMode(false);
mHeaderCollapsed = false;
mSnappedScrolledY = -mMaxTranslation;
mCurrentRV.scrollToTop();
@@ -442,6 +461,38 @@
}
return Math.max(getHeight() - getPaddingTop() + mTranslationY, 0);
}
+
+ /**
+ * When suggestion mode is enabled, hides AllApps content view and shows AllApps button.
+ */
+ public void setSuggestionMode(boolean isSuggestMode) {
+ if (mInSuggestionMode == isSuggestMode || mAllAppsButton == null) return;
+ if (!FeatureFlags.ENABLE_ONE_SEARCH.get()) return;
+ AllAppsContainerView allApps = (AllAppsContainerView) getParent();
+ mInSuggestionMode = isSuggestMode;
+ if (isSuggestMode) {
+ mTabLayout.setVisibility(GONE);
+ mAllAppsButton.setVisibility(VISIBLE);
+ allApps.getContentView().setVisibility(GONE);
+ } else {
+ mTabLayout.setVisibility(mTabsHidden ? GONE : VISIBLE);
+ mAllAppsButton.setVisibility(GONE);
+ allApps.getContentView().setVisibility(VISIBLE);
+ }
+ }
+
+ private void onAllAppsButtonClicked(View view) {
+ setSuggestionMode(false);
+ mAllAppsContentAnimator.start();
+ }
+
+ private void onAllAppsContentAnimationUpdate(ValueAnimator valueAnimator) {
+ float prog = valueAnimator.getAnimatedFraction();
+ View allAppsList = ((AllAppsContainerView) getParent()).getContentView();
+ allAppsList.setAlpha(255 * prog);
+ allAppsList.setTranslationY((1 - prog) * mAllAppsContentFadeInOffset);
+ }
+
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index ec077de..a3d9ba7 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -72,12 +72,6 @@
"PROMISE_APPS_NEW_INSTALLS", true,
"Adds a promise icon to the home screen for new install sessions.");
- public static final BooleanFlag QUICKSTEP_SPRINGS = getDebugFlag(
- "QUICKSTEP_SPRINGS", true, "Enable springs for quickstep animations");
-
- public static final BooleanFlag UNSTABLE_SPRINGS = getDebugFlag(
- "UNSTABLE_SPRINGS", false, "Enable unstable springs for quickstep animations");
-
public static final BooleanFlag ENABLE_LOCAL_COLOR_POPUPS = getDebugFlag(
"ENABLE_LOCAL_COLOR_POPUPS", false, "Enable local color extraction for popups.");
@@ -122,16 +116,6 @@
public static final BooleanFlag ENABLE_PREDICTION_DISMISS = getDebugFlag(
"ENABLE_PREDICTION_DISMISS", true, "Allow option to dimiss apps from predicted list");
- public static final BooleanFlag ENABLE_QUICK_CAPTURE_GESTURE = getDebugFlag(
- "ENABLE_QUICK_CAPTURE_GESTURE", true, "Swipe from right to left to quick capture");
-
- public static final BooleanFlag ENABLE_QUICK_CAPTURE_WINDOW = getDebugFlag(
- "ENABLE_QUICK_CAPTURE_WINDOW", false, "Use window to host quick capture");
-
- public static final BooleanFlag FORCE_LOCAL_OVERSCROLL_PLUGIN = getDebugFlag(
- "FORCE_LOCAL_OVERSCROLL_PLUGIN", false,
- "Use a launcher-provided OverscrollPlugin if available");
-
public static final BooleanFlag ASSISTANT_GIVES_LAUNCHER_FOCUS = getDebugFlag(
"ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
"Allow Launcher to handle nav bar gestures while Assistant is running over it");
@@ -160,7 +144,7 @@
"ENABLE_OVERVIEW_SELECTIONS", true, "Show Select Mode button in Overview Actions");
public static final BooleanFlag ENABLE_WIDGETS_PICKER_AIAI_SEARCH = new DeviceFlag(
- "ENABLE_WIDGETS_PICKER_AIAI_SEARCH", false, "Enable AiAi search in the widgets picker");
+ "ENABLE_WIDGETS_PICKER_AIAI_SEARCH", true, "Enable AiAi search in the widgets picker");
public static final BooleanFlag ENABLE_OVERVIEW_SHARING_TO_PEOPLE = getDebugFlag(
"ENABLE_OVERVIEW_SHARING_TO_PEOPLE", true,
diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java
index 3cae1e1..d270cc5 100644
--- a/src/com/android/launcher3/model/BaseLoaderResults.java
+++ b/src/com/android/launcher3/model/BaseLoaderResults.java
@@ -177,7 +177,9 @@
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NULL_INT_SET, "bind (1) currentScreenIds: "
+ currentScreenIds
- + ", mCallBacks: "
+ + ", pointer: "
+ + mCallbacks
+ + ", name: "
+ mCallbacks.getClass().getName());
}
filterCurrentWorkspaceItems(currentScreenIds, mWorkspaceItems, currentWorkspaceItems,
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 5f8a4d4..61d488c 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -21,7 +21,6 @@
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
-import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
@@ -217,7 +216,7 @@
mFlingBlockCheck.blockFling();
}
}
- if (mToState == LauncherState.ALL_APPS && !UNSTABLE_SPRINGS.get()) {
+ if (mToState == LauncherState.ALL_APPS) {
mAllAppsOvershootStarted = true;
// 1f, value when all apps container hit the top
mLauncher.getAppsView().onPull(progress - 1f, progress - 1f);
@@ -333,7 +332,7 @@
anim.setFloatValues(startProgress, endProgress);
updateSwipeCompleteAnimation(anim, duration, targetState, velocity, fling);
mCurrentAnimation.dispatchOnStart();
- if (targetState == LauncherState.ALL_APPS && !UNSTABLE_SPRINGS.get()) {
+ if (targetState == LauncherState.ALL_APPS) {
if (mAllAppsOvershootStarted) {
mLauncher.getAppsView().onRelease();
mAllAppsOvershootStarted = false;
diff --git a/src/com/android/launcher3/util/WindowManagerCompat.java b/src/com/android/launcher3/util/WindowManagerCompat.java
index bfdf1e4..e1b9478 100644
--- a/src/com/android/launcher3/util/WindowManagerCompat.java
+++ b/src/com/android/launcher3/util/WindowManagerCompat.java
@@ -60,10 +60,10 @@
}
WindowInsets defaultInsets = windowContext.getSystemService(WindowManager.class)
.getMaximumWindowMetrics().getWindowInsets();
- boolean hasNavbar = ResourceUtils.getIntegerByName(
+ boolean isGesturalMode = ResourceUtils.getIntegerByName(
"config_navBarInteractionMode",
windowContext.getResources(),
- INVALID_RESOURCE_HANDLE) != 0;
+ INVALID_RESOURCE_HANDLE) == 2;
WindowInsets.Builder insetsBuilder = new WindowInsets.Builder(defaultInsets);
Set<WindowBounds> result = new ArraySet<>();
@@ -74,7 +74,7 @@
if (isTablet && !consumeTaskBar) {
portraitNav = landscapeNav = Insets.of(0, 0, 0, windowContext.getResources()
.getDimensionPixelSize(R.dimen.taskbar_size));
- } else if (hasNavbar) {
+ } else if (!isGesturalMode) {
portraitNav = Insets.of(0, 0, 0,
getSystemResource(windowContext, "navigation_bar_height", swDP));
landscapeNav = isTablet
diff --git a/src/com/android/launcher3/views/BubbleTextHolder.java b/src/com/android/launcher3/views/BubbleTextHolder.java
index 78aac06..42701c6 100644
--- a/src/com/android/launcher3/views/BubbleTextHolder.java
+++ b/src/com/android/launcher3/views/BubbleTextHolder.java
@@ -16,12 +16,14 @@
package com.android.launcher3.views;
import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.ItemInfoWithIcon;
/**
* Views that contain {@link BubbleTextView} should implement this interface.
*/
-public interface BubbleTextHolder {
+public interface BubbleTextHolder extends IconCache.ItemInfoUpdateReceiver {
BubbleTextView getBubbleText();
/**
@@ -29,6 +31,6 @@
*
* @param itemInfo the new itemInfo
*/
- default void onItemInfoChanged(ItemInfo itemInfo) {
- }
+ @Override
+ default void reapplyItemInfo(ItemInfoWithIcon itemInfo){};
}
diff --git a/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java b/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java
deleted file mode 100644
index a434d07..0000000
--- a/src_plugins/com/android/systemui/plugins/OverscrollPlugin.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2019 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.systemui.plugins;
-
-import android.view.MotionEvent;
-
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
-/**
- * Implement this interface to receive a callback when the user swipes right
- * to left on the gesture area. It won't fire if the user has quick switched to a previous app
- * (swiped right) and the current app isn't yet the active one (i.e., if swiping left would take
- * the user to a more recent app).
- */
-@ProvidesInterface(action = com.android.systemui.plugins.OverscrollPlugin.ACTION,
- version = com.android.systemui.plugins.OverscrollPlugin.VERSION)
-public interface OverscrollPlugin extends Plugin {
-
- String ACTION = "com.android.systemui.action.PLUGIN_LAUNCHER_OVERSCROLL";
- int VERSION = 4;
-
- String DEVICE_STATE_LOCKED = "Locked";
- String DEVICE_STATE_LAUNCHER = "Launcher";
- String DEVICE_STATE_APP = "App";
- String DEVICE_STATE_UNKNOWN = "Unknown";
-
- /**
- * @return true if the plugin is active and will accept overscroll gestures
- */
- boolean isActive();
-
- /**
- * Called when a touch has been recognized as an overscroll gesture.
- * @param horizontalDistancePx Horizontal distance from the last finger location to the finger
- * location when it first touched the screen.
- * @param verticalDistancePx Horizontal distance from the last finger location to the finger
- * location when it first touched the screen.
- * @param thresholdPx Minimum distance for gesture.
- * @param flingDistanceThresholdPx Minimum distance for gesture by fling.
- * @param flingVelocityThresholdPx Minimum velocity for gesture by fling.
- * @param deviceState String representing the current device state
- * @param underlyingActivity String representing the currently active Activity
- */
- void onTouchEvent(MotionEvent event,
- int horizontalDistancePx,
- int verticalDistancePx,
- int thresholdPx,
- int flingDistanceThresholdPx,
- int flingVelocityThresholdPx,
- String deviceState,
- String underlyingActivity);
-
- /**
- * @return `true` if overscroll gesture handling should override all other gestures.
- */
- boolean blockOtherGestures();
-
- /**
- * @return `true` if the overscroll gesture can pan the underlying app.
- */
- boolean allowsUnderlyingActivityOverscroll();
-}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 0ffbeeb..da6551c 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -288,13 +288,14 @@
}
/**
- * Removes all icons from homescreen and hotseat.
+ * Removes all items from workspace and populate default hotseat.
*/
- public void clearHomescreen() throws Throwable {
+ public void clearWorkspace() {
+ // First clear data to ensure hotseat is populated.
+ clearLauncherData();
+ // Next make provider call to clear everything apart from hotseat.
LauncherSettings.Settings.call(mTargetContext.getContentResolver(),
- LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
- LauncherSettings.Settings.call(mTargetContext.getContentResolver(),
- LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG);
+ LauncherSettings.Settings.METHOD_CLEAR_WORKSPACE);
resetLoaderState();
}
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index 5ea5d65..34dddf5 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -85,7 +85,7 @@
* @param acceptConfig accept the config activity
*/
private void runTest(boolean acceptConfig) throws Throwable {
- clearHomescreen();
+ clearWorkspace();
mDevice.pressHome();
final Widgets widgets = mLauncher.getWorkspace().openAllWidgets();
diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
index dad4f2b..3696755 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
@@ -47,7 +47,7 @@
@Test
@PortraitLandscape
public void testDragIcon() throws Throwable {
- clearHomescreen();
+ clearWorkspace();
mDevice.pressHome();
final LauncherAppWidgetProviderInfo widgetInfo =
@@ -81,7 +81,7 @@
@Test
@PortraitLandscape
public void testDragCustomShortcut() throws Throwable {
- clearHomescreen();
+ clearWorkspace();
mDevice.pressHome();
mLauncher.getWorkspace().openAllWidgets()
.getWidget("com.android.launcher3.testcomponent.CustomShortcutConfigActivity")
diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
index ccbb662..270c2ec 100644
--- a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
@@ -125,7 +125,7 @@
private void runTest(String activityMethod, boolean isWidget, ItemOperator itemMatcher,
Intent... commandIntents) throws Throwable {
- clearHomescreen();
+ clearWorkspace();
mDevice.pressHome();
// Open Pin item activity