Merge "Import translations. DO NOT MERGE ANYWHERE"
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 002a86c..094bced 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -36,6 +36,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
+import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
@@ -55,9 +56,11 @@
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnClickListener;
import android.view.View.OnHoverListener;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -68,10 +71,13 @@
import com.android.launcher3.anim.AlphaUpdateListener;
import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton;
import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.TouchController;
+import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.AnimatedFloat;
import com.android.systemui.shared.rotation.FloatingRotationButton;
import com.android.systemui.shared.rotation.RotationButton;
import com.android.systemui.shared.rotation.RotationButtonController;
+import com.android.systemui.shared.system.ViewTreeObserverWrapper;
import java.util.ArrayList;
import java.util.function.IntPredicate;
@@ -98,6 +104,8 @@
private static final int MASK_IME_SWITCHER_VISIBLE = FLAG_SWITCHER_SUPPORTED | FLAG_IME_VISIBLE;
+ private static final String NAV_BUTTONS_SEPARATE_WINDOW_TITLE = "Taskbar Nav Buttons";
+
private final ArrayList<StatePropertyHolder> mPropertyHolders = new ArrayList<>();
private final ArrayList<ImageView> mAllButtons = new ArrayList<>();
private int mState;
@@ -134,6 +142,12 @@
private View mHomeButton;
private FloatingRotationButton mFloatingRotationButton;
+ // Variables for moving nav buttons to a separate window above IME
+ private boolean mAreNavButtonsInSeparateWindow = false;
+ private BaseDragLayer<TaskbarActivityContext> mSeparateWindowParent; // Initialized in init.
+ private final ViewTreeObserverWrapper.OnComputeInsetsListener mSeparateWindowInsetsComputer =
+ this::onComputeInsetsForSeparateWindow;
+
public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
mContext = context;
mNavButtonsView = navButtonsView;
@@ -321,6 +335,21 @@
R.id.notifications_button);
}
+ // Initialize things needed to move nav buttons to separate window.
+ mSeparateWindowParent = new BaseDragLayer<TaskbarActivityContext>(mContext, null, 0) {
+ @Override
+ public void recreateControllers() {
+ mControllers = new TouchController[0];
+ }
+
+ @Override
+ protected boolean canFindActiveController() {
+ // We don't have any controllers, but we don't want any floating views such as
+ // folder to intercept, either. This ensures nav buttons can always be pressed.
+ return false;
+ }
+ };
+ mSeparateWindowParent.recreateControllers();
}
private void initButtons(ViewGroup navContainer, ViewGroup endContainer,
@@ -456,7 +485,7 @@
/**
* Adds the bounds corresponding to all visible buttons to provided region
*/
- public void addVisibleButtonsRegion(TaskbarDragLayer parent, Region outRegion) {
+ public void addVisibleButtonsRegion(BaseDragLayer<?> parent, Region outRegion) {
int count = mAllButtons.size();
for (int i = 0; i < count; i++) {
View button = mAllButtons.get(i);
@@ -561,6 +590,59 @@
if (mFloatingRotationButton != null) {
mFloatingRotationButton.hide();
}
+
+ moveNavButtonsBackToTaskbarWindow();
+ }
+
+ /**
+ * Moves mNavButtonsView from TaskbarDragLayer to a placeholder BaseDragLayer on a new window.
+ */
+ public void moveNavButtonsToNewWindow() {
+ if (mAreNavButtonsInSeparateWindow) {
+ return;
+ }
+
+ mSeparateWindowParent.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View view) {
+ ViewTreeObserverWrapper.addOnComputeInsetsListener(
+ mSeparateWindowParent.getViewTreeObserver(), mSeparateWindowInsetsComputer);
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View view) {
+ mSeparateWindowParent.removeOnAttachStateChangeListener(this);
+ ViewTreeObserverWrapper.removeOnComputeInsetsListener(
+ mSeparateWindowInsetsComputer);
+ }
+ });
+
+ mAreNavButtonsInSeparateWindow = true;
+ mContext.getDragLayer().removeView(mNavButtonsView);
+ mSeparateWindowParent.addView(mNavButtonsView);
+ WindowManager.LayoutParams windowLayoutParams = mContext.createDefaultWindowLayoutParams();
+ windowLayoutParams.setTitle(NAV_BUTTONS_SEPARATE_WINDOW_TITLE);
+ mContext.addWindowView(mSeparateWindowParent, windowLayoutParams);
+
+ }
+
+ /**
+ * Moves mNavButtonsView from its temporary window and reattaches it to TaskbarDragLayer.
+ */
+ public void moveNavButtonsBackToTaskbarWindow() {
+ if (!mAreNavButtonsInSeparateWindow) {
+ return;
+ }
+
+ mAreNavButtonsInSeparateWindow = false;
+ mContext.removeWindowView(mSeparateWindowParent);
+ mSeparateWindowParent.removeView(mNavButtonsView);
+ mContext.getDragLayer().addView(mNavButtonsView);
+ }
+
+ private void onComputeInsetsForSeparateWindow(ViewTreeObserverWrapper.InsetsInfo insetsInfo) {
+ addVisibleButtonsRegion(mSeparateWindowParent, insetsInfo.touchableRegion);
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
}
private class RotationButtonListener implements RotationButton.RotationButtonUpdatesCallback {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 1198dc5..a60d434 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -16,6 +16,7 @@
package com.android.launcher3.taskbar;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
@@ -189,21 +190,7 @@
public void init(TaskbarSharedState sharedState) {
mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight();
- mWindowLayoutParams = new WindowManager.LayoutParams(
- MATCH_PARENT,
- mLastRequestedNonFullscreenHeight,
- TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_SLIPPERY,
- PixelFormat.TRANSLUCENT);
- mWindowLayoutParams.setTitle(WINDOW_TITLE);
- mWindowLayoutParams.packageName = getPackageName();
- mWindowLayoutParams.gravity = Gravity.BOTTOM;
- mWindowLayoutParams.setFitInsetsTypes(0);
- mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
- mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- mWindowLayoutParams.privateFlags =
- WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+ mWindowLayoutParams = createDefaultWindowLayoutParams();
WindowManagerWrapper wmWrapper = WindowManagerWrapper.getInstance();
wmWrapper.setProvidesInsetsTypes(
@@ -224,6 +211,27 @@
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
}
+ /** Creates LayoutParams for adding a view directly to WindowManager as a new window */
+ public WindowManager.LayoutParams createDefaultWindowLayoutParams() {
+ WindowManager.LayoutParams windowLayoutParams = new WindowManager.LayoutParams(
+ MATCH_PARENT,
+ mLastRequestedNonFullscreenHeight,
+ TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_SLIPPERY,
+ PixelFormat.TRANSLUCENT);
+ windowLayoutParams.setTitle(WINDOW_TITLE);
+ windowLayoutParams.packageName = getPackageName();
+ windowLayoutParams.gravity = Gravity.BOTTOM;
+ windowLayoutParams.setFitInsetsTypes(0);
+ windowLayoutParams.receiveInsetsIgnoringZOrder = true;
+ windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+ windowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ windowLayoutParams.privateFlags =
+ WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+ return windowLayoutParams;
+ }
+
public void onConfigurationChanged(@Config int configChanges) {
mControllers.onConfigurationChanged(configChanges);
}
@@ -271,14 +279,6 @@
}
@Override
- public boolean supportsIme() {
- // Currently we don't support IME because we have FLAG_NOT_FOCUSABLE. We can remove that
- // flag when opening a floating view that needs IME (such as Folder), but then that means
- // Taskbar will be below IME and thus users can't click the back button.
- return false;
- }
-
- @Override
public View.OnClickListener getItemOnClickListener() {
return this::onTaskbarIconClicked;
}
@@ -505,6 +505,42 @@
return mTaskbarHeightForIme;
}
+ /**
+ * Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
+ * window.
+ */
+ public void setTaskbarWindowFocusable(boolean focusable) {
+ if (focusable) {
+ mWindowLayoutParams.flags &= ~FLAG_NOT_FOCUSABLE;
+ } else {
+ mWindowLayoutParams.flags |= FLAG_NOT_FOCUSABLE;
+ }
+ mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
+ }
+
+ /**
+ * Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
+ * window. If we're now focusable, also move nav buttons to a separate window above IME.
+ */
+ public void setTaskbarWindowFocusableForIme(boolean focusable) {
+ if (focusable) {
+ mControllers.navbarButtonsViewController.moveNavButtonsToNewWindow();
+ } else {
+ mControllers.navbarButtonsViewController.moveNavButtonsBackToTaskbarWindow();
+ }
+ setTaskbarWindowFocusable(focusable);
+ }
+
+ /** Adds the given view to WindowManager with the provided LayoutParams (creates new window). */
+ public void addWindowView(View view, WindowManager.LayoutParams windowLayoutParams) {
+ mWindowManager.addView(view, windowLayoutParams);
+ }
+
+ /** Removes the given view from WindowManager. See {@link #addWindowView}. */
+ public void removeWindowView(View view) {
+ mWindowManager.removeViewImmediate(view);
+ }
+
protected void onTaskbarIconClicked(View view) {
Object tag = view.getTag();
if (tag instanceof Task) {
@@ -514,6 +550,17 @@
} else if (tag instanceof FolderInfo) {
FolderIcon folderIcon = (FolderIcon) view;
Folder folder = folderIcon.getFolder();
+
+ folder.setOnFolderStateChangedListener(newState -> {
+ if (newState == Folder.STATE_OPEN) {
+ setTaskbarWindowFocusableForIme(true);
+ } else if (newState == Folder.STATE_CLOSED) {
+ // Defer by a frame to ensure we're no longer fullscreen and thus won't jump.
+ getDragLayer().post(() -> setTaskbarWindowFocusableForIme(false));
+ folder.setOnFolderStateChangedListener(null);
+ }
+ });
+
setTaskbarWindowFullscreen(true);
getDragLayer().post(() -> {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index b42a60c..df004ef 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -15,17 +15,22 @@
*/
package com.android.launcher3.taskbar;
+import static android.view.KeyEvent.ACTION_UP;
+import static android.view.KeyEvent.KEYCODE_BACK;
+
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.R;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
@@ -187,4 +192,17 @@
TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev);
return super.dispatchTouchEvent(ev);
}
+
+ /** Called while Taskbar window is focusable, e.g. when pressing back while a folder is open */
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
+ AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
+ if (topView != null && topView.onBackPressed()) {
+ // Handled by the floating view.
+ return true;
+ }
+ }
+ return super.dispatchKeyEvent(event);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 7a50d0b..a654a56 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -27,6 +27,7 @@
import androidx.annotation.NonNull;
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.statemanager.StateManager;
@@ -256,6 +257,10 @@
if (hasAnyFlag(changedFlags, FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING)) {
boolean goingToLauncher = hasAnyFlag(FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING);
+ if (goingToLauncher) {
+ // Handle closing open popups when going home/overview
+ AbstractFloatingView.closeAllOpenViews(mControllers.taskbarActivityContext);
+ }
animatorSet.play(mTaskbarBackgroundAlpha.animateToValue(goingToLauncher ? 0 : 1)
.setDuration(duration));
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 2dee506..7af9c9d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -154,6 +154,15 @@
.filter(Objects::nonNull)
.collect(Collectors.toList()));
container.requestFocus();
+
+ // Make focusable to receive back events
+ mControllers.taskbarActivityContext.setTaskbarWindowFocusable(true);
+ container.setOnCloseCallback(() -> {
+ mControllers.taskbarActivityContext.getDragLayer().post(
+ () -> mControllers.taskbarActivityContext.setTaskbarWindowFocusable(false));
+ container.setOnCloseCallback(null);
+ });
+
return container;
}
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 9f1e47f..bc06944 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1410,7 +1410,7 @@
.setContext(mContext)
.setTaskId(runningTaskTarget.taskId)
.setComponentName(taskInfo.topActivity)
- .setLeash(runningTaskTarget.leash.getSurfaceControl())
+ .setLeash(runningTaskTarget.leash)
.setSourceRectHint(
runningTaskTarget.taskInfo.pictureInPictureParams.getSourceRectHint())
.setAppBounds(taskInfo.configuration.windowConfiguration.getBounds())
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 306e864..af53bca 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -419,7 +419,7 @@
RemoteAnimationTargets targets = new RemoteAnimationTargets(
appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
for (RemoteAnimationTargetCompat app : targets.apps) {
- new Transaction().setAlpha(app.leash.getSurfaceControl(), 1).apply();
+ new Transaction().setAlpha(app.leash, 1).apply();
}
AnimatorSet anim = new AnimatorSet();
anim.play(controller.getAnimationPlayer());
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 5d9a537..0a09e34 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -469,7 +469,7 @@
for (RemoteAnimationTargetCompat appTarget : appTargets) {
final int taskId = appTarget.taskInfo != null ? appTarget.taskInfo.taskId : -1;
final int mode = appTarget.mode;
- final SurfaceControl leash = appTarget.leash.getSurfaceControl();
+ final SurfaceControl leash = appTarget.leash;
if (leash == null) {
continue;
}
@@ -484,7 +484,7 @@
}
for (int i = 0; i < nonAppTargets.length; ++i) {
- final SurfaceControl leash = appTargets[i].leash.getSurfaceControl();
+ final SurfaceControl leash = appTargets[i].leash;
if (nonAppTargets[i].windowType == TYPE_DOCK_DIVIDER && leash != null) {
openingTargets.add(leash);
}
@@ -611,7 +611,7 @@
boolean hasSurfaceToAnimate = false;
for (int i = 0; i < nonApps.length; ++i) {
final RemoteAnimationTargetCompat targ = nonApps[i];
- final SurfaceControl leash = targ.leash.getSurfaceControl();
+ final SurfaceControl leash = targ.leash;
if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null) {
auxiliarySurfaces.add(leash);
hasSurfaceToAnimate = true;
diff --git a/quickstep/src/com/android/quickstep/util/TransformParams.java b/quickstep/src/com/android/quickstep/util/TransformParams.java
index 03d7a37..75d6001 100644
--- a/quickstep/src/com/android/quickstep/util/TransformParams.java
+++ b/quickstep/src/com/android/quickstep/util/TransformParams.java
@@ -174,10 +174,10 @@
RemoteAnimationTargetCompat app = targets.unfilteredApps[i];
if (app.mode == targets.targetMode) {
if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_RECENTS) {
- return app.leash.getSurfaceControl();
+ return app.leash;
}
} else {
- return app.leash.getSurfaceControl();
+ return app.leash;
}
}
return null;
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 6db0af3..0b04b86 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -187,6 +187,10 @@
<attr name="minCellHeight" format="float" />
<attr name="minCellWidth" format="float" />
<!-- defaults to minCellHeight, if not specified -->
+ <attr name="minCellHeightLandscape" format="float" />
+ <!-- defaults to minCellWidth, if not specified -->
+ <attr name="minCellWidthLandscape" format="float" />
+ <!-- defaults to minCellHeight, if not specified -->
<attr name="minCellHeightTwoPanelPortrait" format="float" />
<!-- defaults to minCellWidth, if not specified -->
<attr name="minCellWidthTwoPanelPortrait" format="float" />
@@ -244,6 +248,8 @@
<!-- defaults to borderSpaceDps, if not specified -->
<attr name="hotseatBorderSpace" format="float" />
<!-- defaults to hotseatBorderSpace, if not specified -->
+ <attr name="hotseatBorderSpaceLandscape" format="float" />
+ <!-- defaults to hotseatBorderSpace, if not specified -->
<attr name="hotseatBorderSpaceTwoPanelLandscape" format="float" />
<!-- defaults to hotseatBorderSpace, if not specified -->
<attr name="hotseatBorderSpaceTwoPanelPortrait" format="float" />
@@ -270,6 +276,8 @@
<!-- Margin on left and right of the workspace when GridDisplayOption#isScalable is true -->
<attr name="horizontalMargin" format="float"/>
<!-- defaults to horizontalMargin if not specified -->
+ <attr name="horizontalMarginLandscape" format="float"/>
+ <!-- defaults to horizontalMargin if not specified -->
<attr name="horizontalMarginTwoPanelLandscape" format="float"/>
<!-- defaults to horizontalMargin if not specified -->
<attr name="horizontalMarginTwoPanelPortrait" format="float"/>
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index adb1613..11f58e7 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -238,9 +238,19 @@
mActivity = ActivityContext.lookupContext(context);
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
- mBorderSpace = mContainerType == FOLDER
- ? new Point(deviceProfile.folderCellLayoutBorderSpacePx)
- : new Point(deviceProfile.cellLayoutBorderSpacePx);
+ switch (mContainerType) {
+ case FOLDER:
+ mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx);
+ break;
+ case HOTSEAT:
+ mBorderSpace = new Point(deviceProfile.hotseatBorderSpace,
+ deviceProfile.hotseatBorderSpace);
+ break;
+ case WORKSPACE:
+ default:
+ mBorderSpace = new Point(deviceProfile.cellLayoutBorderSpacePx);
+ break;
+ }
mCellWidth = mCellHeight = -1;
mFixedCellWidth = mFixedCellHeight = -1;
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index ab8e5e7..8a5b888 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -161,7 +161,7 @@
public final int hotseatBarSidePaddingStartPx;
public final int hotseatBarSidePaddingEndPx;
public final int hotseatQsbHeight;
- public final int hotseatBorderSpace;
+ public int hotseatBorderSpace;
public final float qsbBottomMarginOriginalPx;
public int qsbBottomMarginPx;
@@ -716,6 +716,7 @@
}
// Hotseat
+ hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics, scale);
updateHotseatIconSize(iconSizePx);
if (!isVerticalLayout) {
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 94325d0..0b168a5 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -794,6 +794,11 @@
x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidth, 0);
y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeight, 0);
minCellSize[INDEX_DEFAULT] = new PointF(x, y);
+
+ x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthLandscape,
+ minCellSize[INDEX_DEFAULT].x);
+ y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightLandscape,
+ minCellSize[INDEX_DEFAULT].y);
minCellSize[INDEX_LANDSCAPE] = new PointF(x, y);
x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthTwoPanelPortrait,
@@ -896,7 +901,9 @@
horizontalMargin[INDEX_DEFAULT] = a.getFloat(
R.styleable.ProfileDisplayOption_horizontalMargin, 0);
- horizontalMargin[INDEX_LANDSCAPE] = horizontalMargin[INDEX_DEFAULT];
+ horizontalMargin[INDEX_LANDSCAPE] = a.getFloat(
+ R.styleable.ProfileDisplayOption_horizontalMarginLandscape,
+ horizontalMargin[INDEX_DEFAULT]);
horizontalMargin[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
R.styleable.ProfileDisplayOption_horizontalMarginTwoPanelLandscape,
horizontalMargin[INDEX_DEFAULT]);
@@ -906,7 +913,9 @@
hotseatBorderSpaces[INDEX_DEFAULT] = a.getFloat(
R.styleable.ProfileDisplayOption_hotseatBorderSpace, borderSpace);
- hotseatBorderSpaces[INDEX_LANDSCAPE] = hotseatBorderSpaces[INDEX_DEFAULT];
+ hotseatBorderSpaces[INDEX_LANDSCAPE] = a.getFloat(
+ R.styleable.ProfileDisplayOption_hotseatBorderSpaceLandscape,
+ hotseatBorderSpaces[INDEX_DEFAULT]);
hotseatBorderSpaces[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelLandscape,
hotseatBorderSpaces[INDEX_DEFAULT]);
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index b062b91..225460d 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -229,7 +229,7 @@
offsetPoints(coord, v.getLeft(), v.getTop());
scale *= v.getScaleX();
- v = (View) v.getParent();
+ v = v.getParent() instanceof View ? (View) v.getParent() : null;
}
return scale;
}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index daef682..1e6342c 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -57,6 +57,7 @@
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
+import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
@@ -101,6 +102,8 @@
import com.android.launcher3.views.ClipPathView;
import com.android.launcher3.widget.PendingAddShortcutInfo;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -130,10 +133,13 @@
*/
private static final int MIN_CONTENT_DIMEN = 5;
- static final int STATE_NONE = -1;
- static final int STATE_SMALL = 0;
- static final int STATE_ANIMATING = 1;
- static final int STATE_OPEN = 2;
+ public static final int STATE_CLOSED = 0;
+ public static final int STATE_ANIMATING = 1;
+ public static final int STATE_OPEN = 2;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({STATE_CLOSED, STATE_ANIMATING, STATE_OPEN})
+ public @interface FolderState {}
/**
* Time for which the scroll hint is shown before automatically changing page.
@@ -198,13 +204,12 @@
@ViewDebug.ExportedProperty(category = "launcher",
mapping = {
- @ViewDebug.IntToString(from = STATE_NONE, to = "STATE_NONE"),
- @ViewDebug.IntToString(from = STATE_SMALL, to = "STATE_SMALL"),
+ @ViewDebug.IntToString(from = STATE_CLOSED, to = "STATE_CLOSED"),
@ViewDebug.IntToString(from = STATE_ANIMATING, to = "STATE_ANIMATING"),
@ViewDebug.IntToString(from = STATE_OPEN, to = "STATE_OPEN"),
})
- @Thunk
- int mState = STATE_NONE;
+ private int mState = STATE_CLOSED;
+ private OnFolderStateChangedListener mOnFolderStateChangedListener;
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mRearrangeOnClose = false;
boolean mItemsInvalidated = false;
@@ -277,19 +282,15 @@
mPageIndicator = findViewById(R.id.folder_page_indicator);
mFolderName = findViewById(R.id.folder_name);
mFolderName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.folderLabelTextSizePx);
- if (mActivityContext.supportsIme()) {
- mFolderName.setOnBackKeyListener(this);
- mFolderName.setOnFocusChangeListener(this);
- mFolderName.setOnEditorActionListener(this);
- mFolderName.setSelectAllOnFocus(true);
- mFolderName.setInputType(mFolderName.getInputType()
- & ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
- | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
- | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
- mFolderName.forceDisableSuggestions(true);
- } else {
- mFolderName.setEnabled(false);
- }
+ mFolderName.setOnBackKeyListener(this);
+ mFolderName.setOnFocusChangeListener(this);
+ mFolderName.setOnEditorActionListener(this);
+ mFolderName.setSelectAllOnFocus(true);
+ mFolderName.setInputType(mFolderName.getInputType()
+ & ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
+ | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
+ | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
+ mFolderName.forceDisableSuggestions(true);
mFooter = findViewById(R.id.folder_footer);
mFooterHeight = getResources().getDimensionPixelSize(R.dimen.folder_label_height);
@@ -561,7 +562,7 @@
a.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- mState = STATE_ANIMATING;
+ setState(STATE_ANIMATING);
mCurrentAnimator = a;
}
@@ -686,7 +687,7 @@
@Override
public void onAnimationEnd(Animator animation) {
- mState = STATE_OPEN;
+ setState(STATE_OPEN);
announceAccessibilityChanges();
AccessibilityManagerCompat.sendFolderOpenedEventToTest(getContext());
@@ -862,7 +863,7 @@
}
mSuppressFolderDeletion = false;
clearDragInfo();
- mState = STATE_SMALL;
+ setState(STATE_CLOSED);
mContent.setCurrentPage(0);
}
@@ -1655,4 +1656,21 @@
return windowBottomPx - folderBottomPx;
}
+
+ private void setState(@FolderState int newState) {
+ mState = newState;
+ if (mOnFolderStateChangedListener != null) {
+ mOnFolderStateChangedListener.onFolderStateChanged(mState);
+ }
+ }
+
+ public void setOnFolderStateChangedListener(@Nullable OnFolderStateChangedListener listener) {
+ mOnFolderStateChangedListener = listener;
+ }
+
+ /** Listener that can be registered via {@link Folder#setOnFolderStateChangedListener} */
+ public interface OnFolderStateChangedListener {
+ /** See {@link Folder.FolderState} */
+ void onFolderStateChanged(@FolderState int newState);
+ }
}
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index b1a4109..f06e5ce 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -48,7 +48,7 @@
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
-import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.InsettableFrameLayout;
@@ -120,7 +120,7 @@
private final GradientDrawable mRoundedTop;
private final GradientDrawable mRoundedBottom;
- private Runnable mOnCloseCallback = () -> { };
+ @Nullable private Runnable mOnCloseCallback = null;
// The rect string of the view that the arrow is attached to, in screen reference frame.
protected int mArrowColor;
@@ -766,7 +766,6 @@
}
}
-
protected void animateClose() {
if (!mIsOpen) {
return;
@@ -816,7 +815,9 @@
mDeferContainerRemoval = false;
getPopupContainer().removeView(this);
getPopupContainer().removeView(mArrow);
- mOnCloseCallback.run();
+ if (mOnCloseCallback != null) {
+ mOnCloseCallback.run();
+ }
if (mColorExtractors != null) {
mColorExtractors.forEach(e -> e.setListener(null));
}
@@ -825,7 +826,7 @@
/**
* Callback to be called when the popup is closed
*/
- public void setOnCloseCallback(@NonNull Runnable callback) {
+ public void setOnCloseCallback(@Nullable Runnable callback) {
mOnCloseCallback = callback;
}
diff --git a/src/com/android/launcher3/util/UiThreadHelper.java b/src/com/android/launcher3/util/UiThreadHelper.java
index ac5368c..a1f31fe 100644
--- a/src/com/android/launcher3/util/UiThreadHelper.java
+++ b/src/com/android/launcher3/util/UiThreadHelper.java
@@ -28,7 +28,6 @@
import android.view.View;
import android.view.inputmethod.InputMethodManager;
-import com.android.launcher3.BaseActivity;
import com.android.launcher3.views.ActivityContext;
/**
@@ -56,7 +55,7 @@
STATS_LOGGER_KEY,
Message.obtain(
HANDLER.get(root.getContext()),
- () -> BaseActivity.fromContext(root.getContext())
+ () -> ActivityContext.lookupContext(root.getContext())
.getStatsLogManager()
.logger()
.log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED)
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index e09eff6..c0f6316 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -125,13 +125,6 @@
}
/**
- * Returns whether we can show the IME for elements hosted by this ActivityContext.
- */
- default boolean supportsIme() {
- return true;
- }
-
- /**
* Called just before logging the given item.
*/
default void applyOverwritesToLogItem(LauncherAtom.ItemInfo.Builder itemInfoBuilder) { }