diff --git a/Android.bp b/Android.bp index b3027bc440..0a55675d43 100644 --- a/Android.bp +++ b/Android.bp @@ -228,7 +228,7 @@ filegroup { ], } -// Common source files used to build go launcher +// Common source files used to build go launcher except go/src files filegroup { name: "launcher-go-src-no-build-config", srcs: [ @@ -236,8 +236,6 @@ filegroup { "src/**/*.kt", "quickstep/src/**/*.java", "quickstep/src/**/*.kt", - "go/src/**/*.java", - "go/src/**/*.kt", "go/quickstep/src/**/*.java", "go/quickstep/src/**/*.kt", ], diff --git a/go/src/com/android/launcher3/util/AbsGridOccupancy.java b/go/src/com/android/launcher3/util/AbsGridOccupancy.java new file mode 100644 index 0000000000..4a46bd193f --- /dev/null +++ b/go/src/com/android/launcher3/util/AbsGridOccupancy.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.util; + +/** + * Defines method to find the next vacant cell on a grid. + * This uses the default top-down, left-right approach and can be over-written through + * code swaps in different launchers. + */ +public abstract class AbsGridOccupancy { + + /** + * Find the first vacant cell, if there is one. + * + * @param vacantOut Holds the x and y coordinate of the vacant cell + * @param spanX Horizontal cell span. + * @param spanY Vertical cell span. + * + * @return true if a vacant cell was found + */ + protected boolean findVacantCell(int[] vacantOut, boolean[][] cells, int countX, int countY, + int spanX, int spanY) { + for (int y = 0; (y + spanY) <= countY; y++) { + for (int x = 0; (x + spanX) <= countX; x++) { + boolean available = !cells[x][y]; + out: + for (int i = x; i < x + spanX; i++) { + for (int j = y; j < y + spanY; j++) { + available = available && !cells[i][j]; + if (!available) break out; + } + } + if (available) { + vacantOut[0] = x; + vacantOut[1] = y; + return true; + } + } + } + return false; + } +} diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index 5b912ade65..097609f2d9 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -1161,7 +1161,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner, false /* startAtFrontOfQueue */), mLauncher.getIApplicationThread()); mLauncherOpenTransition.addHomeOpenCheck(mLauncher.getComponentName()); - SystemUiProxy.INSTANCE.getNoCreate().registerRemoteTransition(mLauncherOpenTransition); + SystemUiProxy.INSTANCE.get(mLauncher).registerRemoteTransition(mLauncherOpenTransition); } if (mBackAnimationController != null) { mBackAnimationController.registerBackCallbacks(mHandler); @@ -1172,7 +1172,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener unregisterRemoteAnimations(); unregisterRemoteTransitions(); mStartingWindowListener.setTransitionManager(null); - SystemUiProxy.INSTANCE.getNoCreate().setStartingWindowListener(null); + SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(null); } private void unregisterRemoteAnimations() { @@ -1196,7 +1196,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener } if (hasControlRemoteAppTransitionPermission()) { if (mLauncherOpenTransition == null) return; - SystemUiProxy.INSTANCE.getNoCreate().unregisterRemoteTransition( + SystemUiProxy.INSTANCE.get(mLauncher).unregisterRemoteTransition( mLauncherOpenTransition); mLauncherOpenTransition = null; mWallpaperOpenTransitionRunner = null; diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java index 175a1d92b2..f65b907668 100644 --- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java @@ -210,7 +210,7 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT 0, 1)); // Center nav buttons in new height for IME. float transForIme = (mContext.getDeviceProfile().taskbarSize - - mContext.getTaskbarHeightForIme()) / 2f; + - mControllers.taskbarInsetsController.getTaskbarHeightForIme()) / 2f; // For gesture nav, nav buttons only show for IME anyway so keep them translated down. float defaultButtonTransY = alwaysShowButtons ? 0 : transForIme; mPropertyHolders.add(new StatePropertyHolder(mTaskbarNavButtonTranslationYForIme, diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index ef9c62dfd6..9561b749f2 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -27,9 +27,6 @@ import static com.android.launcher3.ResourceUtils.getBoolByName; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED; -import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT; -import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR; -import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_SIZE; import android.animation.AnimatorSet; import android.app.ActivityOptions; @@ -39,7 +36,6 @@ import android.content.Intent; import android.content.pm.ActivityInfo.Config; import android.content.pm.LauncherApps; import android.content.res.Resources; -import android.graphics.Insets; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Process; @@ -88,7 +84,6 @@ import com.android.launcher3.views.ActivityContext; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.rotation.RotationButtonController; import com.android.systemui.shared.system.ActivityManagerWrapper; -import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider; import java.io.PrintWriter; @@ -113,7 +108,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { private final WindowManager mWindowManager; private final @Nullable RoundedCorner mLeftCorner, mRightCorner; - private final int mTaskbarHeightForIme; private WindowManager.LayoutParams mWindowLayoutParams; private boolean mIsFullscreen; // The size we should return to when we call setTaskbarWindowFullscreen(false) @@ -154,7 +148,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), 0); updateIconSize(resources); - mTaskbarHeightForIme = resources.getDimensionPixelSize(R.dimen.taskbar_ime_size); // Get display and corners first, as views might use them in constructor. Display display = windowContext.getDisplay(); @@ -202,29 +195,14 @@ public class TaskbarActivityContext extends BaseTaskbarContext { new TaskbarAutohideSuspendController(this), new TaskbarPopupController(this), new TaskbarForceVisibleImmersiveController(this), - new TaskbarAllAppsController(this)); + new TaskbarAllAppsController(this), + new TaskbarInsetsController(this)); } public void init(TaskbarSharedState sharedState) { mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight(); mWindowLayoutParams = createDefaultWindowLayoutParams(); - WindowManagerWrapper wmWrapper = WindowManagerWrapper.getInstance(); - wmWrapper.setProvidesInsetsTypes( - mWindowLayoutParams, - new int[] { ITYPE_EXTRA_NAVIGATION_BAR, ITYPE_BOTTOM_TAPPABLE_ELEMENT } - ); - // Adjust the frame by the rounded corners (ie. leaving just the bar as the inset) when - // the IME is showing - mWindowLayoutParams.providedInternalImeInsets = new Insets[ITYPE_SIZE]; - final Insets reducingSize = Insets.of(0, - getDefaultTaskbarWindowHeight() - mTaskbarHeightForIme, 0, 0); - mWindowLayoutParams.providedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR] = reducingSize; - mWindowLayoutParams.providedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT] = - reducingSize; - - mWindowLayoutParams.insetsRoundedCornerFrame = true; - // Initialize controllers after all are constructed. mControllers.init(sharedState); updateSysuiStateFlags(sharedState.sysuiStateFlags, true /* fromInit */); @@ -304,6 +282,10 @@ public class TaskbarActivityContext extends BaseTaskbarContext { return mRightCorner == null ? 0 : mRightCorner.getRadius(); } + public WindowManager.LayoutParams getWindowLayoutParams() { + return mWindowLayoutParams; + } + @Override public TaskbarDragLayer getDragLayer() { return mDragLayer; @@ -577,14 +559,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { } } mWindowLayoutParams.height = height; - final Insets reducingSize = - Insets.of(0, height - mTaskbarHeightForIme, 0, 0); - if (mWindowLayoutParams.providedInternalImeInsets == null) { - mWindowLayoutParams.providedInternalImeInsets = new Insets[ITYPE_SIZE]; - } - mWindowLayoutParams.providedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR] = reducingSize; - mWindowLayoutParams.providedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT] = - reducingSize; + mControllers.taskbarInsetsController.onTaskbarWindowHeightChanged(); mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams); } @@ -595,13 +570,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { return mDeviceProfile.taskbarSize + Math.max(getLeftCornerRadius(), getRightCornerRadius()); } - /** - * Returns the bottom insets taskbar provides to the IME when IME is visible. - */ - public int getTaskbarHeightForIme() { - return mTaskbarHeightForIme; - } - /** * Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar * window. diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java index a3586396ea..5d3a1520fc 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java @@ -51,6 +51,7 @@ public class TaskbarControllers { public final TaskbarPopupController taskbarPopupController; public final TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController; public final TaskbarAllAppsController taskbarAllAppsController; + public final TaskbarInsetsController taskbarInsetsController; @Nullable private LoggableTaskbarController[] mControllersToLog = null; @@ -76,7 +77,8 @@ public class TaskbarControllers { TaskbarAutohideSuspendController taskbarAutoHideSuspendController, TaskbarPopupController taskbarPopupController, TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController, - TaskbarAllAppsController taskbarAllAppsController) { + TaskbarAllAppsController taskbarAllAppsController, + TaskbarInsetsController taskbarInsetsController) { this.taskbarActivityContext = taskbarActivityContext; this.taskbarDragController = taskbarDragController; this.navButtonController = navButtonController; @@ -94,6 +96,7 @@ public class TaskbarControllers { this.taskbarPopupController = taskbarPopupController; this.taskbarForceVisibleImmersiveController = taskbarForceVisibleImmersiveController; this.taskbarAllAppsController = taskbarAllAppsController; + this.taskbarInsetsController = taskbarInsetsController; } /** @@ -119,13 +122,14 @@ public class TaskbarControllers { taskbarForceVisibleImmersiveController.init(this); taskbarAllAppsController.init(this, sharedState); navButtonController.init(this); + taskbarInsetsController.init(this); mControllersToLog = new LoggableTaskbarController[] { taskbarDragController, navButtonController, navbarButtonsViewController, taskbarDragLayerController, taskbarScrimViewController, taskbarViewController, taskbarUnfoldAnimationController, taskbarKeyguardController, stashedHandleViewController, taskbarStashController, taskbarEduController, - taskbarAutohideSuspendController, taskbarPopupController + taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController }; mAreAllControllersInitialized = true; diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java index c7330d365c..307f674ee6 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java @@ -15,18 +15,10 @@ */ package com.android.launcher3.taskbar; -import static com.android.launcher3.AbstractFloatingView.TYPE_ALL; -import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_ALL_APPS; -import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_CONTENT; -import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_FRAME; -import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION; - import android.content.res.Resources; import android.graphics.Rect; -import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.R; -import com.android.launcher3.anim.AlphaUpdateListener; import com.android.launcher3.util.TouchController; import com.android.quickstep.AnimatedFloat; import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo; @@ -168,37 +160,7 @@ public class TaskbarDragLayerController implements TaskbarControllers.LoggableTa * @see InsetsInfo#setTouchableInsets(int) */ public void updateInsetsTouchability(InsetsInfo insetsInfo) { - insetsInfo.touchableRegion.setEmpty(); - // Always have nav buttons be touchable - mControllers.navbarButtonsViewController.addVisibleButtonsRegion( - mTaskbarDragLayer, insetsInfo.touchableRegion); - boolean insetsIsTouchableRegion = true; - - if (mTaskbarDragLayer.getAlpha() < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) { - // Let touches pass through us. - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); - } else if (mControllers.navbarButtonsViewController.isImeVisible()) { - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); - } else if (!mControllers.uiController.isTaskbarTouchable()) { - // Let touches pass through us. - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); - } else if (mControllers.taskbarDragController.isSystemDragInProgress()) { - // Let touches pass through us. - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); - } else if (AbstractFloatingView.getOpenView(mActivity, TYPE_TASKBAR_ALL_APPS) != null) { - // Let touches pass through us. - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); - } else if (mControllers.taskbarViewController.areIconsVisible() - || AbstractFloatingView.getOpenView(mActivity, TYPE_ALL) != null - || mActivity.isNavBarKidsModeActive()) { - // Taskbar has some touchable elements, take over the full taskbar area - insetsInfo.setTouchableInsets(mActivity.isTaskbarWindowFullscreen() - ? TOUCHABLE_INSETS_FRAME : TOUCHABLE_INSETS_CONTENT); - insetsIsTouchableRegion = false; - } else { - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); - } - mActivity.excludeFromMagnificationRegion(insetsIsTouchableRegion); + mControllers.taskbarInsetsController.updateInsetsTouchability(insetsInfo); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt new file mode 100644 index 0000000000..a2ff7806f7 --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.taskbar + +import android.graphics.Insets +import android.view.WindowManager +import com.android.launcher3.AbstractFloatingView +import com.android.launcher3.R +import com.android.launcher3.anim.AlphaUpdateListener +import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController +import com.android.quickstep.KtR +import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo +import com.android.systemui.shared.system.WindowManagerWrapper +import com.android.systemui.shared.system.WindowManagerWrapper.* +import java.io.PrintWriter + +/** + * Handles the insets that Taskbar provides to underlying apps and the IME. + */ +class TaskbarInsetsController(val context: TaskbarActivityContext): LoggableTaskbarController { + + /** The bottom insets taskbar provides to the IME when IME is visible. */ + val taskbarHeightForIme: Int = context.resources.getDimensionPixelSize( + KtR.dimen.taskbar_ime_size) + + // Initialized in init. + private lateinit var controllers: TaskbarControllers + private lateinit var windowLayoutParams: WindowManager.LayoutParams + + fun init(controllers: TaskbarControllers) { + this.controllers = controllers + windowLayoutParams = context.windowLayoutParams + + val wmWrapper: WindowManagerWrapper = getInstance() + wmWrapper.setProvidesInsetsTypes( + windowLayoutParams, + intArrayOf( + ITYPE_EXTRA_NAVIGATION_BAR, + ITYPE_BOTTOM_TAPPABLE_ELEMENT + ) + ) + + windowLayoutParams.providedInternalImeInsets = arrayOfNulls(ITYPE_SIZE) + + onTaskbarWindowHeightChanged() + + windowLayoutParams.insetsRoundedCornerFrame = true + } + + fun onTaskbarWindowHeightChanged() { + val reducingSize = Insets.of(0, windowLayoutParams.height - taskbarHeightForIme, 0, 0) + windowLayoutParams.providedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR] = reducingSize + windowLayoutParams.providedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT] = reducingSize + } + + /** + * Called to update the touchable insets. + * @see InsetsInfo.setTouchableInsets + */ + fun updateInsetsTouchability(insetsInfo: InsetsInfo) { + insetsInfo.touchableRegion.setEmpty() + // Always have nav buttons be touchable + controllers.navbarButtonsViewController.addVisibleButtonsRegion( + context.dragLayer, insetsInfo.touchableRegion + ) + var insetsIsTouchableRegion = true + if (context.dragLayer.alpha < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) { + // Let touches pass through us. + insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION) + } else if (controllers.navbarButtonsViewController.isImeVisible) { + insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION) + } else if (!controllers.uiController.isTaskbarTouchable) { + // Let touches pass through us. + insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION) + } else if (controllers.taskbarDragController.isSystemDragInProgress) { + // Let touches pass through us. + insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION) + } else if (AbstractFloatingView.getOpenView( + context, + AbstractFloatingView.TYPE_TASKBAR_ALL_APPS + ) != null + ) { + // Let touches pass through us. + insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION) + } else if (controllers.taskbarViewController.areIconsVisible() + || AbstractFloatingView.getOpenView( + context, + AbstractFloatingView.TYPE_ALL + ) != null + || context.isNavBarKidsModeActive + ) { + // Taskbar has some touchable elements, take over the full taskbar area + insetsInfo.setTouchableInsets( + if (context.isTaskbarWindowFullscreen) { + InsetsInfo.TOUCHABLE_INSETS_FRAME + } else { + InsetsInfo.TOUCHABLE_INSETS_CONTENT + } + ) + insetsIsTouchableRegion = false + } else { + insetsInfo.setTouchableInsets(InsetsInfo.TOUCHABLE_INSETS_REGION) + } + context.excludeFromMagnificationRegion(insetsIsTouchableRegion) + } + + override fun dumpLogs(prefix: String, pw: PrintWriter) { + pw.println(prefix + "TaskbarInsetsController:") + pw.println("$prefix\twindowHeight=${windowLayoutParams.height}") + pw.println("$prefix\tprovidedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR]=" + + "${windowLayoutParams.providedInternalImeInsets[ITYPE_EXTRA_NAVIGATION_BAR]}") + pw.println("$prefix\tprovidedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT]=" + + "${windowLayoutParams.providedInternalImeInsets[ITYPE_BOTTOM_TAPPABLE_ELEMENT]}") + } +} \ No newline at end of file diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index 8291475f5d..7548398be2 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -312,8 +312,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar if (!mTouchEnabled) { return true; } - if (mIconLayoutBounds.contains((int) event.getX(), (int) event.getY())) { - // Don't allow long pressing between icons. + if (mIconLayoutBounds.left <= event.getX() && event.getX() <= mIconLayoutBounds.right) { + // Don't allow long pressing between icons, or above/below them. return true; } if (mControllerCallbacks.onTouchEvent(event)) { diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 7ca76399a6..b073b90baf 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -770,7 +770,7 @@ public abstract class AbsSwipeUpHandler, // We will handle the sysui flags based on the centermost task view. mRecentsAnimationController.setUseLauncherSystemBarFlags(swipeUpThresholdPassed || (quickswitchThresholdPassed && centermostTaskFlags != 0)); - mRecentsAnimationController.setSplitScreenMinimized(swipeUpThresholdPassed); + mRecentsAnimationController.setSplitScreenMinimized(mContext, swipeUpThresholdPassed); // Provide a hint to WM the direction that we will be settling in case the animation // needs to be canceled mRecentsAnimationController.setWillFinishToHome(swipeUpThresholdPassed); diff --git a/quickstep/src/com/android/quickstep/KtR.java b/quickstep/src/com/android/quickstep/KtR.java index a768ef5253..758c6e08ef 100644 --- a/quickstep/src/com/android/quickstep/KtR.java +++ b/quickstep/src/com/android/quickstep/KtR.java @@ -31,6 +31,7 @@ public class KtR { public static final class dimen { public static int task_menu_spacing = R.dimen.task_menu_spacing; public static int task_menu_horizontal_padding = R.dimen.task_menu_horizontal_padding; + public static int taskbar_ime_size = R.dimen.taskbar_ime_size; } public static final class layout { diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java index cc79f4a1d8..921674a2d4 100644 --- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java +++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java @@ -29,7 +29,6 @@ import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.os.Handler; -import android.util.Log; import android.util.MathUtils; import android.util.Pair; import android.view.RemoteAnimationTarget; @@ -55,7 +54,7 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; * the app window and plays the rest of app close transitions in one go. * * This animation is used only for apps that enable back dispatching via - * {@link android.view.OnBackInvokedDispatcher}. The controller registers + * {@link android.window.OnBackInvokedDispatcher}. The controller registers * an {@link IOnBackInvokedCallback} with WM Shell and receives back dispatches when a back * navigation to launcher starts. * @@ -66,7 +65,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; public class LauncherBackAnimationController { private static final int CANCEL_TRANSITION_DURATION = 233; private static final float MIN_WINDOW_SCALE = 0.7f; - private static final String TAG = "LauncherBackAnimationController"; private final QuickstepTransitionManager mQuickstepTransitionManager; private final Matrix mTransformMatrix = new Matrix(); /** The window position at the beginning of the back animation. */ @@ -115,12 +113,7 @@ public class LauncherBackAnimationController { * @param handler Handler to the thread to run the animations on. */ public void registerBackCallbacks(Handler handler) { - SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate(); - if (systemUiProxy == null) { - Log.e(TAG, "SystemUiProxy is null. Skip registering back invocation callbacks"); - return; - } - systemUiProxy.setBackToLauncherCallback( + SystemUiProxy.INSTANCE.get(mLauncher).setBackToLauncherCallback( new IOnBackInvokedCallback.Stub() { @Override public void onBackCancelled() { @@ -170,10 +163,7 @@ public class LauncherBackAnimationController { /** Unregisters the back to launcher callback in shell. */ public void unregisterBackCallbacks() { - SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate(); - if (systemUiProxy != null) { - systemUiProxy.clearBackToLauncherCallback(); - } + SystemUiProxy.INSTANCE.get(mLauncher).clearBackToLauncherCallback(); } private void startBack(BackEvent backEvent) { @@ -298,10 +288,7 @@ public class LauncherBackAnimationController { mInitialTouchPos.set(0, 0); mAnimatorSetInProgress = false; mSpringAnimationInProgress = false; - SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.getNoCreate(); - if (systemUiProxy != null) { - SystemUiProxy.INSTANCE.getNoCreate().onBackToLauncherAnimationFinished(); - } + SystemUiProxy.INSTANCE.get(mLauncher).onBackToLauncherAnimationFinished(); } private void startTransitionAnimations(RectFSpringAnim springAnim, AnimatorSet anim) { diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java index c120b32543..2007ee1ebd 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java @@ -19,6 +19,7 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS; +import android.content.Context; import android.os.RemoteException; import android.util.Log; import android.view.IRecentsAnimationController; @@ -97,24 +98,20 @@ public class RecentsAnimationController { * Indicates that the gesture has crossed the window boundary threshold and we should minimize * if we are in splitscreen. */ - public void setSplitScreenMinimized(boolean splitScreenMinimized) { + public void setSplitScreenMinimized(Context context, boolean splitScreenMinimized) { if (!mAllowMinimizeSplitScreen) { return; } if (mSplitScreenMinimized != splitScreenMinimized) { mSplitScreenMinimized = splitScreenMinimized; - UI_HELPER_EXECUTOR.execute(() -> { - SystemUiProxy p = SystemUiProxy.INSTANCE.getNoCreate(); - if (p != null) { - p.setSplitScreenMinimized(splitScreenMinimized); - } - }); + UI_HELPER_EXECUTOR.execute(() -> SystemUiProxy.INSTANCE.get(context) + .setSplitScreenMinimized(splitScreenMinimized)); } } /** * Remove task remote animation target from - * {@link RecentsAnimationCallbacks#onTaskAppeared(RemoteAnimationTargetCompat)}}. + * {@link RecentsAnimationCallbacks#onTasksAppeared}}. */ @UiThread public void removeTaskTarget(@NonNull RemoteAnimationTargetCompat target) { diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index b8334a9ae8..f094d712a1 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -177,9 +177,8 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn ((RecentsActivity) activityInterface.getCreatedActivity()).startHome(); return; } - RemoteAnimationTarget[] nonAppTargets = - SystemUiProxy.INSTANCE.getNoCreate() - .onGoingToRecentsLegacy(false, nonHomeApps); + RemoteAnimationTarget[] nonAppTargets = SystemUiProxy.INSTANCE.get(mCtx) + .onGoingToRecentsLegacy(false, nonHomeApps); if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode() && activityInterface.getCreatedActivity() != null) { diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java index 955fffcdb4..244a794562 100644 --- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java +++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java @@ -26,6 +26,7 @@ import com.android.quickstep.util.CancellableTask; import com.android.quickstep.util.RecentsOrientedState; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; +import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import java.util.HashMap; import java.util.function.Consumer; @@ -171,8 +172,14 @@ public class GroupedTaskView extends TaskView { RunnableList endCallback = new RunnableList(); RecentsView recentsView = getRecentsView(); // Callbacks run from remote animation when recents animation not currently running + InteractionJankMonitorWrapper.begin(this, + InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "Enter form GroupedTaskView"); recentsView.getSplitPlaceholder().launchTasks(this /*groupedTaskView*/, - success -> endCallback.executeAllAndDestroy(), + success -> { + endCallback.executeAllAndDestroy(); + InteractionJankMonitorWrapper.end( + InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER); + }, false /* freezeTaskList */); // Callbacks get run from recentsView for case when recents animation already running diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index aff9df6f35..5f715f812f 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -175,6 +175,7 @@ import com.android.systemui.plugins.ResourceProvider; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; @@ -2744,9 +2745,16 @@ public abstract class RecentsView { if (success) { mSplitToast.show(); + InteractionJankMonitorWrapper.end( + InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER); + } else { + InteractionJankMonitorWrapper.cancel( + InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER); } }); } @@ -4040,9 +4048,11 @@ public abstract class RecentsView - mSplitSelectStateController.launchSplitTasks( - aBoolean1 -> RecentsView.this.resetFromSplitSelectionState())); + pendingAnimation.addEndListener(aBoolean -> { + mSplitSelectStateController.launchSplitTasks( + aBoolean1 -> RecentsView.this.resetFromSplitSelectionState()); + InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER); + }); if (containerTaskView.containsMultipleTasks()) { // If we are launching from a child task, then only hide the thumbnail itself mSecondSplitHiddenView = thumbnailView; @@ -4050,6 +4060,8 @@ public abstract class RecentsView @@ -153,14 +155,29 @@ launcher:name="Tablet" launcher:minWidthDps="900" launcher:minHeightDps="820" - launcher:minCellHeight="104" - launcher:minCellWidth="80" + launcher:minCellHeight="120" + launcher:minCellWidth="102" + launcher:minCellHeightLandscape="104" + launcher:minCellWidthLandscape="120" launcher:iconImageSize="60" launcher:iconTextSize="14" - launcher:borderSpace="16" + launcher:borderSpaceHorizontal="16" + launcher:borderSpaceVertical="64" + launcher:borderSpaceLandscapeHorizontal="64" + launcher:borderSpaceLandscapeVertical="16" + launcher:horizontalMargin="54" + launcher:horizontalMarginLandscape="120" + launcher:allAppsCellWidth="96" + launcher:allAppsCellHeight="142" + launcher:allAppsCellWidthLandscape="126" + launcher:allAppsCellHeightLandscape="126" launcher:allAppsIconSize="60" launcher:allAppsIconTextSize="14" - launcher:allAppsBorderSpace="16" + launcher:allAppsBorderSpaceHorizontal="8" + launcher:allAppsBorderSpaceVertical="16" + launcher:allAppsBorderSpaceLandscape="16" + launcher:hotseatBorderSpace="58" + launcher:hotseatBorderSpaceLandscape="50.4" launcher:canBeDefault="true" /> diff --git a/res/xml/paddings_6x5.xml b/res/xml/paddings_6x5.xml new file mode 100644 index 0000000000..a958ec7b55 --- /dev/null +++ b/res/xml/paddings_6x5.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index fd9d0e1906..b6a05b02d4 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -3235,12 +3235,12 @@ public class Launcher extends StatefulActivity /** Pauses view updates that should not be run during the app launch animation. */ public void pauseExpensiveViewUpdates() { // Pause page indicator animations as they lead to layer trashing. - mWorkspace.getPageIndicator().pauseAnimations(); + getWorkspace().getPageIndicator().pauseAnimations(); } /** Resumes view updates at the end of the app launch animation. */ public void resumeExpensiveViewUpdates() { - mWorkspace.getPageIndicator().skipAnimationsToEnd(); + getWorkspace().getPageIndicator().skipAnimationsToEnd(); } } diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java index 3dfece7660..a11bd4fdad 100644 --- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java +++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java @@ -23,7 +23,6 @@ import static android.view.View.VISIBLE; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION; import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems; import static com.android.launcher3.model.ModelUtils.getMissingHotseatRanks; -import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially; import android.annotation.TargetApi; import android.app.Fragment; @@ -420,8 +419,6 @@ public class LauncherPreviewRenderer extends ContextWrapper currentWorkspaceItems, otherWorkspaceItems); filterCurrentWorkspaceItems(currentScreenIds, dataModel.appWidgets, currentAppWidgets, otherAppWidgets); - - sortWorkspaceItemsSpatially(mIdp, currentWorkspaceItems); for (ItemInfo itemInfo : currentWorkspaceItems) { switch (itemInfo.itemType) { case Favorites.ITEM_TYPE_APPLICATION: diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java index 5b278ab4cf..6c4cfb9068 100644 --- a/src/com/android/launcher3/model/BaseLoaderResults.java +++ b/src/com/android/launcher3/model/BaseLoaderResults.java @@ -18,7 +18,6 @@ package com.android.launcher3.model; import static com.android.launcher3.model.ItemInstallQueue.FLAG_LOADER_RUNNING; import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems; -import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.os.Process; @@ -27,6 +26,8 @@ import android.util.Log; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel.CallbackTask; +import com.android.launcher3.LauncherSettings; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.BgDataModel.FixedContainerItems; import com.android.launcher3.model.data.AppInfo; @@ -110,6 +111,42 @@ public abstract class BaseLoaderResults { public abstract void bindWidgets(); + /** + * Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to right) + */ + protected void sortWorkspaceItemsSpatially(InvariantDeviceProfile profile, + ArrayList workspaceItems) { + final int screenCols = profile.numColumns; + final int screenCellCount = profile.numColumns * profile.numRows; + Collections.sort(workspaceItems, (lhs, rhs) -> { + if (lhs.container == rhs.container) { + // Within containers, order by their spatial position in that container + switch (lhs.container) { + case LauncherSettings.Favorites.CONTAINER_DESKTOP: { + int lr = (lhs.screenId * screenCellCount + lhs.cellY * screenCols + + lhs.cellX); + int rr = (rhs.screenId * screenCellCount + +rhs.cellY * screenCols + + rhs.cellX); + return Integer.compare(lr, rr); + } + case LauncherSettings.Favorites.CONTAINER_HOTSEAT: { + // We currently use the screen id as the rank + return Integer.compare(lhs.screenId, rhs.screenId); + } + default: + if (FeatureFlags.IS_STUDIO_BUILD) { + throw new RuntimeException( + "Unexpected container type when sorting workspace items."); + } + return 0; + } + } else { + // Between containers, order by hotseat, desktop + return Integer.compare(lhs.container, rhs.container); + } + }); + } + protected void executeCallbacksTask(CallbackTask task, Executor executor) { executor.execute(() -> { if (mMyBindingId != mBgDataModel.lastBindId) { @@ -131,7 +168,7 @@ public abstract class BaseLoaderResults { return idleLock; } - private static class WorkspaceBinder { + private class WorkspaceBinder { private final Executor mUiExecutor; private final Callbacks mCallbacks; diff --git a/src/com/android/launcher3/model/ModelUtils.java b/src/com/android/launcher3/model/ModelUtils.java index ef5eef1e43..df6768d582 100644 --- a/src/com/android/launcher3/model/ModelUtils.java +++ b/src/com/android/launcher3/model/ModelUtils.java @@ -23,10 +23,8 @@ import android.graphics.Bitmap; import android.os.Process; import android.util.Log; -import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherSettings; import com.android.launcher3.Utilities; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.model.data.ItemInfo; @@ -91,42 +89,6 @@ public class ModelUtils { } } - /** - * Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to right) - */ - public static void sortWorkspaceItemsSpatially(InvariantDeviceProfile profile, - ArrayList workspaceItems) { - final int screenCols = profile.numColumns; - final int screenCellCount = profile.numColumns * profile.numRows; - Collections.sort(workspaceItems, (lhs, rhs) -> { - if (lhs.container == rhs.container) { - // Within containers, order by their spatial position in that container - switch (lhs.container) { - case LauncherSettings.Favorites.CONTAINER_DESKTOP: { - int lr = (lhs.screenId * screenCellCount + lhs.cellY * screenCols - + lhs.cellX); - int rr = (rhs.screenId * screenCellCount + +rhs.cellY * screenCols - + rhs.cellX); - return Integer.compare(lr, rr); - } - case LauncherSettings.Favorites.CONTAINER_HOTSEAT: { - // We currently use the screen id as the rank - return Integer.compare(lhs.screenId, rhs.screenId); - } - default: - if (FeatureFlags.IS_STUDIO_BUILD) { - throw new RuntimeException( - "Unexpected container type when sorting workspace items."); - } - return 0; - } - } else { - // Between containers, order by hotseat, desktop - return Integer.compare(lhs.container, rhs.container); - } - }); - } - /** * Iterates though current workspace items and returns available hotseat ranks for prediction. */ diff --git a/src/com/android/launcher3/util/GridOccupancy.java b/src/com/android/launcher3/util/GridOccupancy.java index 9c752a7043..13014608c4 100644 --- a/src/com/android/launcher3/util/GridOccupancy.java +++ b/src/com/android/launcher3/util/GridOccupancy.java @@ -7,7 +7,7 @@ import com.android.launcher3.model.data.ItemInfo; /** * Utility object to manage the occupancy in a grid. */ -public class GridOccupancy { +public class GridOccupancy extends AbsGridOccupancy { private final int mCountX; private final int mCountY; @@ -30,24 +30,7 @@ public class GridOccupancy { * @return true if a vacant cell was found */ public boolean findVacantCell(int[] vacantOut, int spanX, int spanY) { - for (int y = 0; (y + spanY) <= mCountY; y++) { - for (int x = 0; (x + spanX) <= mCountX; x++) { - boolean available = !cells[x][y]; - out: - for (int i = x; i < x + spanX; i++) { - for (int j = y; j < y + spanY; j++) { - available = available && !cells[i][j]; - if (!available) break out; - } - } - if (available) { - vacantOut[0] = x; - vacantOut[1] = y; - return true; - } - } - } - return false; + return super.findVacantCell(vacantOut, cells, mCountX, mCountY, spanX, spanY); } public void copyTo(GridOccupancy dest) { diff --git a/src_shortcuts_overrides/com/android/launcher3/util/AbsGridOccupancy.java b/src_shortcuts_overrides/com/android/launcher3/util/AbsGridOccupancy.java new file mode 100644 index 0000000000..968b281787 --- /dev/null +++ b/src_shortcuts_overrides/com/android/launcher3/util/AbsGridOccupancy.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.util; + +/** + * Defines method to find the next vacant cell on a grid. + * This uses the default top-down, left-right approach and can be over-written through + * code swaps in different launchers. + */ +public abstract class AbsGridOccupancy { + /** + * Find the first vacant cell, if there is one. + * + * @param vacantOut Holds the x and y coordinate of the vacant cell + * @param spanX Horizontal cell span. + * @param spanY Vertical cell span. + * + * @return true if a vacant cell was found + */ + protected boolean findVacantCell(int[] vacantOut, boolean[][] cells, int countX, int countY, + int spanX, int spanY) { + for (int y = 0; (y + spanY) <= countY; y++) { + for (int x = 0; (x + spanX) <= countX; x++) { + boolean available = !cells[x][y]; + out: + for (int i = x; i < x + spanX; i++) { + for (int j = y; j < y + spanY; j++) { + available = available && !cells[i][j]; + if (!available) break out; + } + } + if (available) { + vacantOut[0] = x; + vacantOut[1] = y; + return true; + } + } + } + return false; + } +}