Snap for 11494200 from e98d88ef2f to 24Q2-release
Change-Id: I8de1fe57f6d93f1e04c6f15d16fe6d9fc083db35
This commit is contained in:
@@ -2049,7 +2049,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
private final RemoteAnimationTarget[] mAppTargets;
|
||||
private final Matrix mMatrix = new Matrix();
|
||||
private final Point mTmpPos = new Point();
|
||||
private final Rect mCurrentRect = new Rect();
|
||||
private final RectF mCurrentRectF = new RectF();
|
||||
private final float mStartRadius;
|
||||
private final float mEndRadius;
|
||||
private final SurfaceTransactionApplier mSurfaceApplier;
|
||||
@@ -2116,25 +2116,24 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
}
|
||||
|
||||
if (target.mode == MODE_CLOSING) {
|
||||
transferRectToTargetCoordinate(target, currentRectF, false, currentRectF);
|
||||
currentRectF.round(mCurrentRect);
|
||||
transferRectToTargetCoordinate(target, currentRectF, false, mCurrentRectF);
|
||||
|
||||
// Scale the target window to match the currentRectF.
|
||||
final float scale;
|
||||
|
||||
// We need to infer the crop (we crop the window to match the currentRectF).
|
||||
if (mWindowStartBounds.height() > mWindowStartBounds.width()) {
|
||||
scale = Math.min(1f, currentRectF.width() / mWindowOriginalBounds.width());
|
||||
scale = Math.min(1f, mCurrentRectF.width() / mWindowOriginalBounds.width());
|
||||
|
||||
int unscaledHeight = (int) (mCurrentRect.height() * (1f / scale));
|
||||
int unscaledHeight = (int) (mCurrentRectF.height() * (1f / scale));
|
||||
int croppedHeight = mWindowStartBounds.height() - unscaledHeight;
|
||||
mTmpRect.set(0, 0, mWindowOriginalBounds.width(),
|
||||
mWindowStartBounds.height() - croppedHeight);
|
||||
} else {
|
||||
scale = Math.min(1f, currentRectF.height()
|
||||
scale = Math.min(1f, mCurrentRectF.height()
|
||||
/ mWindowOriginalBounds.height());
|
||||
|
||||
int unscaledWidth = (int) (mCurrentRect.width() * (1f / scale));
|
||||
int unscaledWidth = (int) (mCurrentRectF.width() * (1f / scale));
|
||||
int croppedWidth = mWindowStartBounds.width() - unscaledWidth;
|
||||
mTmpRect.set(0, 0, mWindowStartBounds.width() - croppedWidth,
|
||||
mWindowOriginalBounds.height());
|
||||
@@ -2142,7 +2141,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
|
||||
// Match size and position of currentRect.
|
||||
mMatrix.setScale(scale, scale);
|
||||
mMatrix.postTranslate(mCurrentRect.left, mCurrentRect.top);
|
||||
mMatrix.postTranslate(mCurrentRectF.left, mCurrentRectF.top);
|
||||
|
||||
builder.setMatrix(mMatrix)
|
||||
.setWindowCrop(mTmpRect)
|
||||
|
||||
@@ -219,7 +219,9 @@ public class WidgetPickerActivity extends BaseActivity {
|
||||
final boolean isHorizontallyResizable =
|
||||
(info.resizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0;
|
||||
if (mDesiredWidgetWidth > 0 && isHorizontallyResizable) {
|
||||
if (info.maxResizeWidth > 0 && info.maxResizeWidth < mDesiredWidgetWidth) {
|
||||
if (info.maxResizeWidth > 0
|
||||
&& info.maxResizeWidth >= info.minWidth
|
||||
&& info.maxResizeWidth < mDesiredWidgetWidth) {
|
||||
return rejectWidget(
|
||||
widget,
|
||||
"maxResizeWidth[%d] < mDesiredWidgetWidth[%d]",
|
||||
@@ -227,12 +229,13 @@ public class WidgetPickerActivity extends BaseActivity {
|
||||
mDesiredWidgetWidth);
|
||||
}
|
||||
|
||||
final int minWidth = info.minResizeWidth > 0 ? info.minResizeWidth : info.minWidth;
|
||||
final int minWidth = Math.min(info.minResizeWidth, info.minWidth);
|
||||
if (minWidth > mDesiredWidgetWidth) {
|
||||
return rejectWidget(
|
||||
widget,
|
||||
"minWidth[%d] > mDesiredWidgetWidth[%d]",
|
||||
minWidth,
|
||||
"min(minWidth[%d], minResizeWidth[%d]) > mDesiredWidgetWidth[%d]",
|
||||
info.minWidth,
|
||||
info.minResizeWidth,
|
||||
mDesiredWidgetWidth);
|
||||
}
|
||||
}
|
||||
@@ -240,7 +243,9 @@ public class WidgetPickerActivity extends BaseActivity {
|
||||
final boolean isVerticallyResizable =
|
||||
(info.resizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0;
|
||||
if (mDesiredWidgetHeight > 0 && isVerticallyResizable) {
|
||||
if (info.maxResizeHeight > 0 && info.maxResizeHeight < mDesiredWidgetHeight) {
|
||||
if (info.maxResizeHeight > 0
|
||||
&& info.maxResizeHeight >= info.minHeight
|
||||
&& info.maxResizeHeight < mDesiredWidgetHeight) {
|
||||
return rejectWidget(
|
||||
widget,
|
||||
"maxResizeHeight[%d] < mDesiredWidgetHeight[%d]",
|
||||
@@ -248,20 +253,19 @@ public class WidgetPickerActivity extends BaseActivity {
|
||||
mDesiredWidgetHeight);
|
||||
}
|
||||
|
||||
final int minHeight = info.minResizeHeight > 0 ? info.minResizeHeight : info.minHeight;
|
||||
final int minHeight = Math.min(info.minResizeHeight, info.minHeight);
|
||||
if (minHeight > mDesiredWidgetHeight) {
|
||||
return rejectWidget(
|
||||
widget,
|
||||
"minHeight[%d] > mDesiredWidgetHeight[%d]",
|
||||
minHeight,
|
||||
"min(minHeight[%d], minResizeHeight[%d]) > mDesiredWidgetHeight[%d]",
|
||||
info.minHeight,
|
||||
info.minResizeHeight,
|
||||
mDesiredWidgetHeight);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isHorizontallyResizable
|
||||
&& !isVerticallyResizable
|
||||
&& (info.minWidth < mDesiredWidgetWidth || info.minHeight < mDesiredWidgetHeight)) {
|
||||
return rejectWidget(widget, "too small and not resizeable");
|
||||
if (!isHorizontallyResizable || !isVerticallyResizable) {
|
||||
return rejectWidget(widget, "not resizeable");
|
||||
}
|
||||
|
||||
return acceptWidget(widget);
|
||||
@@ -271,12 +275,15 @@ public class WidgetPickerActivity extends BaseActivity {
|
||||
WidgetItem widget, String rejectionReason, Object... args) {
|
||||
return new WidgetAcceptabilityVerdict(
|
||||
false,
|
||||
widget.label,
|
||||
widget.widgetInfo != null
|
||||
? widget.widgetInfo.provider.flattenToShortString()
|
||||
: widget.label,
|
||||
String.format(Locale.ENGLISH, rejectionReason, args));
|
||||
}
|
||||
|
||||
private static WidgetAcceptabilityVerdict acceptWidget(WidgetItem widget) {
|
||||
return new WidgetAcceptabilityVerdict(true, widget.label, "");
|
||||
return new WidgetAcceptabilityVerdict(
|
||||
true, widget.widgetInfo.provider.flattenToShortString(), "");
|
||||
}
|
||||
|
||||
private record WidgetAcceptabilityVerdict(
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
|
||||
package com.android.launcher3.taskbar;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||
import com.android.quickstep.util.TISBindHelper;
|
||||
|
||||
/**
|
||||
* A data source which integrates with a Launcher instance, used specifically for a
|
||||
@@ -50,4 +53,10 @@ public class DesktopTaskbarUIController extends TaskbarUIController {
|
||||
public boolean supportsVisualStashing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected TISBindHelper getTISBindHelper() {
|
||||
return mLauncher.getTISBindHelper();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,11 +21,14 @@ import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASH
|
||||
|
||||
import android.animation.Animator;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
import com.android.quickstep.TopTaskTracker;
|
||||
import com.android.quickstep.fallback.RecentsState;
|
||||
import com.android.quickstep.util.TISBindHelper;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
@@ -124,4 +127,10 @@ public class FallbackTaskbarUIController extends TaskbarUIController {
|
||||
.get(mControllers.taskbarActivityContext).getCachedTopTask(true);
|
||||
return topTask.isHomeTask() || topTask.isRecentsTask();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected TISBindHelper getTISBindHelper() {
|
||||
return mRecentsActivity.getTISBindHelper();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
|
||||
KeyboardQuickSwitchTaskView taskView = (KeyboardQuickSwitchTaskView) layoutInflater.inflate(
|
||||
R.layout.keyboard_quick_switch_taskview, mContent, false);
|
||||
taskView.setId(View.generateViewId());
|
||||
taskView.setOnClickListener(v -> mViewCallbacks.launchTappedTask(index));
|
||||
taskView.setOnClickListener(v -> mViewCallbacks.launchTaskAt(index));
|
||||
|
||||
LayoutParams lp = new LayoutParams(width, mTaskViewHeight);
|
||||
// Create a left-to-right ordering of views (or right-to-left in RTL locales)
|
||||
@@ -186,7 +186,7 @@ public class KeyboardQuickSwitchView extends ConstraintLayout {
|
||||
KeyboardQuickSwitchTaskView overviewButton =
|
||||
(KeyboardQuickSwitchTaskView) layoutInflater.inflate(
|
||||
R.layout.keyboard_quick_switch_overview, this, false);
|
||||
overviewButton.setOnClickListener(v -> mViewCallbacks.launchTappedTask(MAX_TASKS));
|
||||
overviewButton.setOnClickListener(v -> mViewCallbacks.launchTaskAt(MAX_TASKS));
|
||||
|
||||
overviewButton.<TextView>findViewById(R.id.text).setText(overflowString);
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import android.animation.Animator;
|
||||
import android.app.ActivityOptions;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.window.RemoteTransition;
|
||||
|
||||
@@ -137,7 +136,6 @@ public class KeyboardQuickSwitchViewController {
|
||||
}
|
||||
// Even with a valid index, this can be null if the user tries to quick switch before the
|
||||
// views have been added in the KeyboardQuickSwitchView.
|
||||
View taskView = mKeyboardQuickSwitchView.getTaskAt(index);
|
||||
GroupTask task = mControllerCallbacks.getTaskAt(index);
|
||||
if (task == null) {
|
||||
return Math.max(0, index);
|
||||
@@ -198,13 +196,18 @@ public class KeyboardQuickSwitchViewController {
|
||||
&& keyCode != KeyEvent.KEYCODE_DPAD_RIGHT
|
||||
&& keyCode != KeyEvent.KEYCODE_DPAD_LEFT
|
||||
&& keyCode != KeyEvent.KEYCODE_GRAVE
|
||||
&& keyCode != KeyEvent.KEYCODE_ESCAPE) {
|
||||
&& keyCode != KeyEvent.KEYCODE_ESCAPE
|
||||
&& keyCode != KeyEvent.KEYCODE_ENTER) {
|
||||
return false;
|
||||
}
|
||||
if (keyCode == KeyEvent.KEYCODE_GRAVE || keyCode == KeyEvent.KEYCODE_ESCAPE) {
|
||||
closeQuickSwitchView(true);
|
||||
return true;
|
||||
}
|
||||
if (keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||
launchTaskAt(mCurrentFocusIndex);
|
||||
return true;
|
||||
}
|
||||
if (!allowTraversal) {
|
||||
return false;
|
||||
}
|
||||
@@ -234,9 +237,10 @@ public class KeyboardQuickSwitchViewController {
|
||||
mCurrentFocusIndex = index;
|
||||
}
|
||||
|
||||
void launchTappedTask(int index) {
|
||||
KeyboardQuickSwitchViewController.this.launchTaskAt(index);
|
||||
closeQuickSwitchView(true);
|
||||
void launchTaskAt(int index) {
|
||||
mCurrentFocusIndex = Utilities.boundToRange(
|
||||
index, 0, mKeyboardQuickSwitchView.getChildCount() - 1);
|
||||
mControllers.taskbarActivityContext.launchKeyboardFocusedTask();
|
||||
}
|
||||
|
||||
void updateThumbnailInBackground(Task task, Consumer<ThumbnailData> callback) {
|
||||
|
||||
@@ -52,6 +52,7 @@ import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.quickstep.LauncherActivityInterface;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks;
|
||||
import com.android.quickstep.util.GroupTask;
|
||||
import com.android.quickstep.util.TISBindHelper;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -428,6 +429,12 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
||||
mTaskbarLauncherStateController.resetIconAlignment();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected TISBindHelper getTISBindHelper() {
|
||||
return mLauncher.getTISBindHelper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dumpLogs(String prefix, PrintWriter pw) {
|
||||
super.dumpLogs(prefix, pw);
|
||||
|
||||
@@ -505,52 +505,26 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
|
||||
/**
|
||||
* Creates {@link WindowManager.LayoutParams} for Taskbar, and also sets LP.paramsForRotation
|
||||
* for taskbar showing as navigation bar
|
||||
* for taskbar
|
||||
*/
|
||||
private WindowManager.LayoutParams createAllWindowParams() {
|
||||
final int windowType =
|
||||
ENABLE_TASKBAR_NAVBAR_UNIFICATION ? TYPE_NAVIGATION_BAR : TYPE_NAVIGATION_BAR_PANEL;
|
||||
WindowManager.LayoutParams windowLayoutParams =
|
||||
createDefaultWindowLayoutParams(windowType, TaskbarActivityContext.WINDOW_TITLE);
|
||||
if (!isPhoneButtonNavMode()) {
|
||||
return windowLayoutParams;
|
||||
}
|
||||
|
||||
// Provide WM layout params for all rotations to cache, see NavigationBar#getBarLayoutParams
|
||||
int width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
int height = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
int gravity = Gravity.BOTTOM;
|
||||
windowLayoutParams.paramsForRotation = new WindowManager.LayoutParams[4];
|
||||
for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
|
||||
WindowManager.LayoutParams lp =
|
||||
createDefaultWindowLayoutParams(windowType,
|
||||
TaskbarActivityContext.WINDOW_TITLE);
|
||||
switch (rot) {
|
||||
case Surface.ROTATION_0, Surface.ROTATION_180 -> {
|
||||
// Defaults are fine
|
||||
width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
height = mLastRequestedNonFullscreenSize;
|
||||
gravity = Gravity.BOTTOM;
|
||||
}
|
||||
case Surface.ROTATION_90 -> {
|
||||
width = mLastRequestedNonFullscreenSize;
|
||||
height = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
gravity = Gravity.END;
|
||||
}
|
||||
case Surface.ROTATION_270 -> {
|
||||
width = mLastRequestedNonFullscreenSize;
|
||||
height = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
gravity = Gravity.START;
|
||||
}
|
||||
|
||||
if (isPhoneButtonNavMode()) {
|
||||
populatePhoneButtonNavModeWindowLayoutParams(rot, lp);
|
||||
}
|
||||
lp.width = width;
|
||||
lp.height = height;
|
||||
lp.gravity = gravity;
|
||||
windowLayoutParams.paramsForRotation[rot] = lp;
|
||||
}
|
||||
|
||||
// Override current layout params
|
||||
// Override with current layout params
|
||||
WindowManager.LayoutParams currentParams =
|
||||
windowLayoutParams.paramsForRotation[getDisplay().getRotation()];
|
||||
windowLayoutParams.width = currentParams.width;
|
||||
@@ -560,6 +534,32 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
return windowLayoutParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update {@link WindowManager.LayoutParams} with values specific to phone and 3 button
|
||||
* navigation users
|
||||
*/
|
||||
private void populatePhoneButtonNavModeWindowLayoutParams(int rot,
|
||||
WindowManager.LayoutParams lp) {
|
||||
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
lp.height = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
lp.gravity = Gravity.BOTTOM;
|
||||
|
||||
// Override with per-rotation specific values
|
||||
switch (rot) {
|
||||
case Surface.ROTATION_0, Surface.ROTATION_180 -> {
|
||||
lp.height = mLastRequestedNonFullscreenSize;
|
||||
}
|
||||
case Surface.ROTATION_90 -> {
|
||||
lp.width = mLastRequestedNonFullscreenSize;
|
||||
lp.gravity = Gravity.END;
|
||||
}
|
||||
case Surface.ROTATION_270 -> {
|
||||
lp.width = mLastRequestedNonFullscreenSize;
|
||||
lp.gravity = Gravity.START;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onConfigurationChanged(@Config int configChanges) {
|
||||
mControllers.onConfigurationChanged(configChanges);
|
||||
if (!mIsUserSetupComplete) {
|
||||
@@ -920,8 +920,10 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
}
|
||||
if (landscapePhoneButtonNav) {
|
||||
mWindowLayoutParams.width = size;
|
||||
mWindowLayoutParams.paramsForRotation[getDisplay().getRotation()].width = size;
|
||||
} else {
|
||||
mWindowLayoutParams.height = size;
|
||||
mWindowLayoutParams.paramsForRotation[getDisplay().getRotation()].height = size;
|
||||
}
|
||||
mControllers.taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
|
||||
notifyUpdateLayoutParams();
|
||||
@@ -1485,6 +1487,10 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
btv.post(() -> mControllers.taskbarPopupController.showForIcon(btv));
|
||||
}
|
||||
|
||||
public void launchKeyboardFocusedTask() {
|
||||
mControllers.uiController.launchKeyboardFocusedTask();
|
||||
}
|
||||
|
||||
public boolean isInApp() {
|
||||
return mControllers.taskbarStashController.isInApp();
|
||||
}
|
||||
|
||||
@@ -118,11 +118,9 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas
|
||||
getProvidedInsets(insetsRoundedCornerFlag)
|
||||
}
|
||||
|
||||
if (!context.isGestureNav) {
|
||||
if (windowLayoutParams.paramsForRotation != null) {
|
||||
for (layoutParams in windowLayoutParams.paramsForRotation) {
|
||||
layoutParams.providedInsets = getProvidedInsets(insetsRoundedCornerFlag)
|
||||
}
|
||||
if (windowLayoutParams.paramsForRotation != null) {
|
||||
for (layoutParams in windowLayoutParams.paramsForRotation) {
|
||||
layoutParams.providedInsets = getProvidedInsets(insetsRoundedCornerFlag)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,19 +154,12 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas
|
||||
)
|
||||
}
|
||||
|
||||
val gravity = windowLayoutParams.gravity
|
||||
|
||||
// Pre-calculate insets for different providers across different rotations for this gravity
|
||||
for (rotation in Surface.ROTATION_0..Surface.ROTATION_270) {
|
||||
// Add insets for navbar rotated params
|
||||
if (windowLayoutParams.paramsForRotation != null) {
|
||||
val layoutParams = windowLayoutParams.paramsForRotation[rotation]
|
||||
for (provider in layoutParams.providedInsets) {
|
||||
setProviderInsets(provider, layoutParams.gravity, rotation)
|
||||
}
|
||||
}
|
||||
for (provider in windowLayoutParams.providedInsets) {
|
||||
setProviderInsets(provider, gravity, rotation)
|
||||
val layoutParams = windowLayoutParams.paramsForRotation[rotation]
|
||||
for (provider in layoutParams.providedInsets) {
|
||||
setProviderInsets(provider, layoutParams.gravity, rotation)
|
||||
}
|
||||
}
|
||||
context.notifyUpdateLayoutParams()
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
|
||||
import static com.android.quickstep.OverviewCommandHelper.TYPE_HIDE;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
@@ -38,7 +39,9 @@ import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.SplitConfigurationOptions;
|
||||
import com.android.quickstep.OverviewCommandHelper;
|
||||
import com.android.quickstep.util.GroupTask;
|
||||
import com.android.quickstep.util.TISBindHelper;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
|
||||
@@ -361,6 +364,28 @@ public class TaskbarUIController {
|
||||
/** Adjusts the hotseat for the bubble bar. */
|
||||
public void adjustHotseatForBubbleBar(boolean isBubbleBarVisible) {}
|
||||
|
||||
@Nullable
|
||||
protected TISBindHelper getTISBindHelper() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the focused task in the Keyboard Quick Switch view through the OverviewCommandHelper
|
||||
* <p>
|
||||
* Use this helper method when the focused task may be the overview task.
|
||||
*/
|
||||
public void launchKeyboardFocusedTask() {
|
||||
TISBindHelper tisBindHelper = getTISBindHelper();
|
||||
if (tisBindHelper == null) {
|
||||
return;
|
||||
}
|
||||
OverviewCommandHelper overviewCommandHelper = tisBindHelper.getOverviewCommandHelper();
|
||||
if (overviewCommandHelper == null) {
|
||||
return;
|
||||
}
|
||||
overviewCommandHelper.addCommand(TYPE_HIDE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the taskbar based on the visibility of the launcher.
|
||||
* @param isVisible True if launcher is visible, false otherwise.
|
||||
|
||||
@@ -650,10 +650,13 @@ public class QuickstepLauncher extends Launcher {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// Back dispatcher is registered in {@link BaseActivity#onCreate}. For predictive back to
|
||||
// work, we must opt-in BEFORE registering back dispatcher. So we need to call
|
||||
// setEnableOnBackInvokedCallback() before super.onCreate()
|
||||
if (Utilities.ATLEAST_U && enablePredictiveBackGesture()) {
|
||||
getApplicationInfo().setEnableOnBackInvokedCallback(true);
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
if (savedInstanceState != null) {
|
||||
mPendingSplitSelectInfo = ObjectWrapper.unwrap(
|
||||
savedInstanceState.getIBinder(PENDING_SPLIT_SELECT_INFO));
|
||||
@@ -1360,6 +1363,11 @@ public class QuickstepLauncher extends Launcher {
|
||||
return (mTaskbarUIController != null && mTaskbarUIController.hasBubbles());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TISBindHelper getTISBindHelper() {
|
||||
return mTISBindHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleIncorrectSplitTargetSelection() {
|
||||
if (!enableSplitContextually() || !mSplitSelectStateController.isSplitSelectActive()) {
|
||||
|
||||
+1
-2
@@ -324,12 +324,12 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
||||
|
||||
@Override
|
||||
public void onDragEnd(PointF velocity) {
|
||||
cancelAnimations();
|
||||
boolean horizontalFling = mSwipeDetector.isFling(velocity.x);
|
||||
boolean verticalFling = mSwipeDetector.isFling(velocity.y);
|
||||
boolean noFling = !horizontalFling && !verticalFling;
|
||||
if (mMotionPauseDetector.isPaused() && noFling) {
|
||||
// Going to Overview.
|
||||
cancelAnimations();
|
||||
InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_QUICK_SWITCH);
|
||||
|
||||
StateAnimationConfig config = new StateAnimationConfig();
|
||||
@@ -455,7 +455,6 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
||||
nonOverviewAnim.setDuration(Math.max(xDuration, yDuration));
|
||||
mNonOverviewAnim.setEndAction(() -> onAnimationToStateCompleted(targetState));
|
||||
|
||||
cancelAnimations();
|
||||
xOverviewAnim.start();
|
||||
yOverviewAnim.start();
|
||||
nonOverviewAnim.start();
|
||||
|
||||
@@ -52,6 +52,7 @@ import android.window.BackMotionEvent;
|
||||
import android.window.BackProgressAnimator;
|
||||
import android.window.IOnBackInvokedCallback;
|
||||
|
||||
import com.android.app.animation.Interpolators;
|
||||
import com.android.internal.view.AppearanceRegion;
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
@@ -103,7 +104,8 @@ public class LauncherBackAnimationController {
|
||||
private float mWindowScaleEndCornerRadius;
|
||||
private float mWindowScaleStartCornerRadius;
|
||||
private final Interpolator mCancelInterpolator;
|
||||
private final Interpolator mProgressInterpolator = new DecelerateInterpolator();
|
||||
private final Interpolator mProgressInterpolator = Interpolators.STANDARD_DECELERATE;
|
||||
private final Interpolator mVerticalMoveInterpolator = new DecelerateInterpolator();
|
||||
private final PointF mInitialTouchPos = new PointF();
|
||||
|
||||
private RemoteAnimationTarget mBackTarget;
|
||||
@@ -376,7 +378,7 @@ public class LauncherBackAnimationController {
|
||||
float yDirection = rawYDelta < 0 ? -1 : 1;
|
||||
// limit yDelta interpretation to 1/2 of screen height in either direction
|
||||
float deltaYRatio = Math.min(screenHeight / 2f, Math.abs(rawYDelta)) / (screenHeight / 2f);
|
||||
float interpolatedYRatio = mProgressInterpolator.getInterpolation(deltaYRatio);
|
||||
float interpolatedYRatio = mVerticalMoveInterpolator.getInterpolation(deltaYRatio);
|
||||
// limit y-shift so surface never passes 8dp screen margin
|
||||
float deltaY = yDirection * interpolatedYRatio * Math.max(0f, (screenHeight - height)
|
||||
/ 2f - mWindowScaleMarginX);
|
||||
|
||||
@@ -498,4 +498,9 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
OverviewCommandHelper overviewCommandHelper = mTISBindHelper.getOverviewCommandHelper();
|
||||
return overviewCommandHelper == null || overviewCommandHelper.canStartHomeSafely();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TISBindHelper getTISBindHelper() {
|
||||
return mTISBindHelper;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package com.android.quickstep.util;
|
||||
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_PAIR_LAUNCH;
|
||||
import static com.android.launcher3.model.data.AppInfo.PACKAGE_KEY_COMPARATOR;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
|
||||
@@ -30,6 +31,7 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.isPersisten
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
@@ -42,10 +44,12 @@ import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.allapps.AllAppsStore;
|
||||
import com.android.launcher3.apppairs.AppPairIcon;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.logging.InstanceId;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
@@ -93,14 +97,38 @@ public class AppPairsController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new app pair ItemInfo and adds it to the workspace
|
||||
* Creates a new app pair ItemInfo and adds it to the workspace.
|
||||
* <br>
|
||||
* We create WorkspaceItemInfos to save onto the app pair in the following way:
|
||||
* <br> 1. We verify that the ComponentKey from our Recents tile corresponds to a real
|
||||
* launchable app in the app store.
|
||||
* <br> 2. If it doesn't, we search for the underlying launchable app via package name, and use
|
||||
* that instead.
|
||||
* <br> 3. If that fails, we re-use the existing WorkspaceItemInfo by cloning it and replacing
|
||||
* its intent with one from PackageManager.
|
||||
* <br> 4. If everything fails, we just use the WorkspaceItemInfo as is, with its existing
|
||||
* intent. This is not preferred, but will still work in most cases (notably it will not work
|
||||
* well on trampoline apps).
|
||||
*/
|
||||
public void saveAppPair(GroupedTaskView gtv) {
|
||||
TaskView.TaskIdAttributeContainer[] attributes = gtv.getTaskIdAttributeContainers();
|
||||
WorkspaceItemInfo app1 = attributes[0].getItemInfo().clone();
|
||||
WorkspaceItemInfo app2 = attributes[1].getItemInfo().clone();
|
||||
app1.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
|
||||
app2.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
|
||||
WorkspaceItemInfo recentsInfo1 = attributes[0].getItemInfo();
|
||||
WorkspaceItemInfo recentsInfo2 = attributes[0].getItemInfo();
|
||||
WorkspaceItemInfo app1 = lookupLaunchableItem(recentsInfo1.getComponentKey());
|
||||
WorkspaceItemInfo app2 = lookupLaunchableItem(recentsInfo2.getComponentKey());
|
||||
|
||||
// If app lookup fails, use the WorkspaceItemInfo that we have, but try to override default
|
||||
// intent with one from PackageManager.
|
||||
if (app1 == null) {
|
||||
Log.w(TAG, "Creating an app pair, but app lookup for " + recentsInfo1.title
|
||||
+ " failed. Falling back to the WorkspaceItemInfo from Recents.");
|
||||
app1 = convertRecentsItemToAppItem(recentsInfo1);
|
||||
}
|
||||
if (app2 == null) {
|
||||
Log.w(TAG, "Creating an app pair, but app lookup for " + recentsInfo2.title
|
||||
+ " failed. Falling back to the WorkspaceItemInfo from Recents.");
|
||||
app2 = convertRecentsItemToAppItem(recentsInfo2);
|
||||
}
|
||||
|
||||
@PersistentSnapPosition int snapPosition = gtv.getSnapPosition();
|
||||
if (!isPersistentSnapPosition(snapPosition)) {
|
||||
@@ -188,6 +216,52 @@ public class AppPairsController {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new launchable WorkspaceItemInfo of itemType=ITEM_TYPE_APPLICATION by looking the
|
||||
* ComponentKey up in the AllAppsStore. If no app is found, attempts a lookup by package
|
||||
* instead. If that lookup fails, returns null.
|
||||
*/
|
||||
@Nullable
|
||||
private WorkspaceItemInfo lookupLaunchableItem(@Nullable ComponentKey key) {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AllAppsStore appsStore = Launcher.getLauncher(mContext).getAppsView().getAppsStore();
|
||||
|
||||
// Lookup by ComponentKey
|
||||
AppInfo appInfo = appsStore.getApp(key);
|
||||
if (appInfo == null) {
|
||||
// Lookup by package
|
||||
appInfo = appsStore.getApp(key, PACKAGE_KEY_COMPARATOR);
|
||||
}
|
||||
|
||||
return appInfo != null ? appInfo.makeWorkspaceItem(mContext) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a WorkspaceItemInfo of itemType=ITEM_TYPE_TASK (from a Recents task) to a new
|
||||
* WorkspaceItemInfo of itemType=ITEM_TYPE_APPLICATION.
|
||||
*/
|
||||
private WorkspaceItemInfo convertRecentsItemToAppItem(WorkspaceItemInfo recentsItem) {
|
||||
if (recentsItem.itemType != LauncherSettings.Favorites.ITEM_TYPE_TASK) {
|
||||
Log.w(TAG, "Expected ItemInfo of type ITEM_TYPE_TASK, but received "
|
||||
+ recentsItem.itemType);
|
||||
}
|
||||
|
||||
WorkspaceItemInfo launchableItem = recentsItem.clone();
|
||||
PackageManager p = mContext.getPackageManager();
|
||||
Intent launchIntent = p.getLaunchIntentForPackage(recentsItem.getTargetPackage());
|
||||
Log.w(TAG, "Initial intent from Recents: " + launchableItem.intent + "\n"
|
||||
+ "Intent from PackageManager: " + launchIntent);
|
||||
if (launchIntent != null) {
|
||||
// If lookup from PackageManager fails, just use the existing intent
|
||||
launchableItem.intent = launchIntent;
|
||||
}
|
||||
launchableItem.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
|
||||
return launchableItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the complicated logic for how to animate an app pair entrance when already inside an
|
||||
* app or app pair.
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
@@ -138,12 +139,22 @@ public class AllAppsStore<T extends Context & ActivityContext> {
|
||||
/**
|
||||
* Returns {@link AppInfo} if any apps matches with provided {@link ComponentKey}, otherwise
|
||||
* null.
|
||||
*
|
||||
* Uses {@link AppInfo#COMPONENT_KEY_COMPARATOR} as a default comparator.
|
||||
*/
|
||||
@Nullable
|
||||
public AppInfo getApp(ComponentKey key) {
|
||||
return getApp(key, COMPONENT_KEY_COMPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic version of {@link #getApp(ComponentKey)} that allows comparator to be specified.
|
||||
*/
|
||||
@Nullable
|
||||
public AppInfo getApp(ComponentKey key, Comparator<AppInfo> comparator) {
|
||||
mTempInfo.componentName = key.componentName;
|
||||
mTempInfo.user = key.user;
|
||||
int index = Arrays.binarySearch(mApps, mTempInfo, COMPONENT_KEY_COMPARATOR);
|
||||
int index = Arrays.binarySearch(mApps, mTempInfo, comparator);
|
||||
return index < 0 ? null : mApps[index];
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,9 @@ public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
|
||||
return uc != 0 ? uc : a.componentName.compareTo(b.componentName);
|
||||
};
|
||||
|
||||
public static final Comparator<AppInfo> PACKAGE_KEY_COMPARATOR = Comparator.comparingInt(
|
||||
(AppInfo a) -> a.user.hashCode()).thenComparing(ItemInfo::getTargetPackage);
|
||||
|
||||
/**
|
||||
* The intent used to start the application.
|
||||
*/
|
||||
|
||||
@@ -34,6 +34,17 @@ import com.android.launcher3.util.Executors;
|
||||
*/
|
||||
public abstract class BaseLauncherAppWidgetHostView extends NavigableAppWidgetHostView {
|
||||
|
||||
private static final ViewOutlineProvider VIEW_OUTLINE_PROVIDER = new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
// Since ShortcutAndWidgetContainer sets clipChildren to false, we should restrict the
|
||||
// outline to be the view bounds, otherwise widgets might draw themselves outside of
|
||||
// the launcher view. Setting alpha to 0 to match the previous behavior.
|
||||
outline.setRect(0, 0, view.getWidth(), view.getHeight());
|
||||
outline.setAlpha(.0f);
|
||||
}
|
||||
};
|
||||
|
||||
protected final LayoutInflater mInflater;
|
||||
|
||||
private final Rect mEnforcedRectangle = new Rect();
|
||||
@@ -49,10 +60,13 @@ public abstract class BaseLauncherAppWidgetHostView extends NavigableAppWidgetHo
|
||||
}
|
||||
};
|
||||
|
||||
private boolean mIsCornerRadiusEnforced;
|
||||
|
||||
public BaseLauncherAppWidgetHostView(Context context) {
|
||||
super(context);
|
||||
|
||||
setExecutor(Executors.THREAD_POOL_EXECUTOR);
|
||||
setClipToOutline(true);
|
||||
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(getContext());
|
||||
@@ -84,8 +98,8 @@ public abstract class BaseLauncherAppWidgetHostView extends NavigableAppWidgetHo
|
||||
|
||||
@UiThread
|
||||
private void resetRoundedCorners() {
|
||||
setOutlineProvider(ViewOutlineProvider.BACKGROUND);
|
||||
setClipToOutline(false);
|
||||
setOutlineProvider(VIEW_OUTLINE_PROVIDER);
|
||||
mIsCornerRadiusEnforced = false;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@@ -104,7 +118,7 @@ public abstract class BaseLauncherAppWidgetHostView extends NavigableAppWidgetHo
|
||||
background,
|
||||
mEnforcedRectangle);
|
||||
setOutlineProvider(mCornerRadiusEnforcementOutline);
|
||||
setClipToOutline(true);
|
||||
mIsCornerRadiusEnforced = true;
|
||||
invalidateOutline();
|
||||
}
|
||||
|
||||
@@ -115,6 +129,6 @@ public abstract class BaseLauncherAppWidgetHostView extends NavigableAppWidgetHo
|
||||
|
||||
/** Returns true if the corner radius are enforced for this App Widget. */
|
||||
public boolean hasEnforcedCornerRadius() {
|
||||
return getClipToOutline();
|
||||
return mIsCornerRadiusEnforced;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user