Merging from ub-launcher3-master @ build 6369897 am: 884f8f217f
Change-Id: I3fee2a4fdb36e90743402d107aaf898c6e190dcb
This commit is contained in:
+1
@@ -209,6 +209,7 @@ public class HotseatEduDialog extends AbstractSlideInView implements Insettable
|
||||
WorkspaceItemInfo info = predictions.get(i);
|
||||
PredictedAppIcon icon = PredictedAppIcon.createIcon(mSampleHotseat, info);
|
||||
icon.setEnabled(false);
|
||||
icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
icon.verifyHighRes();
|
||||
CellLayout.LayoutParams lp = new CellLayout.LayoutParams(i, 0, 1, 1);
|
||||
mSampleHotseat.addViewToCellLayout(icon, i, info.getViewId(), lp, true);
|
||||
|
||||
+4
-1
@@ -349,7 +349,10 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
mHotSeatItemsCount);
|
||||
}
|
||||
|
||||
private void pinPrediction(ItemInfo info) {
|
||||
/**
|
||||
* Pins a predicted app icon into place.
|
||||
*/
|
||||
public void pinPrediction(ItemInfo info) {
|
||||
PredictedAppIcon icon = (PredictedAppIcon) mHotseat.getChildAt(
|
||||
mHotseat.getCellXFromOrder(info.rank),
|
||||
mHotseat.getCellYFromOrder(info.rank));
|
||||
|
||||
+36
-2
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.launcher3.uioverrides;
|
||||
|
||||
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.PIN_PREDICTION;
|
||||
import static com.android.launcher3.graphics.IconShape.getShape;
|
||||
|
||||
import android.content.Context;
|
||||
@@ -26,15 +27,19 @@ import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.graphics.IconPalette;
|
||||
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
|
||||
import com.android.launcher3.icons.IconNormalizer;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
@@ -43,7 +48,8 @@ import com.android.launcher3.views.DoubleShadowBubbleTextView;
|
||||
/**
|
||||
* A BubbleTextView with a ring around it's drawable
|
||||
*/
|
||||
public class PredictedAppIcon extends DoubleShadowBubbleTextView {
|
||||
public class PredictedAppIcon extends DoubleShadowBubbleTextView implements
|
||||
LauncherAccessibilityDelegate.AccessibilityActionHandler {
|
||||
|
||||
private static final float RING_EFFECT_RATIO = 0.11f;
|
||||
|
||||
@@ -97,6 +103,13 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView {
|
||||
super.applyFromWorkspaceItem(info);
|
||||
int color = IconPalette.getMutedColor(info.bitmap.color, 0.54f);
|
||||
mIconRingPaint.setColor(ColorUtils.setAlphaComponent(color, 200));
|
||||
if (mIsPinned) {
|
||||
setContentDescription(info.contentDescription);
|
||||
} else {
|
||||
setContentDescription(
|
||||
getContext().getString(R.string.hotseat_prediction_content_description,
|
||||
info.contentDescription));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,9 +117,9 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView {
|
||||
*/
|
||||
public void pin(WorkspaceItemInfo info) {
|
||||
if (mIsPinned) return;
|
||||
mIsPinned = true;
|
||||
applyFromWorkspaceItem(info);
|
||||
setOnLongClickListener(ItemLongClickListener.INSTANCE_WORKSPACE);
|
||||
mIsPinned = true;
|
||||
((CellLayout.LayoutParams) getLayoutParams()).canReorder = true;
|
||||
invalidate();
|
||||
}
|
||||
@@ -121,6 +134,27 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView {
|
||||
verifyHighRes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSupportedAccessibilityActions(AccessibilityNodeInfo accessibilityNodeInfo) {
|
||||
accessibilityNodeInfo.addAction(
|
||||
new AccessibilityNodeInfo.AccessibilityAction(PIN_PREDICTION,
|
||||
getContext().getText(R.string.pin_prediction)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performAccessibilityAction(int action, ItemInfo info) {
|
||||
QuickstepLauncher launcher = Launcher.cast(Launcher.getLauncher(getContext()));
|
||||
if (action == PIN_PREDICTION) {
|
||||
if (launcher == null || launcher.getHotseatPredictionController() == null) {
|
||||
return false;
|
||||
}
|
||||
HotseatPredictionController controller = launcher.getHotseatPredictionController();
|
||||
controller.pinPrediction(info);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getIconBounds(Rect outBounds) {
|
||||
super.getIconBounds(outBounds);
|
||||
|
||||
-81
@@ -19,12 +19,9 @@ import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -38,7 +35,6 @@ import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController;
|
||||
@@ -72,77 +68,6 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
||||
*/
|
||||
public static final AsyncCommand SET_SHELF_HEIGHT = (context, arg1, arg2) ->
|
||||
SystemUiProxy.INSTANCE.get(context).setShelfHeight(arg1 != 0, arg2);
|
||||
public static final RotationMode ROTATION_LANDSCAPE = new RotationMode(-90) {
|
||||
@Override
|
||||
public void mapRect(int left, int top, int right, int bottom, Rect out) {
|
||||
out.left = top;
|
||||
out.top = right;
|
||||
out.right = bottom;
|
||||
out.bottom = left;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mapInsets(Context context, Rect insets, Rect out) {
|
||||
// If there is a display cutout, the top insets in portrait would also include the
|
||||
// cutout, which we will get as the left inset in landscape. Using the max of left and
|
||||
// top allows us to cover both cases (with or without cutout).
|
||||
if (SysUINavigationMode.getMode(context) == NO_BUTTON) {
|
||||
out.top = Math.max(insets.top, insets.left);
|
||||
out.bottom = Math.max(insets.right, insets.bottom);
|
||||
out.left = out.right = 0;
|
||||
} else {
|
||||
out.top = Math.max(insets.top, insets.left);
|
||||
out.bottom = insets.right;
|
||||
out.left = insets.bottom;
|
||||
out.right = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
public static final RotationMode ROTATION_SEASCAPE = new RotationMode(90) {
|
||||
@Override
|
||||
public void mapRect(int left, int top, int right, int bottom, Rect out) {
|
||||
out.left = bottom;
|
||||
out.top = left;
|
||||
out.right = top;
|
||||
out.bottom = right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mapInsets(Context context, Rect insets, Rect out) {
|
||||
if (SysUINavigationMode.getMode(context) == NO_BUTTON) {
|
||||
out.top = Math.max(insets.top, insets.right);
|
||||
out.bottom = Math.max(insets.left, insets.bottom);
|
||||
out.left = out.right = 0;
|
||||
} else {
|
||||
out.top = Math.max(insets.top, insets.right);
|
||||
out.bottom = insets.left;
|
||||
out.right = insets.bottom;
|
||||
out.left = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int toNaturalGravity(int absoluteGravity) {
|
||||
int horizontalGravity = absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
|
||||
int verticalGravity = absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK;
|
||||
|
||||
if (horizontalGravity == Gravity.RIGHT) {
|
||||
horizontalGravity = Gravity.LEFT;
|
||||
} else if (horizontalGravity == Gravity.LEFT) {
|
||||
horizontalGravity = Gravity.RIGHT;
|
||||
}
|
||||
|
||||
if (verticalGravity == Gravity.TOP) {
|
||||
verticalGravity = Gravity.BOTTOM;
|
||||
} else if (verticalGravity == Gravity.BOTTOM) {
|
||||
verticalGravity = Gravity.TOP;
|
||||
}
|
||||
|
||||
return ((absoluteGravity & ~Gravity.HORIZONTAL_GRAVITY_MASK)
|
||||
& ~Gravity.VERTICAL_GRAVITY_MASK)
|
||||
| horizontalGravity | verticalGravity;
|
||||
}
|
||||
};
|
||||
private HotseatPredictionController mHotseatPredictionController;
|
||||
|
||||
@Override
|
||||
@@ -153,12 +78,6 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RotationMode getFakeRotationMode(DeviceProfile dp) {
|
||||
return !dp.isVerticalBarLayout() ? RotationMode.NORMAL
|
||||
: (dp.isSeascape() ? ROTATION_SEASCAPE : ROTATION_LANDSCAPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.android.launcher3.uioverrides;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS;
|
||||
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
@@ -91,7 +92,7 @@ public final class RecentsViewStateController extends
|
||||
|
||||
View actionsView = mLauncher.getActionsView();
|
||||
if (actionsView != null) {
|
||||
propertySetter.setViewAlpha(actionsView, buttonAlpha, actionInterpolator);
|
||||
propertySetter.setFloat(actionsView, VIEW_ALPHA, buttonAlpha, actionInterpolator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,6 @@ import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.model.PagedViewOrientedState;
|
||||
import com.android.launcher3.states.RotationHelper;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
@@ -149,8 +148,8 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
|
||||
}
|
||||
|
||||
public Consumer<MotionEvent> getRecentsViewDispatcher(RotationMode navBarRotationMode) {
|
||||
return mRecentsView != null ? mRecentsView.getEventDispatcher(navBarRotationMode) : null;
|
||||
public Consumer<MotionEvent> getRecentsViewDispatcher(float navbarRotation) {
|
||||
return mRecentsView != null ? mRecentsView.getEventDispatcher(navbarRotation) : null;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
||||
+5
-2
@@ -444,9 +444,12 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
GestureState newGestureState;
|
||||
|
||||
if (mDeviceState.isInSwipeUpTouchRegion(event)) {
|
||||
// Clone the previous gesture state since onConsumerAboutToBeSwitched might trigger
|
||||
// onConsumerInactive and wipe the previous gesture state
|
||||
GestureState prevGestureState = new GestureState(mGestureState);
|
||||
newGestureState = createGestureState();
|
||||
mConsumer.onConsumerAboutToBeSwitched();
|
||||
mConsumer = newConsumer(mGestureState, newGestureState, event);
|
||||
mConsumer = newConsumer(prevGestureState, newGestureState, event);
|
||||
|
||||
ActiveGestureLog.INSTANCE.addLog("setInputConsumer", mConsumer.getType());
|
||||
mUncheckedConsumer = mConsumer;
|
||||
@@ -678,7 +681,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
* To be called by the consumer when it's no longer active.
|
||||
*/
|
||||
private void onConsumerInactive(InputConsumer caller) {
|
||||
if (mConsumer == caller) {
|
||||
if (mConsumer != null && mConsumer.isInConsumerHierarchy(caller)) {
|
||||
mConsumer = mUncheckedConsumer = mResetGestureInputConsumer;
|
||||
mGestureState = new GestureState();
|
||||
}
|
||||
|
||||
+5
@@ -29,6 +29,11 @@ public abstract class DelegateInputConsumer implements InputConsumer {
|
||||
return mDelegate.isConsumerDetachedFromGesture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInConsumerHierarchy(InputConsumer candidate) {
|
||||
return this == candidate || mDelegate.isInConsumerHierarchy(candidate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInterceptByParent() {
|
||||
return mDelegate.allowInterceptByParent() && mState != STATE_ACTIVE;
|
||||
|
||||
+1
-1
@@ -182,7 +182,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
if (mPassedWindowMoveSlop && mInteractionHandler != null
|
||||
&& !mRecentsViewDispatcher.hasConsumer()) {
|
||||
mRecentsViewDispatcher.setConsumer(mInteractionHandler
|
||||
.getRecentsViewDispatcher(mNavBarPosition.getRotationMode()));
|
||||
.getRecentsViewDispatcher(mNavBarPosition.getRotation()));
|
||||
}
|
||||
int edgeFlags = ev.getEdgeFlags();
|
||||
ev.setEdgeFlags(edgeFlags | EDGE_NAV_BAR);
|
||||
|
||||
+1
-2
@@ -42,7 +42,6 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager.StateListener;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager;
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
|
||||
@@ -172,7 +171,7 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
|
||||
mActivity.getAllAppsController(), ALL_APPS_PROGRESS, allAppsProgressOffscreen));
|
||||
|
||||
ObjectAnimator dragHandleAnim = ObjectAnimator.ofInt(
|
||||
mActivity.findViewById(R.id.scrim_view), ScrimView.DRAG_HANDLE_ALPHA, 0);
|
||||
mActivity.getScrimView(), ScrimView.DRAG_HANDLE_ALPHA, 0);
|
||||
dragHandleAnim.setInterpolator(Interpolators.ACCEL_2);
|
||||
anim.play(dragHandleAnim);
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ import android.view.HapticFeedbackConstants;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.OrientationEventListener;
|
||||
import android.view.View;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.ViewGroup;
|
||||
@@ -90,6 +91,7 @@ import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.PagedView;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.anim.PendingAnimation.EndState;
|
||||
@@ -97,9 +99,9 @@ import com.android.launcher3.anim.PropertyListBuilder;
|
||||
import com.android.launcher3.anim.SpringProperty;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.states.RotationHelper;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler.CurveProperties;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
@@ -169,6 +171,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
}
|
||||
};
|
||||
|
||||
private OrientationEventListener mOrientationListener;
|
||||
private int mPreviousRotation;
|
||||
protected RecentsAnimationController mRecentsAnimationController;
|
||||
protected RecentsAnimationTargets mRecentsAnimationTargets;
|
||||
@@ -376,6 +379,22 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
|
||||
// Initialize quickstep specific cache params here, as this is constructed only once
|
||||
mActivity.getViewCache().setCacheSize(R.layout.digital_wellbeing_toast, 5);
|
||||
|
||||
mOrientationListener = new OrientationEventListener(getContext()) {
|
||||
@Override
|
||||
public void onOrientationChanged(int i) {
|
||||
int rotation = RotationHelper.getRotationFromDegrees(i);
|
||||
if (mPreviousRotation != rotation) {
|
||||
animateRecentsRotationInPlace(rotation);
|
||||
if (rotation == 0) {
|
||||
showActionsView();
|
||||
} else {
|
||||
hideActionsView();
|
||||
}
|
||||
mPreviousRotation = rotation;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public OverScroller getScroller() {
|
||||
@@ -504,6 +523,15 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
}
|
||||
|
||||
public void setOverviewStateEnabled(boolean enabled) {
|
||||
if (supportsVerticalLandscape()
|
||||
&& !TestProtocol.sDisableSensorRotation // Ignore hardware dependency for tests
|
||||
&& mOrientationListener.canDetectOrientation()) {
|
||||
if (enabled) {
|
||||
mOrientationListener.enable();
|
||||
} else {
|
||||
mOrientationListener.disable();
|
||||
}
|
||||
}
|
||||
mOverviewStateEnabled = enabled;
|
||||
updateTaskStackListenerState();
|
||||
if (!enabled) {
|
||||
@@ -784,23 +812,14 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
if (getPageCount() == 0 || getPageAt(0).getMeasuredWidth() == 0) {
|
||||
return;
|
||||
}
|
||||
CurveProperties curveProperties = mOrientationHandler
|
||||
.getCurveProperties(this, mInsets);
|
||||
int scroll = curveProperties.scroll;
|
||||
final int halfPageSize = curveProperties.halfPageSize;
|
||||
final int screenCenter = curveProperties.screenCenter;
|
||||
final int halfScreenSize = curveProperties.halfScreenSize;
|
||||
final int pageSpacing = mPageSpacing;
|
||||
mScrollState.scrollFromEdge = mIsRtl ? scroll : (mMaxScroll - scroll);
|
||||
mOrientationHandler.getCurveProperties(this, mInsets, mScrollState);
|
||||
mScrollState.scrollFromEdge =
|
||||
mIsRtl ? mScrollState.scroll : (mMaxScroll - mScrollState.scroll);
|
||||
|
||||
final int pageCount = getPageCount();
|
||||
for (int i = 0; i < pageCount; i++) {
|
||||
View page = getPageAt(i);
|
||||
float pageCenter = mOrientationHandler.getViewCenterPosition(page) + halfPageSize;
|
||||
float distanceFromScreenCenter = screenCenter - pageCenter;
|
||||
float distanceToReachEdge = halfScreenSize + halfPageSize + pageSpacing;
|
||||
mScrollState.linearInterpolation = Math.min(1,
|
||||
Math.abs(distanceFromScreenCenter) / distanceToReachEdge);
|
||||
mScrollState.updateInterpolation(mOrientationHandler.getChildStart(page), mPageSpacing);
|
||||
((PageCallbacks) page).onPageScroll(mScrollState);
|
||||
}
|
||||
}
|
||||
@@ -947,6 +966,35 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
setSwipeDownShouldLaunchApp(true);
|
||||
}
|
||||
|
||||
private void animateRecentsRotationInPlace(int newRotation) {
|
||||
if (!supportsVerticalLandscape()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AnimatorSet pa = setRecentsChangedOrientation(true);
|
||||
pa.addListener(AnimationSuccessListener.forRunnable(() -> {
|
||||
updateLayoutRotation(newRotation);
|
||||
mActivity.getDragLayer().recreateControllers();
|
||||
rotateAllChildTasks();
|
||||
setRecentsChangedOrientation(false).start();
|
||||
}));
|
||||
pa.start();
|
||||
}
|
||||
|
||||
public AnimatorSet setRecentsChangedOrientation(boolean fadeInChildren) {
|
||||
getRunningTaskIndex();
|
||||
int runningIndex = getCurrentPage();
|
||||
AnimatorSet as = new AnimatorSet();
|
||||
for (int i = 0; i < getTaskViewCount(); i++) {
|
||||
if (runningIndex == i) {
|
||||
continue;
|
||||
}
|
||||
View taskView = getTaskViewAt(i);
|
||||
as.play(ObjectAnimator.ofFloat(taskView, View.ALPHA, fadeInChildren ? 0 : 1));
|
||||
}
|
||||
return as;
|
||||
}
|
||||
|
||||
abstract protected boolean supportsVerticalLandscape();
|
||||
|
||||
private void rotateAllChildTasks() {
|
||||
@@ -1143,7 +1191,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
default void onPageScroll(ScrollState scrollState) {}
|
||||
}
|
||||
|
||||
public static class ScrollState {
|
||||
public static class ScrollState extends CurveProperties {
|
||||
|
||||
/**
|
||||
* The progress from 0 to 1, where 0 is the center
|
||||
@@ -1155,6 +1203,17 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
* The amount by which all the content is scrolled relative to the end of the list.
|
||||
*/
|
||||
public float scrollFromEdge;
|
||||
|
||||
/**
|
||||
* Updates linearInterpolation for the provided child position
|
||||
*/
|
||||
public void updateInterpolation(int childStart, int pageSpacing) {
|
||||
float pageCenter = childStart + halfPageSize;
|
||||
float distanceFromScreenCenter = screenCenter - pageCenter;
|
||||
float distanceToReachEdge = halfScreenSize + halfPageSize + pageSpacing;
|
||||
linearInterpolation = Math.min(1,
|
||||
Math.abs(distanceFromScreenCenter) / distanceToReachEdge);
|
||||
}
|
||||
}
|
||||
|
||||
public void setIgnoreResetTask(int taskId) {
|
||||
@@ -1924,13 +1983,13 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
return offsetX;
|
||||
}
|
||||
|
||||
public Consumer<MotionEvent> getEventDispatcher(RotationMode navBarRotationMode) {
|
||||
public Consumer<MotionEvent> getEventDispatcher(float navbarRotation) {
|
||||
float degreesRotated;
|
||||
if (navBarRotationMode == RotationMode.NORMAL) {
|
||||
if (navbarRotation == 0) {
|
||||
degreesRotated = mOrientationState.areMultipleLayoutOrientationsDisabled() ? 0 :
|
||||
RotationHelper.getDegreesFromRotation(mLayoutRotation);
|
||||
} else {
|
||||
degreesRotated = -navBarRotationMode.surfaceRotation;
|
||||
degreesRotated = -navbarRotation;
|
||||
}
|
||||
if (degreesRotated == 0) {
|
||||
return super::onTouchEvent;
|
||||
@@ -1940,7 +1999,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
// undo that transformation since PagedView also accommodates for the transformation via
|
||||
// PagedOrientationHandler
|
||||
return e -> {
|
||||
if (navBarRotationMode != RotationMode.NORMAL
|
||||
if (navbarRotation != 0
|
||||
&& !mOrientationState.areMultipleLayoutOrientationsDisabled()) {
|
||||
RotationHelper.transformEventForNavBar(e, true);
|
||||
super.onTouchEvent(e);
|
||||
|
||||
@@ -66,9 +66,6 @@
|
||||
docked_stack_divider_thickness - 2 * docked_stack_divider_insets -->
|
||||
<dimen name="multi_window_task_divider_size">10dp</dimen>
|
||||
|
||||
<!-- same as vertical_drag_handle_size -->
|
||||
<dimen name="shelf_surface_offset">24dp</dimen>
|
||||
|
||||
<!-- Assistant Gestures -->
|
||||
<!-- Distance from the vertical edges of the screen in which assist gestures are recognized -->
|
||||
<dimen name="gestures_assistant_width">48dp</dimen>
|
||||
|
||||
@@ -90,6 +90,9 @@
|
||||
<!-- tip shown if user declines migration and has some open spots for prediction -->
|
||||
<string name="hotseat_tip_gaps_filled">App suggestions added to empty space</string>
|
||||
|
||||
<!-- content description for hotseat items -->
|
||||
<string name="hotseat_prediction_content_description">Predicted app: <xliff:g id="title" example="Chrome">%1$s</xliff:g></string>
|
||||
|
||||
<!-- Title shown during interactive part of Back gesture tutorial for right edge. [CHAR LIMIT=30] -->
|
||||
<string name="back_gesture_tutorial_playground_title_swipe_inward_right_edge" translatable="false">Try the back gesture</string>
|
||||
<!-- Subtitle shown during interactive parts of Back gesture tutorial for right edge. [CHAR LIMIT=60] -->
|
||||
|
||||
@@ -88,9 +88,7 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
||||
super.onCreate(savedInstanceState);
|
||||
mSystemActions = new SystemActions(this);
|
||||
|
||||
SysUINavigationMode.Mode mode = SysUINavigationMode.INSTANCE.get(this)
|
||||
.addModeChangeListener(this);
|
||||
getRotationHelper().setRotationHadDifferentUI(mode != Mode.NO_BUTTON);
|
||||
SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this);
|
||||
|
||||
if (!getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)) {
|
||||
getStateManager().addStateListener(new LauncherStateManager.StateListener() {
|
||||
@@ -141,7 +139,6 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
||||
@Override
|
||||
public void onNavigationModeChanged(Mode newMode) {
|
||||
getDragLayer().recreateControllers();
|
||||
getRotationHelper().setRotationHadDifferentUI(newMode != Mode.NO_BUTTON);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -130,6 +130,17 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
|
||||
mGestureId = gestureId;
|
||||
}
|
||||
|
||||
public GestureState(GestureState other) {
|
||||
mHomeIntent = other.mHomeIntent;
|
||||
mOverviewIntent = other.mOverviewIntent;
|
||||
mActivityInterface = other.mActivityInterface;
|
||||
mStateCallback = other.mStateCallback;
|
||||
mGestureId = other.mGestureId;
|
||||
mRunningTask = other.mRunningTask;
|
||||
mEndTarget = other.mEndTarget;
|
||||
mFinishingRecentsAnimationTaskId = other.mFinishingRecentsAnimationTaskId;
|
||||
}
|
||||
|
||||
public GestureState() {
|
||||
// Do nothing, only used for initializing the gesture state prior to user unlock
|
||||
mHomeIntent = new Intent();
|
||||
|
||||
@@ -69,6 +69,13 @@ public interface InputConsumer {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given input consumer is in the hierarchy of this input consumer.
|
||||
*/
|
||||
default boolean isInConsumerHierarchy(InputConsumer candidate) {
|
||||
return this == candidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the event queue when the consumer is about to be switched to a new consumer.
|
||||
* Consumers should update the state accordingly here before the state is passed to the new
|
||||
|
||||
@@ -107,11 +107,11 @@ public class BackGestureTutorialFragment extends Fragment implements BackGesture
|
||||
}
|
||||
|
||||
void onAttachedToWindow() {
|
||||
mEdgeBackGestureHandler.setIsEnabled(true);
|
||||
mEdgeBackGestureHandler.setViewGroupParent((ViewGroup) getRootView());
|
||||
}
|
||||
|
||||
void onDetachedFromWindow() {
|
||||
mEdgeBackGestureHandler.setIsEnabled(false);
|
||||
mEdgeBackGestureHandler.setViewGroupParent(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,21 +17,18 @@ package com.android.quickstep.interaction;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayManager.DisplayListener;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemProperties;
|
||||
import android.view.Display;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.ResourceUtils;
|
||||
|
||||
@@ -40,7 +37,7 @@ import com.android.launcher3.ResourceUtils;
|
||||
*
|
||||
* Forked from platform/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java.
|
||||
*/
|
||||
public class EdgeBackGestureHandler implements DisplayListener, OnTouchListener {
|
||||
public class EdgeBackGestureHandler implements OnTouchListener {
|
||||
|
||||
private static final String TAG = "EdgeBackGestureHandler";
|
||||
private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
|
||||
@@ -106,29 +103,22 @@ public class EdgeBackGestureHandler implements DisplayListener, OnTouchListener
|
||||
mEdgeWidth = ResourceUtils.getNavbarSize("config_backGestureInset", res);
|
||||
}
|
||||
|
||||
void setIsEnabled(boolean isEnabled) {
|
||||
if (isEnabled == mIsEnabled) {
|
||||
return;
|
||||
}
|
||||
mIsEnabled = isEnabled;
|
||||
void setViewGroupParent(@Nullable ViewGroup parent) {
|
||||
mIsEnabled = parent != null;
|
||||
|
||||
if (mEdgeBackPanel != null) {
|
||||
mEdgeBackPanel.onDestroy();
|
||||
mEdgeBackPanel = null;
|
||||
}
|
||||
|
||||
if (!mIsEnabled) {
|
||||
mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
|
||||
} else {
|
||||
updateDisplaySize();
|
||||
mContext.getSystemService(DisplayManager.class).registerDisplayListener(this,
|
||||
new Handler(Looper.getMainLooper()));
|
||||
|
||||
if (mIsEnabled) {
|
||||
// Add a nav bar panel window.
|
||||
mEdgeBackPanel = new EdgeBackGesturePanel(mContext);
|
||||
mEdgeBackPanel = new EdgeBackGesturePanel(mContext, parent, createLayoutParams());
|
||||
mEdgeBackPanel.setBackCallback(mBackCallback);
|
||||
mEdgeBackPanel.setLayoutParams(createLayoutParams());
|
||||
updateDisplaySize();
|
||||
if (mContext.getDisplay() != null) {
|
||||
mContext.getDisplay().getRealSize(mDisplaySize);
|
||||
mEdgeBackPanel.setDisplaySize(mDisplaySize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,21 +126,11 @@ public class EdgeBackGestureHandler implements DisplayListener, OnTouchListener
|
||||
mGestureCallback = callback;
|
||||
}
|
||||
|
||||
private WindowManager.LayoutParams createLayoutParams() {
|
||||
private LayoutParams createLayoutParams() {
|
||||
Resources resources = mContext.getResources();
|
||||
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
|
||||
return new LayoutParams(
|
||||
ResourceUtils.getNavbarSize("navigation_edge_panel_width", resources),
|
||||
ResourceUtils.getNavbarSize("navigation_edge_panel_height", resources),
|
||||
LayoutParams.TYPE_APPLICATION_PANEL,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|
||||
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
|
||||
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
layoutParams.setTitle(TAG + mDisplayId);
|
||||
layoutParams.windowAnimations = 0;
|
||||
layoutParams.setFitInsetsTypes(0 /* types */);
|
||||
return layoutParams;
|
||||
ResourceUtils.getNavbarSize("navigation_edge_panel_height", resources));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -232,26 +212,6 @@ public class EdgeBackGestureHandler implements DisplayListener, OnTouchListener
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayAdded(int displayId) { }
|
||||
|
||||
@Override
|
||||
public void onDisplayRemoved(int displayId) { }
|
||||
|
||||
@Override
|
||||
public void onDisplayChanged(int displayId) {
|
||||
if (displayId == mDisplayId) {
|
||||
updateDisplaySize();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDisplaySize() {
|
||||
mContext.getDisplay().getRealSize(mDisplaySize);
|
||||
if (mEdgeBackPanel != null) {
|
||||
mEdgeBackPanel.setDisplaySize(mDisplaySize);
|
||||
}
|
||||
}
|
||||
|
||||
void setInsets(int leftInset, int rightInset) {
|
||||
mLeftInset = leftInset;
|
||||
mRightInset = rightInset;
|
||||
|
||||
@@ -26,11 +26,11 @@ import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.os.SystemClock;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
@@ -110,7 +110,6 @@ public class EdgeBackGesturePanel extends View {
|
||||
private static final Interpolator RUBBER_BAND_INTERPOLATOR_APPEAR =
|
||||
new PathInterpolator(1.0f / RUBBER_BAND_AMOUNT_APPEAR, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
private final WindowManager mWindowManager;
|
||||
private BackCallback mBackCallback;
|
||||
|
||||
/**
|
||||
@@ -147,7 +146,6 @@ public class EdgeBackGesturePanel extends View {
|
||||
|
||||
private VelocityTracker mVelocityTracker;
|
||||
private int mArrowPaddingEnd;
|
||||
private WindowManager.LayoutParams mLayoutParams;
|
||||
|
||||
/**
|
||||
* True if the panel is currently on the left of the screen
|
||||
@@ -232,11 +230,9 @@ public class EdgeBackGesturePanel extends View {
|
||||
}
|
||||
};
|
||||
|
||||
public EdgeBackGesturePanel(Context context) {
|
||||
public EdgeBackGesturePanel(Context context, ViewGroup parent, LayoutParams layoutParams) {
|
||||
super(context);
|
||||
|
||||
mWindowManager = context.getSystemService(WindowManager.class);
|
||||
|
||||
mDensity = context.getResources().getDisplayMetrics().density;
|
||||
|
||||
mBaseTranslation = dp(BASE_TRANSLATION_DP);
|
||||
@@ -290,11 +286,15 @@ public class EdgeBackGesturePanel extends View {
|
||||
|
||||
mSwipeThreshold = ResourceUtils.getDimenByName(
|
||||
"navigation_edge_action_drag_threshold", context.getResources(), 16 /* defaultValue */);
|
||||
parent.addView(this, layoutParams);
|
||||
setVisibility(GONE);
|
||||
}
|
||||
|
||||
void onDestroy() {
|
||||
mWindowManager.removeView(this);
|
||||
ViewGroup parent = (ViewGroup) getParent();
|
||||
if (parent != null) {
|
||||
parent.removeView(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -305,9 +305,6 @@ public class EdgeBackGesturePanel extends View {
|
||||
@SuppressLint("RtlHardcoded")
|
||||
void setIsLeftPanel(boolean isLeftPanel) {
|
||||
mIsLeftPanel = isLeftPanel;
|
||||
mLayoutParams.gravity = mIsLeftPanel
|
||||
? (Gravity.LEFT | Gravity.TOP)
|
||||
: (Gravity.RIGHT | Gravity.TOP);
|
||||
}
|
||||
|
||||
boolean getIsLeftPanel() {
|
||||
@@ -323,11 +320,6 @@ public class EdgeBackGesturePanel extends View {
|
||||
mBackCallback = callback;
|
||||
}
|
||||
|
||||
void setLayoutParams(WindowManager.LayoutParams layoutParams) {
|
||||
mLayoutParams = layoutParams;
|
||||
mWindowManager.addView(this, mLayoutParams);
|
||||
}
|
||||
|
||||
private float getCurrentAngle() {
|
||||
return mCurrentAngle;
|
||||
}
|
||||
@@ -349,7 +341,6 @@ public class EdgeBackGesturePanel extends View {
|
||||
mStartY = event.getY();
|
||||
setVisibility(VISIBLE);
|
||||
updatePosition(event.getY());
|
||||
mWindowManager.updateViewLayout(this, mLayoutParams);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
handleMoveEvent(event);
|
||||
@@ -614,10 +605,11 @@ public class EdgeBackGesturePanel extends View {
|
||||
}
|
||||
|
||||
private void updatePosition(float touchY) {
|
||||
float position = touchY - mFingerOffset;
|
||||
position = Math.max(position, mMinArrowPosition);
|
||||
position -= mLayoutParams.height / 2.0f;
|
||||
mLayoutParams.y = MathUtils.clamp((int) position, 0, mDisplaySize.y);
|
||||
float positionY = touchY - mFingerOffset;
|
||||
positionY = Math.max(positionY, mMinArrowPosition);
|
||||
positionY -= getLayoutParams().height / 2.0f;
|
||||
setX(mIsLeftPanel ? 0 : mDisplaySize.x - getLayoutParams().width);
|
||||
setY(MathUtils.clamp((int) positionY, 0, mDisplaySize.y));
|
||||
}
|
||||
|
||||
private void setDesiredVerticalTransition(float verticalTranslation, boolean animated) {
|
||||
|
||||
@@ -33,9 +33,6 @@ import com.android.quickstep.SysUINavigationMode;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
public class LayoutUtils {
|
||||
|
||||
private static final int MULTI_WINDOW_STRATEGY_HALF_SCREEN = 1;
|
||||
@@ -68,7 +65,7 @@ public class LayoutUtils {
|
||||
// UI when shown.
|
||||
extraSpace = 0;
|
||||
} else {
|
||||
extraSpace = getDefaultSwipeHeight(context, dp) + dp.verticalDragHandleSizePx
|
||||
extraSpace = getDefaultSwipeHeight(context, dp) + dp.workspacePageIndicatorHeight
|
||||
+ res.getDimensionPixelSize(
|
||||
R.dimen.dynamic_grid_hotseat_extra_vertical_size)
|
||||
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
|
||||
|
||||
@@ -17,12 +17,8 @@ package com.android.quickstep.util;
|
||||
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.view.Gravity;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.util.DefaultDisplay;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
|
||||
@@ -31,79 +27,6 @@ import com.android.quickstep.SysUINavigationMode;
|
||||
*/
|
||||
public class NavBarPosition {
|
||||
|
||||
public static final RotationMode ROTATION_LANDSCAPE = new RotationMode(-90) {
|
||||
@Override
|
||||
public void mapRect(int left, int top, int right, int bottom, Rect out) {
|
||||
out.left = top;
|
||||
out.top = right;
|
||||
out.right = bottom;
|
||||
out.bottom = left;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mapInsets(Context context, Rect insets, Rect out) {
|
||||
// If there is a display cutout, the top insets in portrait would also include the
|
||||
// cutout, which we will get as the left inset in landscape. Using the max of left and
|
||||
// top allows us to cover both cases (with or without cutout).
|
||||
if (SysUINavigationMode.getMode(context) == NO_BUTTON) {
|
||||
out.top = Math.max(insets.top, insets.left);
|
||||
out.bottom = Math.max(insets.right, insets.bottom);
|
||||
out.left = out.right = 0;
|
||||
} else {
|
||||
out.top = Math.max(insets.top, insets.left);
|
||||
out.bottom = insets.right;
|
||||
out.left = insets.bottom;
|
||||
out.right = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static final RotationMode ROTATION_SEASCAPE = new RotationMode(90) {
|
||||
@Override
|
||||
public void mapRect(int left, int top, int right, int bottom, Rect out) {
|
||||
out.left = bottom;
|
||||
out.top = left;
|
||||
out.right = top;
|
||||
out.bottom = right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mapInsets(Context context, Rect insets, Rect out) {
|
||||
if (SysUINavigationMode.getMode(context) == NO_BUTTON) {
|
||||
out.top = Math.max(insets.top, insets.right);
|
||||
out.bottom = Math.max(insets.left, insets.bottom);
|
||||
out.left = out.right = 0;
|
||||
} else {
|
||||
out.top = Math.max(insets.top, insets.right);
|
||||
out.bottom = insets.left;
|
||||
out.right = insets.bottom;
|
||||
out.left = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int toNaturalGravity(int absoluteGravity) {
|
||||
int horizontalGravity = absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
|
||||
int verticalGravity = absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK;
|
||||
|
||||
if (horizontalGravity == Gravity.RIGHT) {
|
||||
horizontalGravity = Gravity.LEFT;
|
||||
} else if (horizontalGravity == Gravity.LEFT) {
|
||||
horizontalGravity = Gravity.RIGHT;
|
||||
}
|
||||
|
||||
if (verticalGravity == Gravity.TOP) {
|
||||
verticalGravity = Gravity.BOTTOM;
|
||||
} else if (verticalGravity == Gravity.BOTTOM) {
|
||||
verticalGravity = Gravity.TOP;
|
||||
}
|
||||
|
||||
return ((absoluteGravity & ~Gravity.HORIZONTAL_GRAVITY_MASK)
|
||||
& ~Gravity.VERTICAL_GRAVITY_MASK)
|
||||
| horizontalGravity | verticalGravity;
|
||||
}
|
||||
};
|
||||
|
||||
private final SysUINavigationMode.Mode mMode;
|
||||
private final int mDisplayRotation;
|
||||
|
||||
@@ -120,8 +43,7 @@ public class NavBarPosition {
|
||||
return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270;
|
||||
}
|
||||
|
||||
public RotationMode getRotationMode() {
|
||||
return isLeftEdge() ? ROTATION_SEASCAPE
|
||||
: (isRightEdge() ? ROTATION_LANDSCAPE : RotationMode.NORMAL);
|
||||
public float getRotation() {
|
||||
return isLeftEdge() ? 90 : (isRightEdge() ? -90 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,6 @@ public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
|
||||
private float mShiftRange;
|
||||
|
||||
private final float mShelfOffset;
|
||||
private float mTopOffset;
|
||||
private float mShelfTop;
|
||||
private float mShelfTopAtThreshold;
|
||||
@@ -110,7 +109,6 @@ public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
mRadius = BOTTOM_CORNER_RADIUS_RATIO * Themes.getDialogCornerRadius(context);
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
mShelfOffset = context.getResources().getDimension(R.dimen.shelf_surface_offset);
|
||||
// Just assume the easiest UI for now, until we have the proper layout information.
|
||||
mDrawingFlatColor = true;
|
||||
}
|
||||
@@ -179,7 +177,7 @@ public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
Math.min(hotseatSize, LayoutUtils.getDefaultSwipeHeight(context, dp));
|
||||
mDragHandleProgress = 1 - (dragHandleTop / mShiftRange);
|
||||
}
|
||||
mTopOffset = dp.getInsets().top - mShelfOffset;
|
||||
mTopOffset = dp.getInsets().top - mDragHandleSize.y;
|
||||
mShelfTopAtThreshold = mShiftRange * SCRIM_CATCHUP_THRESHOLD + mTopOffset;
|
||||
}
|
||||
updateColors();
|
||||
@@ -190,12 +188,15 @@ public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
@Override
|
||||
public void updateColors() {
|
||||
super.updateColors();
|
||||
mDragHandleOffset = 0;
|
||||
if (mDrawingFlatColor) {
|
||||
mDragHandleOffset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
mDragHandleOffset = mShelfOffset - mDragHandleSize;
|
||||
if (mProgress < mDragHandleProgress) {
|
||||
mDragHandleOffset = mShiftRange * (mDragHandleProgress - mProgress);
|
||||
}
|
||||
|
||||
if (mProgress >= SCRIM_CATCHUP_THRESHOLD) {
|
||||
mShelfTop = mShiftRange * mProgress + mTopOffset;
|
||||
} else {
|
||||
@@ -231,10 +232,6 @@ public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
(float) 0, LINEAR));
|
||||
mRemainingScreenColor = setColorAlphaBound(mScrimColor, remainingScrimAlpha);
|
||||
}
|
||||
|
||||
if (mProgress < mDragHandleProgress) {
|
||||
mDragHandleOffset += mShiftRange * (mDragHandleProgress - mProgress);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -290,4 +287,9 @@ public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
mPaint.setColor(mShelfColor);
|
||||
canvas.drawRoundRect(0, mShelfTop, width, height + mRadius, mRadius, mRadius, mPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getVisualTop() {
|
||||
return mShelfTop;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2020 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<com.android.launcher3.graphics.ShadowDrawable
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:src="@drawable/drag_handle_indicator_no_shadow"
|
||||
android:elevation="@dimen/vertical_drag_handle_elevation" />
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2017 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.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="@dimen/vertical_drag_handle_size"
|
||||
android:height="@dimen/vertical_drag_handle_size"
|
||||
android:viewportWidth="36.0"
|
||||
android:viewportHeight="36.0" >
|
||||
|
||||
<group
|
||||
android:translateX="11.5"
|
||||
android:translateY="11.5">
|
||||
<path
|
||||
android:pathData="M2 8.5L6.5 4L11 8.5"
|
||||
android:strokeColor="?attr/workspaceAmbientShadowColor"
|
||||
android:strokeWidth="3.6"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" />
|
||||
|
||||
<path
|
||||
android:pathData="M2 8.5L6.5 4L11 8.5"
|
||||
android:strokeColor="?attr/workspaceTextColor"
|
||||
android:strokeWidth="1.8"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" />
|
||||
</group>
|
||||
</vector>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2020 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="@dimen/vertical_drag_handle_width"
|
||||
android:height="@dimen/vertical_drag_handle_height"
|
||||
android:viewportWidth="18.0"
|
||||
android:viewportHeight="6.0"
|
||||
android:tint="?attr/workspaceTextColor" >
|
||||
|
||||
<path
|
||||
android:pathData="M17,6c-0.15,0-0.3-0.03-0.45-0.11L9,2.12L1.45,5.89c-0.5,0.25-1.09,
|
||||
0.05-1.34-0.45S0.06,4.35,0.55,4.11l8-4c0.28-0.14,0.61-0.14,0.89,0l8,4c0.49,0.25,0.69,
|
||||
0.85,0.45,1.34C17.72,5.8,17.37,6,17,6z"
|
||||
android:fillColor="@android:color/white" />
|
||||
</vector>
|
||||
@@ -57,7 +57,7 @@
|
||||
<com.android.launcher3.pageindicators.WorkspacePageIndicator
|
||||
android:id="@+id/page_indicator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/vertical_drag_handle_size"
|
||||
android:layout_height="@dimen/workspace_page_indicator_height"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:theme="@style/HomeScreenElementTheme" />
|
||||
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
<item type="id" name="action_dismiss_notification" />
|
||||
<item type="id" name="action_remote_action_shortcut" />
|
||||
<item type="id" name="action_dismiss_prediction" />
|
||||
<item type="id" name="action_pin_prediction"/>
|
||||
|
||||
<!-- QSB IDs. DO not change -->
|
||||
<item type="id" name="search_container_workspace" />
|
||||
|
||||
+10
-3
@@ -20,7 +20,6 @@
|
||||
|
||||
<!-- Dynamic Grid -->
|
||||
<dimen name="dynamic_grid_edge_margin">8dp</dimen>
|
||||
<dimen name="dynamic_grid_page_indicator_line_height">1dp</dimen>
|
||||
<dimen name="dynamic_grid_icon_drawable_padding">8dp</dimen>
|
||||
<!-- Minimum space between workspace and hotseat in spring loaded mode -->
|
||||
<dimen name="dynamic_grid_min_spring_loaded_space">8dp</dimen>
|
||||
@@ -36,10 +35,18 @@
|
||||
<dimen name="dynamic_grid_hotseat_extra_vertical_size">34dp</dimen>
|
||||
<dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
|
||||
|
||||
<!-- Workspace page indicator -->
|
||||
<dimen name="workspace_page_indicator_height">24dp</dimen>
|
||||
<dimen name="workspace_page_indicator_line_height">1dp</dimen>
|
||||
<dimen name="workspace_page_indicator_overlap_workspace">0dp</dimen>
|
||||
|
||||
<!-- Hotseat/all-apps scrim -->
|
||||
<dimen name="all_apps_scrim_blur">4dp</dimen>
|
||||
<dimen name="vertical_drag_handle_size">24dp</dimen>
|
||||
<dimen name="vertical_drag_handle_overlap_workspace">0dp</dimen>
|
||||
<dimen name="vertical_drag_handle_width">18dp</dimen>
|
||||
<dimen name="vertical_drag_handle_height">6dp</dimen>
|
||||
<dimen name="vertical_drag_handle_elevation">1dp</dimen>
|
||||
<dimen name="vertical_drag_handle_touch_size">48dp</dimen>
|
||||
<dimen name="vertical_drag_handle_padding_in_vertical_bar_layout">16dp</dimen>
|
||||
|
||||
<!-- Drop target bar -->
|
||||
<dimen name="dynamic_grid_drop_target_size">48dp</dimen>
|
||||
|
||||
@@ -18,4 +18,5 @@
|
||||
<drawable name="ic_remove_shadow">@drawable/ic_remove_no_shadow</drawable>
|
||||
<drawable name="ic_uninstall_shadow">@drawable/ic_uninstall_no_shadow</drawable>
|
||||
<drawable name="ic_block_shadow">@drawable/ic_block_no_shadow</drawable>
|
||||
<drawable name="all_apps_arrow_shadow">@drawable/drag_handle_indicator_no_shadow</drawable>
|
||||
</resources>
|
||||
@@ -30,11 +30,8 @@ import android.content.pm.PackageInstaller.SessionParams;
|
||||
|
||||
import com.android.launcher3.FolderInfo;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.util.Executors;
|
||||
import com.android.launcher3.util.LauncherLayoutBuilder;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
@@ -46,8 +43,6 @@ import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.annotation.LooperMode.Mode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Tests for layout parser for remote layout
|
||||
*/
|
||||
@@ -120,18 +115,6 @@ public class DefaultLayoutProviderTest {
|
||||
}
|
||||
|
||||
private void writeLayoutAndLoad(LauncherLayoutBuilder builder) throws Exception {
|
||||
mModelHelper.setupDefaultLayoutProvider(builder);
|
||||
|
||||
LoaderResults results = new LoaderResults(
|
||||
LauncherAppState.getInstance(mTargetContext),
|
||||
mModelHelper.getBgDataModel(),
|
||||
mModelHelper.getAllAppsList(),
|
||||
new Callbacks[0]);
|
||||
LoaderTask task = new LoaderTask(
|
||||
LauncherAppState.getInstance(mTargetContext),
|
||||
mModelHelper.getAllAppsList(),
|
||||
mModelHelper.getBgDataModel(),
|
||||
results);
|
||||
Executors.MODEL_EXECUTOR.submit(() -> task.loadWorkspace(new ArrayList<>())).get();
|
||||
mModelHelper.setupDefaultLayoutProvider(builder).loadModelSync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,10 @@ public class LShadowLauncherApps extends ShadowLauncherApps {
|
||||
@Override
|
||||
protected List<LauncherActivityInfo> getShortcutConfigActivityList(String packageName,
|
||||
UserHandle user) {
|
||||
return Collections.emptyList();
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT).setPackage(packageName);
|
||||
return RuntimeEnvironment.application.getPackageManager().queryIntentActivities(intent, 0)
|
||||
.stream()
|
||||
.map(ri -> getLauncherActivityInfo(ri.activityInfo))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.shadows;
|
||||
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.shadows.ShadowTypeface;
|
||||
|
||||
/**
|
||||
* Extension of {@link ShadowTypeface} with missing shadow methods
|
||||
*/
|
||||
@Implements(Typeface.class)
|
||||
public class LShadowTypeface extends ShadowTypeface {
|
||||
|
||||
@Implementation
|
||||
public static Typeface create(Typeface family, int weight, boolean italic) {
|
||||
int style = italic ? Typeface.ITALIC : Typeface.NORMAL;
|
||||
if (weight >= 400) {
|
||||
style |= Typeface.BOLD;
|
||||
}
|
||||
return create(family, style);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.shadows;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.Context;
|
||||
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.shadows.ShadowApplication;
|
||||
import org.robolectric.shadows.ShadowUserManager;
|
||||
import org.robolectric.shadows.ShadowWallpaperManager;
|
||||
|
||||
/**
|
||||
* Extension of {@link ShadowUserManager} with missing shadow methods
|
||||
*/
|
||||
@Implements(WallpaperManager.class)
|
||||
public class LShadowWallpaperManager extends ShadowWallpaperManager {
|
||||
|
||||
@Implementation
|
||||
protected static WallpaperManager getInstance(Context context) {
|
||||
return context.getSystemService(WallpaperManager.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove this once the fix for
|
||||
* https://github.com/robolectric/robolectric/issues/5285
|
||||
* is available
|
||||
*/
|
||||
public static void initializeMock() {
|
||||
WallpaperManager wm = mock(WallpaperManager.class);
|
||||
ShadowApplication shadowApplication = Shadows.shadowOf(RuntimeEnvironment.application);
|
||||
shadowApplication.setSystemService(Context.WALLPAPER_SERVICE, wm);
|
||||
doReturn(0).when(wm).getDesiredMinimumWidth();
|
||||
doReturn(0).when(wm).getDesiredMinimumHeight();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.shadows;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.launcher3.util.MainThreadInitializedObject.ObjectProvider;
|
||||
import com.android.launcher3.util.ResourceBasedOverride;
|
||||
import com.android.launcher3.util.ResourceBasedOverride.Overrides;
|
||||
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.util.ReflectionHelpers.ClassParameter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Shadow for {@link Overrides} to provide custom overrides for test
|
||||
*/
|
||||
@Implements(value = Overrides.class, isInAndroidSdk = false)
|
||||
public class ShadowOverrides {
|
||||
|
||||
private static Map<Class, ObjectProvider> sProviderMap = new HashMap<>();
|
||||
|
||||
@Implementation
|
||||
public static <T extends ResourceBasedOverride> T getObject(
|
||||
Class<T> clazz, Context context, int resId) {
|
||||
ObjectProvider<T> provider = sProviderMap.get(clazz);
|
||||
if (provider != null) {
|
||||
return provider.get(context);
|
||||
}
|
||||
return Shadow.directlyOn(Overrides.class, "getObject",
|
||||
ClassParameter.from(Class.class, clazz),
|
||||
ClassParameter.from(Context.class, context),
|
||||
ClassParameter.from(int.class, resId));
|
||||
}
|
||||
|
||||
public static <T> void setProvider(Class<T> clazz, ObjectProvider<T> provider) {
|
||||
sProviderMap.put(clazz, provider);
|
||||
}
|
||||
|
||||
public static void clearProvider() {
|
||||
sProviderMap.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/package com.android.launcher3.ui;
|
||||
|
||||
import static android.view.View.MeasureSpec.EXACTLY;
|
||||
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||
|
||||
import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.Settings;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.MotionEvent.PointerProperties;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.folder.FolderPagedView;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.shadows.ShadowOverrides;
|
||||
import com.android.launcher3.util.LauncherLayoutBuilder;
|
||||
import com.android.launcher3.util.LauncherLayoutBuilder.FolderBuilder;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
import com.android.launcher3.util.ViewOnDrawExecutor;
|
||||
import com.android.launcher3.widget.WidgetsFullSheet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.annotation.LooperMode.Mode;
|
||||
import org.robolectric.shadows.ShadowLooper;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
/**
|
||||
* Tests scroll behavior at various Launcher UI components
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@LooperMode(Mode.PAUSED)
|
||||
public class LauncherUIScrollTest {
|
||||
|
||||
private Context mTargetContext;
|
||||
private InvariantDeviceProfile mIdp;
|
||||
private LauncherModelHelper mModelHelper;
|
||||
|
||||
private LauncherLayoutBuilder mLayoutBuilder;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
mModelHelper = new LauncherModelHelper();
|
||||
mTargetContext = RuntimeEnvironment.application;
|
||||
mIdp = InvariantDeviceProfile.INSTANCE.get(mTargetContext);
|
||||
ShadowOverrides.setProvider(UserEventDispatcher.class,
|
||||
c -> mock(UserEventDispatcher.class));
|
||||
|
||||
Settings.Global.putFloat(mTargetContext.getContentResolver(),
|
||||
Settings.Global.WINDOW_ANIMATION_SCALE, 0);
|
||||
|
||||
mModelHelper.installApp(TEST_PACKAGE);
|
||||
// LayoutBuilder with 3 workspace pages
|
||||
mLayoutBuilder = new LauncherLayoutBuilder()
|
||||
.atWorkspace(0, mIdp.numRows - 1, 0).putApp(TEST_PACKAGE, TEST_PACKAGE)
|
||||
.atWorkspace(0, mIdp.numRows - 1, 1).putApp(TEST_PACKAGE, TEST_PACKAGE)
|
||||
.atWorkspace(0, mIdp.numRows - 1, 2).putApp(TEST_PACKAGE, TEST_PACKAGE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWorkspacePagesBound() throws Exception {
|
||||
// Verify that the workspace if bound synchronously
|
||||
Launcher launcher = loadLauncher();
|
||||
assertEquals(3, launcher.getWorkspace().getPageCount());
|
||||
assertEquals(0, launcher.getWorkspace().getCurrentPage());
|
||||
|
||||
launcher.dispatchGenericMotionEvent(createScrollEvent(-1));
|
||||
assertNotEquals("Workspace was not scrolled",
|
||||
0, launcher.getWorkspace().getNextPage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllAppsScroll() throws Exception {
|
||||
// Install 100 apps
|
||||
for (int i = 0; i < 100; i++) {
|
||||
mModelHelper.installApp(TEST_PACKAGE + i);
|
||||
}
|
||||
|
||||
// Bind and open all-apps
|
||||
Launcher launcher = loadLauncher();
|
||||
launcher.getStateManager().goToState(LauncherState.ALL_APPS, false);
|
||||
doLayout(launcher);
|
||||
|
||||
int currentScroll = launcher.getAppsView().getActiveRecyclerView().getCurrentScrollY();
|
||||
launcher.dispatchGenericMotionEvent(createScrollEvent(-1));
|
||||
int newScroll = launcher.getAppsView().getActiveRecyclerView().getCurrentScrollY();
|
||||
|
||||
assertNotEquals("All Apps was not scrolled", currentScroll, newScroll);
|
||||
assertEquals("Workspace was scrolled", 0, launcher.getWorkspace().getNextPage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWidgetsListScroll() throws Exception {
|
||||
// Install 100 widgets
|
||||
for (int i = 0; i < 100; i++) {
|
||||
mModelHelper.installCustomShortcut(TEST_PACKAGE + i, "shortcutProvider");
|
||||
}
|
||||
|
||||
// Bind and open widgets
|
||||
Launcher launcher = loadLauncher();
|
||||
WidgetsFullSheet widgets = WidgetsFullSheet.show(launcher, false);
|
||||
doLayout(launcher);
|
||||
|
||||
int currentScroll = widgets.getRecyclerView().getCurrentScrollY();
|
||||
launcher.dispatchGenericMotionEvent(createScrollEvent(-1));
|
||||
int newScroll = widgets.getRecyclerView().getCurrentScrollY();
|
||||
assertNotEquals("Widgets was not scrolled", currentScroll, newScroll);
|
||||
assertEquals("Workspace was scrolled", 0, launcher.getWorkspace().getNextPage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFolderPageScroll() throws Exception {
|
||||
// Add a folder with multiple icons
|
||||
FolderBuilder fb = mLayoutBuilder.atWorkspace(mIdp.numColumns / 2, mIdp.numRows / 2, 0)
|
||||
.putFolder(0);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
fb.addApp(TEST_PACKAGE, TEST_PACKAGE);
|
||||
}
|
||||
|
||||
// Bind and open folder
|
||||
Launcher launcher = loadLauncher();
|
||||
doLayout(launcher);
|
||||
launcher.getWorkspace().getFirstMatch((i, v) -> v instanceof FolderIcon).performClick();
|
||||
ShadowLooper.idleMainLooper();
|
||||
doLayout(launcher);
|
||||
FolderPagedView folderPages = Folder.getOpen(launcher).getContent();
|
||||
|
||||
assertEquals(0, folderPages.getNextPage());
|
||||
launcher.dispatchGenericMotionEvent(createScrollEvent(-1));
|
||||
assertNotEquals("Folder page was not scrolled", 0, folderPages.getNextPage());
|
||||
assertEquals("Workspace was scrolled", 0, launcher.getWorkspace().getNextPage());
|
||||
}
|
||||
|
||||
private Launcher loadLauncher() throws Exception {
|
||||
mModelHelper.setupDefaultLayoutProvider(mLayoutBuilder).loadModelSync();
|
||||
|
||||
Launcher launcher = Robolectric.buildActivity(Launcher.class).setup().get();
|
||||
doLayout(launcher);
|
||||
ViewOnDrawExecutor executor = ReflectionHelpers.getField(launcher, "mPendingExecutor");
|
||||
if (executor != null) {
|
||||
executor.runAllTasks();
|
||||
}
|
||||
return launcher;
|
||||
}
|
||||
|
||||
private static void doLayout(Activity activity) {
|
||||
DeviceProfile dp = InvariantDeviceProfile.INSTANCE
|
||||
.get(RuntimeEnvironment.application).portraitProfile;
|
||||
View view = activity.getWindow().getDecorView();
|
||||
view.measure(makeMeasureSpec(dp.widthPx, EXACTLY), makeMeasureSpec(dp.heightPx, EXACTLY));
|
||||
view.layout(0, 0, dp.widthPx, dp.heightPx);
|
||||
ShadowLooper.idleMainLooper();
|
||||
}
|
||||
|
||||
private static MotionEvent createScrollEvent(int scroll) {
|
||||
DeviceProfile dp = InvariantDeviceProfile.INSTANCE
|
||||
.get(RuntimeEnvironment.application).portraitProfile;
|
||||
|
||||
final PointerProperties[] pointerProperties = new PointerProperties[1];
|
||||
pointerProperties[0] = new PointerProperties();
|
||||
pointerProperties[0].id = 0;
|
||||
final MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[1];
|
||||
coords[0] = new MotionEvent.PointerCoords();
|
||||
coords[0].setAxisValue(MotionEvent.AXIS_VSCROLL, scroll);
|
||||
coords[0].x = dp.widthPx / 2;
|
||||
coords[0].y = dp.heightPx / 2;
|
||||
|
||||
final long time = SystemClock.uptimeMillis();
|
||||
return MotionEvent.obtain(time, time, MotionEvent.ACTION_SCROLL, 1,
|
||||
pointerProperties, coords, 0, 0, 1.0f, 1.0f, 0, 0,
|
||||
InputDevice.SOURCE_CLASS_POINTER, 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.android.launcher3.util;
|
||||
|
||||
import static android.content.Intent.ACTION_CREATE_SHORTCUT;
|
||||
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTENT_URI;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
|
||||
@@ -44,6 +46,7 @@ import com.android.launcher3.LauncherProvider;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.model.AllAppsList;
|
||||
import com.android.launcher3.model.BgDataModel;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -61,6 +64,7 @@ import java.io.OutputStreamWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -345,7 +349,8 @@ public class LauncherModelHelper {
|
||||
/**
|
||||
* Sets up a dummy provider to load the provided layout by default, next time the layout loads
|
||||
*/
|
||||
public void setupDefaultLayoutProvider(LauncherLayoutBuilder builder) throws Exception {
|
||||
public LauncherModelHelper setupDefaultLayoutProvider(LauncherLayoutBuilder builder)
|
||||
throws Exception {
|
||||
Context context = RuntimeEnvironment.application;
|
||||
InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(context);
|
||||
idp.numRows = idp.numColumns = idp.numHotseatIcons = DEFAULT_GRID_SIZE;
|
||||
@@ -363,22 +368,52 @@ public class LauncherModelHelper {
|
||||
Uri layoutUri = LauncherProvider.getLayoutUri(TEST_PROVIDER_AUTHORITY, context);
|
||||
shadowOf(context.getContentResolver()).registerInputStream(layoutUri,
|
||||
new ByteArrayInputStream(bos.toByteArray()));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates an apk install with a default main activity with same class and package name
|
||||
*/
|
||||
public void installApp(String component) throws NameNotFoundException {
|
||||
ShadowPackageManager spm = shadowOf(RuntimeEnvironment.application.getPackageManager());
|
||||
ComponentName cn = new ComponentName(component, component);
|
||||
spm.addActivityIfNotPresent(cn);
|
||||
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
|
||||
filter.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
installApp(component, component, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates a custom shortcut install
|
||||
*/
|
||||
public void installCustomShortcut(String pkg, String clazz) throws NameNotFoundException {
|
||||
installApp(pkg, clazz, new IntentFilter(ACTION_CREATE_SHORTCUT));
|
||||
}
|
||||
|
||||
private void installApp(String pkg, String clazz, IntentFilter filter)
|
||||
throws NameNotFoundException {
|
||||
ShadowPackageManager spm = shadowOf(RuntimeEnvironment.application.getPackageManager());
|
||||
ComponentName cn = new ComponentName(pkg, clazz);
|
||||
spm.addActivityIfNotPresent(cn);
|
||||
|
||||
filter.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
spm.addIntentFilterForActivity(cn, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the model in memory synchronously
|
||||
*/
|
||||
public void loadModelSync() throws ExecutionException, InterruptedException {
|
||||
// Since robolectric tests run on main thread, we run the loader-UI calls on a temp thread,
|
||||
// so that we can wait appropriately for the loader to complete.
|
||||
ReflectionHelpers.setField(getModel(), "mMainExecutor", Executors.UI_HELPER_EXECUTOR);
|
||||
|
||||
Callbacks mockCb = mock(Callbacks.class);
|
||||
getModel().addCallbacksAndLoad(mockCb);
|
||||
|
||||
Executors.MODEL_EXECUTOR.submit(() -> { }).get();
|
||||
Executors.UI_HELPER_EXECUTOR.submit(() -> { }).get();
|
||||
ReflectionHelpers.setField(getModel(), "mMainExecutor", Executors.MAIN_EXECUTOR);
|
||||
getModel().removeCallbacks(mockCb);
|
||||
}
|
||||
|
||||
/**
|
||||
* An extension of LauncherProvider backed up by in-memory database.
|
||||
*/
|
||||
|
||||
@@ -21,10 +21,13 @@ import com.android.launcher3.shadows.LShadowAppWidgetManager;
|
||||
import com.android.launcher3.shadows.LShadowBackupManager;
|
||||
import com.android.launcher3.shadows.LShadowBitmap;
|
||||
import com.android.launcher3.shadows.LShadowLauncherApps;
|
||||
import com.android.launcher3.shadows.LShadowTypeface;
|
||||
import com.android.launcher3.shadows.LShadowUserManager;
|
||||
import com.android.launcher3.shadows.LShadowWallpaperManager;
|
||||
import com.android.launcher3.shadows.ShadowDeviceFlag;
|
||||
import com.android.launcher3.shadows.ShadowLooperExecutor;
|
||||
import com.android.launcher3.shadows.ShadowMainThreadInitializedObject;
|
||||
import com.android.launcher3.shadows.ShadowOverrides;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
|
||||
import org.junit.runners.model.InitializationError;
|
||||
@@ -49,9 +52,12 @@ public class LauncherRoboTestRunner extends RobolectricTestRunner {
|
||||
LShadowLauncherApps.class,
|
||||
LShadowBitmap.class,
|
||||
LShadowBackupManager.class,
|
||||
LShadowTypeface.class,
|
||||
LShadowWallpaperManager.class,
|
||||
ShadowLooperExecutor.class,
|
||||
ShadowMainThreadInitializedObject.class,
|
||||
ShadowDeviceFlag.class,
|
||||
ShadowOverrides.class
|
||||
};
|
||||
|
||||
public LauncherRoboTestRunner(Class<?> testClass) throws InitializationError {
|
||||
@@ -78,6 +84,9 @@ public class LauncherRoboTestRunner extends RobolectricTestRunner {
|
||||
|
||||
// Disable plugins
|
||||
PluginManagerWrapper.INSTANCE.initializeForTesting(mock(PluginManagerWrapper.class));
|
||||
|
||||
// Initialize mock wallpaper manager
|
||||
LShadowWallpaperManager.initializeMock();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,6 +95,7 @@ public class LauncherRoboTestRunner extends RobolectricTestRunner {
|
||||
|
||||
ShadowLog.stream = null;
|
||||
ShadowMainThreadInitializedObject.resetInitializedObjects();
|
||||
ShadowOverrides.clearProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,27 +151,25 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.BubbleTextView, defStyle, 0);
|
||||
mLayoutHorizontal = a.getBoolean(R.styleable.BubbleTextView_layoutHorizontal, false);
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
|
||||
mDisplay = a.getInteger(R.styleable.BubbleTextView_iconDisplay, DISPLAY_WORKSPACE);
|
||||
final int defaultIconSize;
|
||||
if (mDisplay == DISPLAY_WORKSPACE) {
|
||||
DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
|
||||
setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
|
||||
defaultIconSize = grid.iconSizePx;
|
||||
} else if (mDisplay == DISPLAY_ALL_APPS) {
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
|
||||
setCompoundDrawablePadding(grid.allAppsIconDrawablePaddingPx);
|
||||
defaultIconSize = grid.allAppsIconSizePx;
|
||||
} else if (mDisplay == DISPLAY_FOLDER) {
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.folderChildTextSizePx);
|
||||
setCompoundDrawablePadding(grid.folderChildDrawablePaddingPx);
|
||||
defaultIconSize = grid.folderChildIconSizePx;
|
||||
} else {
|
||||
// widget_selection or shortcut_popup
|
||||
defaultIconSize = mActivity.getDeviceProfile().iconSizePx;
|
||||
defaultIconSize = grid.iconSizePx;
|
||||
}
|
||||
|
||||
mCenterVertically = a.getBoolean(R.styleable.BubbleTextView_centerVertically, false);
|
||||
|
||||
@@ -59,14 +59,12 @@ import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.folder.PreviewBackground;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.util.CellAndSpan;
|
||||
import com.android.launcher3.util.GridOccupancy;
|
||||
import com.android.launcher3.util.ParcelableSparseArray;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.Transposable;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -77,7 +75,7 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Stack;
|
||||
|
||||
public class CellLayout extends ViewGroup implements Transposable {
|
||||
public class CellLayout extends ViewGroup {
|
||||
private static final String TAG = "CellLayout";
|
||||
private static final boolean LOGD = false;
|
||||
|
||||
@@ -184,7 +182,6 @@ public class CellLayout extends ViewGroup implements Transposable {
|
||||
|
||||
// Related to accessible drag and drop
|
||||
private boolean mUseTouchHelper = false;
|
||||
private RotationMode mRotationMode = RotationMode.NORMAL;
|
||||
|
||||
public CellLayout(Context context) {
|
||||
this(context, null);
|
||||
@@ -206,7 +203,7 @@ public class CellLayout extends ViewGroup implements Transposable {
|
||||
setClipToPadding(false);
|
||||
mActivity = ActivityContext.lookupContext(context);
|
||||
|
||||
DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
|
||||
mCellWidth = mCellHeight = -1;
|
||||
mFixedCellWidth = mFixedCellHeight = -1;
|
||||
@@ -314,24 +311,6 @@ public class CellLayout extends ViewGroup implements Transposable {
|
||||
}
|
||||
}
|
||||
|
||||
public void setRotationMode(RotationMode mode) {
|
||||
if (mRotationMode != mode) {
|
||||
mRotationMode = mode;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RotationMode getRotationMode() {
|
||||
return mRotationMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPadding(int left, int top, int right, int bottom) {
|
||||
mRotationMode.mapRect(left, top, right, bottom, mTempRect);
|
||||
super.setPadding(mTempRect.left, mTempRect.top, mTempRect.right, mTempRect.bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
if (mUseTouchHelper ||
|
||||
@@ -789,13 +768,6 @@ public class CellLayout extends ViewGroup implements Transposable {
|
||||
int childWidthSize = widthSize - (getPaddingLeft() + getPaddingRight());
|
||||
int childHeightSize = heightSize - (getPaddingTop() + getPaddingBottom());
|
||||
|
||||
mShortcutsAndWidgets.setRotation(mRotationMode.surfaceRotation);
|
||||
if (mRotationMode.isTransposed) {
|
||||
int tmp = childWidthSize;
|
||||
childWidthSize = childHeightSize;
|
||||
childHeightSize = tmp;
|
||||
}
|
||||
|
||||
if (mFixedCellWidth < 0 || mFixedCellHeight < 0) {
|
||||
int cw = DeviceProfile.calculateCellWidth(childWidthSize, mCountX);
|
||||
int ch = DeviceProfile.calculateCellHeight(childHeightSize, mCountY);
|
||||
@@ -846,15 +818,7 @@ public class CellLayout extends ViewGroup implements Transposable {
|
||||
right + mTempRect.right + getPaddingRight(),
|
||||
bottom + mTempRect.bottom + getPaddingBottom());
|
||||
|
||||
if (mRotationMode.isTransposed) {
|
||||
int halfW = mShortcutsAndWidgets.getMeasuredWidth() / 2;
|
||||
int halfH = mShortcutsAndWidgets.getMeasuredHeight() / 2;
|
||||
int cX = (left + right) / 2;
|
||||
int cY = (top + bottom) / 2;
|
||||
mShortcutsAndWidgets.layout(cX - halfW, cY - halfH, cX + halfW, cY + halfH);
|
||||
} else {
|
||||
mShortcutsAndWidgets.layout(left, top, right, bottom);
|
||||
}
|
||||
mShortcutsAndWidgets.layout(left, top, right, bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -863,8 +827,7 @@ public class CellLayout extends ViewGroup implements Transposable {
|
||||
* width in {@link DeviceProfile#calculateCellWidth(int, int)}.
|
||||
*/
|
||||
public int getUnusedHorizontalSpace() {
|
||||
return (mRotationMode.isTransposed ? getMeasuredHeight() : getMeasuredWidth())
|
||||
- getPaddingLeft() - getPaddingRight() - (mCountX * mCellWidth);
|
||||
return getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - (mCountX * mCellWidth);
|
||||
}
|
||||
|
||||
public Drawable getScrimBackground() {
|
||||
|
||||
@@ -67,7 +67,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
||||
public boolean supportsAccessibilityDrop(ItemInfo info, View view) {
|
||||
if (info instanceof WorkspaceItemInfo) {
|
||||
// Support the action unless the item is in a context menu.
|
||||
return info.screenId >= 0;
|
||||
return canRemove(info);
|
||||
}
|
||||
|
||||
return (info instanceof LauncherAppWidgetInfo)
|
||||
|
||||
@@ -76,9 +76,9 @@ public class DeviceProfile {
|
||||
public float workspaceSpringLoadShrinkFactor;
|
||||
public final int workspaceSpringLoadedBottomSpace;
|
||||
|
||||
// Drag handle
|
||||
public final int verticalDragHandleSizePx;
|
||||
private final int verticalDragHandleOverlapWorkspace;
|
||||
// Workspace page indicator
|
||||
public final int workspacePageIndicatorHeight;
|
||||
private final int mWorkspacePageIndicatorOverlapWorkspace;
|
||||
|
||||
// Workspace icons
|
||||
public int iconSizePx;
|
||||
@@ -190,10 +190,10 @@ public class DeviceProfile {
|
||||
cellLayoutBottomPaddingPx = 0;
|
||||
}
|
||||
|
||||
verticalDragHandleSizePx = res.getDimensionPixelSize(
|
||||
R.dimen.vertical_drag_handle_size);
|
||||
verticalDragHandleOverlapWorkspace =
|
||||
res.getDimensionPixelSize(R.dimen.vertical_drag_handle_overlap_workspace);
|
||||
workspacePageIndicatorHeight = res.getDimensionPixelSize(
|
||||
R.dimen.workspace_page_indicator_height);
|
||||
mWorkspacePageIndicatorOverlapWorkspace =
|
||||
res.getDimensionPixelSize(R.dimen.workspace_page_indicator_overlap_workspace);
|
||||
|
||||
iconDrawablePaddingOriginalPx =
|
||||
res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
|
||||
@@ -211,7 +211,7 @@ public class DeviceProfile {
|
||||
hotseatBarSidePaddingEndPx =
|
||||
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_side_padding);
|
||||
// Add a bit of space between nav bar and hotseat in vertical bar layout.
|
||||
hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? verticalDragHandleSizePx : 0;
|
||||
hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
|
||||
hotseatBarSizePx = ResourceUtils.pxFromDp(inv.iconSize, dm) + (isVerticalBarLayout()
|
||||
? (hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx)
|
||||
: (res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size)
|
||||
@@ -227,7 +227,7 @@ public class DeviceProfile {
|
||||
// in portrait mode closer together by adding more height to the hotseat.
|
||||
// Note: This calculation was created after noticing a pattern in the design spec.
|
||||
int extraSpace = getCellSize().y - iconSizePx - iconDrawablePaddingPx * 2
|
||||
- verticalDragHandleSizePx;
|
||||
- workspacePageIndicatorHeight;
|
||||
hotseatBarSizePx += extraSpace;
|
||||
hotseatBarBottomPaddingPx += extraSpace;
|
||||
|
||||
@@ -376,7 +376,7 @@ public class DeviceProfile {
|
||||
|
||||
if (!isVerticalLayout) {
|
||||
int expectedWorkspaceHeight = availableHeightPx - hotseatBarSizePx
|
||||
- verticalDragHandleSizePx - edgeMarginPx;
|
||||
- workspacePageIndicatorHeight - edgeMarginPx;
|
||||
float minRequiredHeight = dropTargetBarSizePx + workspaceSpringLoadedBottomSpace;
|
||||
workspaceSpringLoadShrinkFactor = Math.min(
|
||||
res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f,
|
||||
@@ -480,14 +480,14 @@ public class DeviceProfile {
|
||||
padding.bottom = edgeMarginPx;
|
||||
if (isSeascape()) {
|
||||
padding.left = hotseatBarSizePx;
|
||||
padding.right = verticalDragHandleSizePx;
|
||||
padding.right = hotseatBarSidePaddingStartPx;
|
||||
} else {
|
||||
padding.left = verticalDragHandleSizePx;
|
||||
padding.left = hotseatBarSidePaddingStartPx;
|
||||
padding.right = hotseatBarSizePx;
|
||||
}
|
||||
} else {
|
||||
int paddingBottom = hotseatBarSizePx + verticalDragHandleSizePx
|
||||
- verticalDragHandleOverlapWorkspace;
|
||||
int paddingBottom = hotseatBarSizePx + workspacePageIndicatorHeight
|
||||
- mWorkspacePageIndicatorOverlapWorkspace;
|
||||
if (isTablet) {
|
||||
// Pad the left and right of the workspace to ensure consistent spacing
|
||||
// between all icons
|
||||
@@ -554,7 +554,7 @@ public class DeviceProfile {
|
||||
mInsets.top + dropTargetBarSizePx + edgeMarginPx,
|
||||
mInsets.left + availableWidthPx - edgeMarginPx,
|
||||
mInsets.top + availableHeightPx - hotseatBarSizePx
|
||||
- verticalDragHandleSizePx - edgeMarginPx);
|
||||
- workspacePageIndicatorHeight - edgeMarginPx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,15 +27,13 @@ import android.view.ViewDebug;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.views.Transposable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Hotseat extends CellLayout implements LogContainerProvider, Insettable, Transposable {
|
||||
public class Hotseat extends CellLayout implements LogContainerProvider, Insettable {
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private boolean mHasVerticalHotseat;
|
||||
@@ -89,7 +87,7 @@ public class Hotseat extends CellLayout implements LogContainerProvider, Insetta
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
|
||||
DeviceProfile grid = mActivity.getWallpaperDeviceProfile();
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
insets = grid.getInsets();
|
||||
|
||||
if (grid.isVerticalBarLayout()) {
|
||||
@@ -117,9 +115,4 @@ public class Hotseat extends CellLayout implements LogContainerProvider, Insetta
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
return event.getY() > getCellHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RotationMode getRotationMode() {
|
||||
return Launcher.getLauncher(getContext()).getRotationMode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
@@ -102,7 +101,6 @@ import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.folder.FolderGridOrganizer;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.keyboard.CustomActionsPopup;
|
||||
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
@@ -317,9 +315,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
|
||||
private float mCurrentAssistantVisibility = 0f;
|
||||
|
||||
private DeviceProfile mStableDeviceProfile;
|
||||
private RotationMode mRotationMode = RotationMode.NORMAL;
|
||||
|
||||
protected LauncherOverlayManager mOverlayManager;
|
||||
// If true, overlay callbacks are deferred
|
||||
private boolean mDeferOverlayCallbacks;
|
||||
@@ -503,24 +498,12 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
super.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
onIdpChanged(mDeviceProfile.inv);
|
||||
}
|
||||
|
||||
private boolean supportsFakeLandscapeUI() {
|
||||
return FeatureFlags.FAKE_LANDSCAPE_UI.get() && !mRotationHelper.homeScreenCanRotate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reapplyUi() {
|
||||
reapplyUi(true /* cancelCurrentAnimation */);
|
||||
}
|
||||
|
||||
public void reapplyUi(boolean cancelCurrentAnimation) {
|
||||
if (supportsFakeLandscapeUI()) {
|
||||
mRotationMode = mStableDeviceProfile == null
|
||||
? RotationMode.NORMAL : getFakeRotationMode(mDeviceProfile);
|
||||
}
|
||||
getRootView().dispatchInsets();
|
||||
getStateManager().reapplyState(cancelCurrentAnimation);
|
||||
}
|
||||
@@ -533,7 +516,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
private void onIdpChanged(InvariantDeviceProfile idp) {
|
||||
mUserEventDispatcher = null;
|
||||
|
||||
DeviceProfile oldWallpaperProfile = getWallpaperDeviceProfile();
|
||||
initDeviceProfile(idp);
|
||||
dispatchDeviceProfileChanged();
|
||||
reapplyUi();
|
||||
@@ -542,9 +524,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
// Calling onSaveInstanceState ensures that static cache used by listWidgets is
|
||||
// initialized properly.
|
||||
onSaveInstanceState(new Bundle());
|
||||
if (oldWallpaperProfile != getWallpaperDeviceProfile()) {
|
||||
mModel.rebindCallbacks();
|
||||
}
|
||||
mModel.rebindCallbacks();
|
||||
}
|
||||
|
||||
public void onAssistantVisibilityChanged(float visibility) {
|
||||
@@ -571,41 +551,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
mDeviceProfile = mDeviceProfile.getMultiWindowProfile(this, mwSize);
|
||||
}
|
||||
|
||||
if (supportsFakeLandscapeUI() && mDeviceProfile.isVerticalBarLayout()) {
|
||||
mStableDeviceProfile = mDeviceProfile.inv.portraitProfile;
|
||||
mRotationMode = getFakeRotationMode(mDeviceProfile);
|
||||
} else {
|
||||
mStableDeviceProfile = null;
|
||||
mRotationMode = RotationMode.NORMAL;
|
||||
}
|
||||
|
||||
mRotationHelper.updateRotationAnimation();
|
||||
onDeviceProfileInitiated();
|
||||
mModelWriter = mModel.getWriter(getWallpaperDeviceProfile().isVerticalBarLayout(), true);
|
||||
}
|
||||
|
||||
public void updateInsets(Rect insets) {
|
||||
mDeviceProfile.updateInsets(insets);
|
||||
if (mStableDeviceProfile != null) {
|
||||
Rect r = mStableDeviceProfile.getInsets();
|
||||
mRotationMode.mapInsets(this, insets, r);
|
||||
mStableDeviceProfile.updateInsets(r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RotationMode getRotationMode() {
|
||||
return mRotationMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Device profile to be used by UI elements which are shown directly on top of the wallpaper
|
||||
* and whose presentation is tied to the wallpaper (and physical device) and not the activity
|
||||
* configuration.
|
||||
*/
|
||||
@Override
|
||||
public DeviceProfile getWallpaperDeviceProfile() {
|
||||
return mStableDeviceProfile == null ? mDeviceProfile : mStableDeviceProfile;
|
||||
mModelWriter = mModel.getWriter(getDeviceProfile().isVerticalBarLayout(), true);
|
||||
}
|
||||
|
||||
public RotationHelper getRotationHelper() {
|
||||
@@ -1193,7 +1140,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
// Setup the drag controller (drop targets have to be added in reverse order in priority)
|
||||
mDropTargetBar.setup(mDragController);
|
||||
|
||||
mAllAppsController.setupViews(mAppsView);
|
||||
mAllAppsController.setupViews(mAppsView, mScrimView);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1415,6 +1362,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
return mDropTargetBar;
|
||||
}
|
||||
|
||||
public ScrimView getScrimView() {
|
||||
return mScrimView;
|
||||
}
|
||||
|
||||
public LauncherAppWidgetHost getAppWidgetHost() {
|
||||
return mAppWidgetHost;
|
||||
}
|
||||
@@ -1753,7 +1704,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
public FolderIcon addFolder(CellLayout layout, int container, final int screenId, int cellX,
|
||||
int cellY) {
|
||||
final FolderInfo folderInfo = new FolderInfo();
|
||||
folderInfo.title = "";
|
||||
|
||||
// Update the model
|
||||
getModelWriter().addItemToDatabase(folderInfo, container, screenId, cellX, cellY);
|
||||
@@ -2049,7 +1999,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
mAppWidgetHost.clearViews();
|
||||
|
||||
if (mHotseat != null) {
|
||||
mHotseat.resetLayout(getWallpaperDeviceProfile().isVerticalBarLayout());
|
||||
mHotseat.resetLayout(getDeviceProfile().isVerticalBarLayout());
|
||||
}
|
||||
TraceHelper.INSTANCE.endSection(traceToken);
|
||||
}
|
||||
@@ -2724,10 +2674,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
return new TouchController[] {getDragController(), new AllAppsSwipeController(this)};
|
||||
}
|
||||
|
||||
protected RotationMode getFakeRotationMode(DeviceProfile deviceProfile) {
|
||||
return RotationMode.NORMAL;
|
||||
}
|
||||
|
||||
protected ScaleAndTranslation getOverviewScaleAndTranslationForNormalState() {
|
||||
return new ScaleAndTranslation(1.1f, 0f, 0f);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public class LauncherRootView extends InsettableFrameLayout {
|
||||
UI_STATE_ROOT_VIEW, drawInsetBar ? FLAG_DARK_NAV : 0);
|
||||
|
||||
// Update device profile before notifying th children.
|
||||
mLauncher.updateInsets(insets);
|
||||
mLauncher.getDeviceProfile().updateInsets(insets);
|
||||
boolean resetState = !insets.equals(mInsets);
|
||||
setInsets(insets);
|
||||
|
||||
@@ -127,7 +127,7 @@ public class LauncherRootView extends InsettableFrameLayout {
|
||||
}
|
||||
|
||||
public void dispatchInsets() {
|
||||
mLauncher.updateInsets(mInsets);
|
||||
mLauncher.getDeviceProfile().updateInsets(mInsets);
|
||||
super.setInsets(mInsets);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,14 @@
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.isObservedEventType;
|
||||
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
|
||||
import static com.android.launcher3.touch.OverScroll.OVERSCROLL_DAMP_FACTOR;
|
||||
import static com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE;
|
||||
import static com.android.launcher3.touch.PagedOrientationHandler.VIEW_SCROLL_BY;
|
||||
import static com.android.launcher3.touch.PagedOrientationHandler.VIEW_SCROLL_TO;
|
||||
|
||||
import android.animation.LayoutTransition;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.annotation.SuppressLint;
|
||||
@@ -42,14 +50,6 @@ import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.isObservedEventType;
|
||||
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
|
||||
import static com.android.launcher3.touch.OverScroll.OVERSCROLL_DAMP_FACTOR;
|
||||
import static com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE;
|
||||
import static com.android.launcher3.touch.PagedOrientationHandler.VIEW_SCROLL_BY;
|
||||
import static com.android.launcher3.touch.PagedOrientationHandler.VIEW_SCROLL_TO;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
@@ -63,6 +63,7 @@ import com.android.launcher3.touch.PagedOrientationHandler.ChildBounds;
|
||||
import com.android.launcher3.touch.PortraitPagedViewHandler;
|
||||
import com.android.launcher3.util.OverScroller;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -1369,10 +1370,6 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_SCROLL: {
|
||||
Launcher launcher = Launcher.getLauncher(getContext());
|
||||
if (launcher != null) {
|
||||
AbstractFloatingView.closeAllOpenViews(launcher);
|
||||
}
|
||||
// Handle mouse (or ext. device) by shifting the page depending on the scroll
|
||||
final float vscroll;
|
||||
final float hscroll;
|
||||
@@ -1383,8 +1380,8 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
vscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL);
|
||||
hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
|
||||
}
|
||||
if (Math.abs(vscroll) > Math.abs(hscroll) && !isVerticalScrollable()) {
|
||||
return true;
|
||||
if (!canScroll(Math.abs(vscroll), Math.abs(hscroll))) {
|
||||
return false;
|
||||
}
|
||||
if (hscroll != 0 || vscroll != 0) {
|
||||
boolean isForwardScroll = mIsRtl ? (hscroll < 0 || vscroll < 0)
|
||||
@@ -1402,8 +1399,13 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
return super.onGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
protected boolean isVerticalScrollable() {
|
||||
return true;
|
||||
/**
|
||||
* Returns true if the paged view can scroll for the provided vertical and horizontal
|
||||
* scroll values
|
||||
*/
|
||||
protected boolean canScroll(float absVScroll, float absHScroll) {
|
||||
ActivityContext ac = ActivityContext.lookupContext(getContext());
|
||||
return (ac == null || AbstractFloatingView.getTopOpenView(ac) == null);
|
||||
}
|
||||
|
||||
private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
|
||||
|
||||
@@ -93,7 +93,7 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
|
||||
public void setupLp(View child) {
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
|
||||
if (child instanceof LauncherAppWidgetHostView) {
|
||||
DeviceProfile profile = mActivity.getWallpaperDeviceProfile();
|
||||
DeviceProfile profile = mActivity.getDeviceProfile();
|
||||
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX,
|
||||
profile.appWidgetScale.x, profile.appWidgetScale.y);
|
||||
} else {
|
||||
@@ -108,12 +108,12 @@ public class ShortcutAndWidgetContainer extends ViewGroup {
|
||||
|
||||
public int getCellContentHeight() {
|
||||
return Math.min(getMeasuredHeight(),
|
||||
mActivity.getWallpaperDeviceProfile().getCellHeight(mContainerType));
|
||||
mActivity.getDeviceProfile().getCellHeight(mContainerType));
|
||||
}
|
||||
|
||||
public void measureChild(View child) {
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
|
||||
final DeviceProfile profile = mActivity.getWallpaperDeviceProfile();
|
||||
final DeviceProfile profile = mActivity.getDeviceProfile();
|
||||
|
||||
if (child instanceof LauncherAppWidgetHostView) {
|
||||
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX,
|
||||
|
||||
@@ -62,7 +62,6 @@ import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.graphics.TintedDrawableSpan;
|
||||
import com.android.launcher3.icons.IconProvider;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
@@ -72,7 +71,6 @@ import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.shortcuts.ShortcutRequest;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.views.Transposable;
|
||||
import com.android.launcher3.widget.PendingAddShortcutInfo;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@@ -165,7 +163,7 @@ public final class Utilities {
|
||||
public static float getDescendantCoordRelativeToAncestor(
|
||||
View descendant, View ancestor, float[] coord, boolean includeRootScroll) {
|
||||
return getDescendantCoordRelativeToAncestor(descendant, ancestor, coord, includeRootScroll,
|
||||
false, null);
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,15 +176,12 @@ public final class Utilities {
|
||||
* @param includeRootScroll Whether or not to account for the scroll of the descendant:
|
||||
* sometimes this is relevant as in a child's coordinates within the descendant.
|
||||
* @param ignoreTransform If true, view transform is ignored
|
||||
* @param outRotation If not null, and {@param ignoreTransform} is true, this is set to the
|
||||
* overall rotation of the view in degrees.
|
||||
* @return The factor by which this descendant is scaled relative to this DragLayer. Caution
|
||||
* this scale factor is assumed to be equal in X and Y, and so if at any point this
|
||||
* assumption fails, we will need to return a pair of scale factors.
|
||||
*/
|
||||
public static float getDescendantCoordRelativeToAncestor(View descendant, View ancestor,
|
||||
float[] coord, boolean includeRootScroll, boolean ignoreTransform,
|
||||
float[] outRotation) {
|
||||
float[] coord, boolean includeRootScroll, boolean ignoreTransform) {
|
||||
float scale = 1.0f;
|
||||
View v = descendant;
|
||||
while(v != ancestor && v != null) {
|
||||
@@ -196,19 +191,7 @@ public final class Utilities {
|
||||
offsetPoints(coord, -v.getScrollX(), -v.getScrollY());
|
||||
}
|
||||
|
||||
if (ignoreTransform) {
|
||||
if (v instanceof Transposable) {
|
||||
RotationMode m = ((Transposable) v).getRotationMode();
|
||||
if (m.isTransposed) {
|
||||
sMatrix.setRotate(m.surfaceRotation, v.getPivotX(), v.getPivotY());
|
||||
sMatrix.mapPoints(coord);
|
||||
|
||||
if (outRotation != null) {
|
||||
outRotation[0] += m.surfaceRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!ignoreTransform) {
|
||||
v.getMatrix().mapPoints(coord);
|
||||
}
|
||||
offsetPoints(coord, v.getLeft(), v.getTop());
|
||||
|
||||
@@ -75,7 +75,6 @@ import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.folder.PreviewBackground;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.icons.BitmapRenderer;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.pageindicators.WorkspacePageIndicator;
|
||||
@@ -125,7 +124,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
|
||||
private static final int ADJACENT_SCREEN_DROP_DURATION = 300;
|
||||
|
||||
private static final int DEFAULT_PAGE = 0;
|
||||
public static final int DEFAULT_PAGE = 0;
|
||||
|
||||
private LayoutTransition mLayoutTransition;
|
||||
@Thunk final WallpaperManager mWallpaperManager;
|
||||
@@ -276,20 +275,13 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
@Override
|
||||
public void setInsets(Rect insets) {
|
||||
DeviceProfile grid = mLauncher.getDeviceProfile();
|
||||
DeviceProfile stableGrid = mLauncher.getWallpaperDeviceProfile();
|
||||
|
||||
mMaxDistanceForFolderCreation = stableGrid.isTablet
|
||||
? 0.75f * stableGrid.iconSizePx
|
||||
: 0.55f * stableGrid.iconSizePx;
|
||||
mMaxDistanceForFolderCreation = grid.isTablet
|
||||
? 0.75f * grid.iconSizePx : 0.55f * grid.iconSizePx;
|
||||
mWorkspaceFadeInAdjacentScreens = grid.shouldFadeAdjacentWorkspaceScreens();
|
||||
|
||||
Rect padding = stableGrid.workspacePadding;
|
||||
|
||||
RotationMode rotationMode = mLauncher.getRotationMode();
|
||||
|
||||
rotationMode.mapRect(padding, mTempRect);
|
||||
setPadding(mTempRect.left, mTempRect.top, mTempRect.right, mTempRect.bottom);
|
||||
rotationMode.mapRect(stableGrid.getInsets(), mInsets);
|
||||
Rect padding = grid.workspacePadding;
|
||||
setPadding(padding.left, padding.top, padding.right, padding.bottom);
|
||||
|
||||
if (mWorkspaceFadeInAdjacentScreens) {
|
||||
// In landscape mode the page spacing is set to the default.
|
||||
@@ -302,12 +294,11 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
}
|
||||
|
||||
|
||||
int paddingLeftRight = stableGrid.cellLayoutPaddingLeftRightPx;
|
||||
int paddingBottom = stableGrid.cellLayoutBottomPaddingPx;
|
||||
int paddingLeftRight = grid.cellLayoutPaddingLeftRightPx;
|
||||
int paddingBottom = grid.cellLayoutBottomPaddingPx;
|
||||
for (int i = mWorkspaceScreens.size() - 1; i >= 0; i--) {
|
||||
CellLayout page = mWorkspaceScreens.valueAt(i);
|
||||
page.setRotationMode(rotationMode);
|
||||
page.setPadding(paddingLeftRight, 0, paddingLeftRight, paddingBottom);
|
||||
mWorkspaceScreens.valueAt(i)
|
||||
.setPadding(paddingLeftRight, 0, paddingLeftRight, paddingBottom);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +318,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
|
||||
float scale = 1;
|
||||
if (isWidget) {
|
||||
DeviceProfile profile = mLauncher.getWallpaperDeviceProfile();
|
||||
DeviceProfile profile = mLauncher.getDeviceProfile();
|
||||
scale = Utilities.shrinkRect(r, profile.appWidgetScale.x, profile.appWidgetScale.y);
|
||||
}
|
||||
size[0] = r.width();
|
||||
@@ -555,10 +546,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
// created CellLayout.
|
||||
CellLayout newScreen = (CellLayout) LayoutInflater.from(getContext()).inflate(
|
||||
R.layout.workspace_screen, this, false /* attachToRoot */);
|
||||
DeviceProfile grid = mLauncher.getWallpaperDeviceProfile();
|
||||
DeviceProfile grid = mLauncher.getDeviceProfile();
|
||||
int paddingLeftRight = grid.cellLayoutPaddingLeftRightPx;
|
||||
int paddingBottom = grid.cellLayoutBottomPaddingPx;
|
||||
newScreen.setRotationMode(mLauncher.getRotationMode());
|
||||
newScreen.setPadding(paddingLeftRight, 0, paddingLeftRight, paddingBottom);
|
||||
|
||||
mWorkspaceScreens.put(screenId, newScreen);
|
||||
|
||||
@@ -104,10 +104,8 @@ public class WorkspaceStateTransitionAnimation {
|
||||
Interpolator scaleInterpolator = config.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
|
||||
propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, scaleInterpolator);
|
||||
|
||||
if (!hotseat.getRotationMode().isTransposed) {
|
||||
setPivotToScaleWithWorkspace(hotseat);
|
||||
setPivotToScaleWithWorkspace(qsbScaleView);
|
||||
}
|
||||
setPivotToScaleWithWorkspace(hotseat);
|
||||
setPivotToScaleWithWorkspace(qsbScaleView);
|
||||
float hotseatScale = hotseatScaleAndTranslation.scale;
|
||||
Interpolator hotseatScaleInterpolator = config.getInterpolator(ANIM_HOTSEAT_SCALE,
|
||||
scaleInterpolator);
|
||||
|
||||
@@ -56,6 +56,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||
public static final int REMOVE = R.id.action_remove;
|
||||
public static final int UNINSTALL = R.id.action_uninstall;
|
||||
public static final int DISMISS_PREDICTION = R.id.action_dismiss_prediction;
|
||||
public static final int PIN_PREDICTION = R.id.action_pin_prediction;
|
||||
public static final int RECONFIGURE = R.id.action_reconfigure;
|
||||
protected static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace;
|
||||
protected static final int MOVE = R.id.action_move;
|
||||
@@ -120,6 +121,10 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||
if (!(host.getTag() instanceof ItemInfo)) return;
|
||||
ItemInfo item = (ItemInfo) host.getTag();
|
||||
|
||||
if (host instanceof AccessibilityActionHandler) {
|
||||
((AccessibilityActionHandler) host).addSupportedAccessibilityActions(info);
|
||||
}
|
||||
|
||||
// If the request came from keyboard, do not add custom shortcuts as that is already
|
||||
// exposed as a direct shortcut
|
||||
if (!fromKeyboard && ShortcutUtil.supportsShortcuts(item)) {
|
||||
@@ -157,14 +162,14 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||
}
|
||||
|
||||
private boolean itemSupportsLongClick(View host, ItemInfo info) {
|
||||
return new CustomActionsPopup(mLauncher, host).canShow()
|
||||
|| ShortcutUtil.supportsShortcuts(info);
|
||||
return PopupContainerWithArrow.canShow(host, info)
|
||||
|| new CustomActionsPopup(mLauncher, host).canShow();
|
||||
}
|
||||
|
||||
private boolean itemSupportsAccessibleDrag(ItemInfo item) {
|
||||
if (item instanceof WorkspaceItemInfo) {
|
||||
// Support the action unless the item is in a context menu.
|
||||
return item.screenId >= 0;
|
||||
return item.screenId >= 0 && item.container != Favorites.CONTAINER_HOTSEAT_PREDICTION;
|
||||
}
|
||||
return (item instanceof LauncherAppWidgetInfo)
|
||||
|| (item instanceof FolderInfo);
|
||||
@@ -181,7 +186,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||
|
||||
public boolean performAction(final View host, final ItemInfo item, int action) {
|
||||
if (action == ACTION_LONG_CLICK) {
|
||||
if (ShortcutUtil.supportsShortcuts(item)) {
|
||||
if (PopupContainerWithArrow.canShow(host, item)) {
|
||||
// Long press should be consumed for workspace items, and it should invoke the
|
||||
// Shortcuts / Notifications / Actions pop-up menu, and not start a drag as the
|
||||
// standard long press path does.
|
||||
@@ -195,7 +200,10 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (host instanceof AccessibilityActionHandler
|
||||
&& ((AccessibilityActionHandler) host).performAccessibilityAction(action, item)) {
|
||||
return true;
|
||||
}
|
||||
if (action == MOVE) {
|
||||
beginAccessibleDrag(host, item);
|
||||
} else if (action == ADD_TO_WORKSPACE) {
|
||||
@@ -466,4 +474,20 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||
}
|
||||
return screenId;
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface allowing views to handle their own action.
|
||||
*/
|
||||
public interface AccessibilityActionHandler {
|
||||
|
||||
/**
|
||||
* performs accessibility action and returns true on success
|
||||
*/
|
||||
boolean performAccessibilityAction(int action, ItemInfo itemInfo);
|
||||
|
||||
/**
|
||||
* adds all the accessibility actions that can be handled.
|
||||
*/
|
||||
void addSupportedAccessibilityActions(AccessibilityNodeInfo accessibilityNodeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public class AllAppsPagedView extends PagedView<PersonalWorkSlidingTabStrip> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVerticalScrollable() {
|
||||
return false;
|
||||
protected boolean canScroll(float absVScroll, float absHScroll) {
|
||||
return (absHScroll > absVScroll) && super.canScroll(absVScroll, absHScroll);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,8 +123,8 @@ public class AllAppsTransitionController implements StateHandler, OnDeviceProfil
|
||||
|
||||
// Use a light system UI (dark icons) if all apps is behind at least half of the
|
||||
// status bar.
|
||||
boolean forceChange = shiftCurrent - mScrimView.getDragHandleSize()
|
||||
<= mLauncher.getDeviceProfile().getInsets().top / 2;
|
||||
boolean forceChange = Math.min(shiftCurrent, mScrimView.getVisualTop())
|
||||
<= mLauncher.getDeviceProfile().getInsets().top / 2f;
|
||||
if (forceChange) {
|
||||
mLauncher.getSystemUiController().updateUiState(UI_STATE_ALL_APPS, !mIsDarkTheme);
|
||||
} else {
|
||||
@@ -212,9 +212,9 @@ public class AllAppsTransitionController implements StateHandler, OnDeviceProfil
|
||||
return AnimationSuccessListener.forRunnable(this::onProgressAnimationEnd);
|
||||
}
|
||||
|
||||
public void setupViews(AllAppsContainerView appsView) {
|
||||
public void setupViews(AllAppsContainerView appsView, ScrimView scrimView) {
|
||||
mAppsView = appsView;
|
||||
mScrimView = mLauncher.findViewById(R.id.scrim_view);
|
||||
mScrimView = scrimView;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -95,9 +95,6 @@ public final class FeatureFlags {
|
||||
public static final BooleanFlag ENABLE_HINTS_IN_OVERVIEW = getDebugFlag(
|
||||
"ENABLE_HINTS_IN_OVERVIEW", false, "Show chip hints and gleams on the overview screen");
|
||||
|
||||
public static final BooleanFlag FAKE_LANDSCAPE_UI = getDebugFlag(
|
||||
"FAKE_LANDSCAPE_UI", false, "Rotate launcher UI instead of using transposed layout");
|
||||
|
||||
public static final BooleanFlag FOLDER_NAME_SUGGEST = new DeviceFlag(
|
||||
"FOLDER_NAME_SUGGEST", true,
|
||||
"Suggests folder names instead of blank text.");
|
||||
|
||||
@@ -17,10 +17,6 @@
|
||||
|
||||
package com.android.launcher3.dragndrop;
|
||||
|
||||
import static android.view.View.MeasureSpec.EXACTLY;
|
||||
import static android.view.View.MeasureSpec.getMode;
|
||||
import static android.view.View.MeasureSpec.getSize;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
|
||||
|
||||
@@ -34,14 +30,12 @@ import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.CellLayout;
|
||||
@@ -52,12 +46,10 @@ import com.android.launcher3.ShortcutAndWidgetContainer;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.graphics.OverviewScrim;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.graphics.WorkspaceAndHotseatScrim;
|
||||
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.views.Transposable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -560,145 +552,4 @@ public class DragLayer extends BaseDragLayer<Launcher> {
|
||||
public OverviewScrim getOverviewScrim() {
|
||||
return mOverviewScrim;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
RotationMode rotation = mActivity.getRotationMode();
|
||||
int count = getChildCount();
|
||||
|
||||
if (!rotation.isTransposed
|
||||
|| getMode(widthMeasureSpec) != EXACTLY
|
||||
|| getMode(heightMeasureSpec) != EXACTLY) {
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View child = getChildAt(i);
|
||||
child.setRotation(rotation.surfaceRotation);
|
||||
}
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
} else {
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View child = getChildAt(i);
|
||||
if (child.getVisibility() == GONE) {
|
||||
continue;
|
||||
}
|
||||
if (!(child instanceof Transposable)) {
|
||||
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
|
||||
} else {
|
||||
measureChildWithMargins(child, heightMeasureSpec, 0, widthMeasureSpec, 0);
|
||||
|
||||
child.setPivotX(child.getMeasuredWidth() / 2);
|
||||
child.setPivotY(child.getMeasuredHeight() / 2);
|
||||
child.setRotation(rotation.surfaceRotation);
|
||||
}
|
||||
}
|
||||
setMeasuredDimension(getSize(widthMeasureSpec), getSize(heightMeasureSpec));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
RotationMode rotation = mActivity.getRotationMode();
|
||||
if (!rotation.isTransposed) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
return;
|
||||
}
|
||||
|
||||
final int count = getChildCount();
|
||||
|
||||
final int parentWidth = right - left;
|
||||
final int parentHeight = bottom - top;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View child = getChildAt(i);
|
||||
if (child.getVisibility() == GONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) child.getLayoutParams();
|
||||
|
||||
if (lp instanceof LayoutParams) {
|
||||
final LayoutParams dlp = (LayoutParams) lp;
|
||||
if (dlp.customPosition) {
|
||||
child.layout(dlp.x, dlp.y, dlp.x + dlp.width, dlp.y + dlp.height);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
final int width = child.getMeasuredWidth();
|
||||
final int height = child.getMeasuredHeight();
|
||||
|
||||
int childLeft;
|
||||
int childTop;
|
||||
|
||||
int gravity = lp.gravity;
|
||||
if (gravity == -1) {
|
||||
gravity = Gravity.TOP | Gravity.START;
|
||||
}
|
||||
|
||||
final int layoutDirection = getLayoutDirection();
|
||||
|
||||
int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
|
||||
|
||||
if (child instanceof Transposable) {
|
||||
absoluteGravity = rotation.toNaturalGravity(absoluteGravity);
|
||||
|
||||
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
|
||||
case Gravity.CENTER_HORIZONTAL:
|
||||
childTop = (parentHeight - height) / 2 +
|
||||
lp.topMargin - lp.bottomMargin;
|
||||
break;
|
||||
case Gravity.RIGHT:
|
||||
childTop = width / 2 + lp.rightMargin - height / 2;
|
||||
break;
|
||||
case Gravity.LEFT:
|
||||
default:
|
||||
childTop = parentHeight - lp.leftMargin - width / 2 - height / 2;
|
||||
}
|
||||
|
||||
switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
|
||||
case Gravity.CENTER_VERTICAL:
|
||||
childLeft = (parentWidth - width) / 2 +
|
||||
lp.leftMargin - lp.rightMargin;
|
||||
break;
|
||||
case Gravity.BOTTOM:
|
||||
childLeft = parentWidth - width / 2 - height / 2 - lp.bottomMargin;
|
||||
break;
|
||||
case Gravity.TOP:
|
||||
default:
|
||||
childLeft = height / 2 - width / 2 + lp.topMargin;
|
||||
}
|
||||
} else {
|
||||
switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
|
||||
case Gravity.CENTER_HORIZONTAL:
|
||||
childLeft = (parentWidth - width) / 2 +
|
||||
lp.leftMargin - lp.rightMargin;
|
||||
break;
|
||||
case Gravity.RIGHT:
|
||||
childLeft = parentWidth - width - lp.rightMargin;
|
||||
break;
|
||||
case Gravity.LEFT:
|
||||
default:
|
||||
childLeft = lp.leftMargin;
|
||||
}
|
||||
|
||||
switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
|
||||
case Gravity.TOP:
|
||||
childTop = lp.topMargin;
|
||||
break;
|
||||
case Gravity.CENTER_VERTICAL:
|
||||
childTop = (parentHeight - height) / 2 +
|
||||
lp.topMargin - lp.bottomMargin;
|
||||
break;
|
||||
case Gravity.BOTTOM:
|
||||
childTop = parentHeight - height - lp.bottomMargin;
|
||||
break;
|
||||
default:
|
||||
childTop = lp.topMargin;
|
||||
}
|
||||
}
|
||||
|
||||
child.layout(childLeft, childTop, childLeft + width, childTop + height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,7 +437,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
}
|
||||
mItemsInvalidated = true;
|
||||
mInfo.addListener(this);
|
||||
mPreviousLabel = mInfo.title.toString();
|
||||
Optional.ofNullable(mInfo.title).ifPresent(title -> mPreviousLabel = title.toString());
|
||||
mIsPreviousLabelSuggested = !mInfo.hasOption(FLAG_MANUAL_FOLDER_NAME);
|
||||
|
||||
if (!isEmpty(mInfo.title)) {
|
||||
@@ -1648,6 +1648,10 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
}
|
||||
}
|
||||
|
||||
public FolderPagedView getContent() {
|
||||
return mContent;
|
||||
}
|
||||
|
||||
private void logEditFolderLabel() {
|
||||
LauncherEvent launcherEvent = LauncherEvent.newBuilder()
|
||||
.setAction(Action.newBuilder().setType(Action.Type.SOFT_KEYBOARD))
|
||||
|
||||
@@ -115,6 +115,7 @@ public class FolderAnimationManager {
|
||||
*/
|
||||
public AnimatorSet getAnimator() {
|
||||
final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) mFolder.getLayoutParams();
|
||||
mFolderIcon.getPreviewItemManager().recomputePreviewDrawingParams();
|
||||
ClippedFolderIconLayoutRule rule = mFolderIcon.getLayoutRule();
|
||||
final List<BubbleTextView> itemsInPreview = getPreviewIconsOnPage(0);
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
||||
"is dependent on this");
|
||||
}
|
||||
|
||||
DeviceProfile grid = activity.getWallpaperDeviceProfile();
|
||||
DeviceProfile grid = activity.getDeviceProfile();
|
||||
FolderIcon icon = (FolderIcon) LayoutInflater.from(group.getContext())
|
||||
.inflate(resId, group, false);
|
||||
|
||||
@@ -570,8 +570,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
||||
public void drawDot(Canvas canvas) {
|
||||
if (!mForceHideDot && ((mDotInfo != null && mDotInfo.hasDot()) || mDotScale > 0)) {
|
||||
Rect iconBounds = mDotParams.iconBounds;
|
||||
BubbleTextView.getIconBounds(this, iconBounds,
|
||||
mActivity.getWallpaperDeviceProfile().iconSizePx);
|
||||
BubbleTextView.getIconBounds(this, iconBounds, mActivity.getDeviceProfile().iconSizePx);
|
||||
float iconScale = (float) mBackground.previewSize / iconBounds.width();
|
||||
Utilities.scaleRectAboutCenter(iconBounds, iconScale);
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.launcher3.folder;
|
||||
|
||||
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
|
||||
import static com.android.launcher3.AbstractFloatingView.TYPE_FOLDER;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
@@ -27,6 +30,7 @@ import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewDebug;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.CellLayout;
|
||||
@@ -258,7 +262,7 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||
@Override
|
||||
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
|
||||
super.onScrollChanged(l, t, oldl, oldt);
|
||||
mPageIndicator.setScroll(l, mMaxScroll);
|
||||
if (mMaxScroll > 0) mPageIndicator.setScroll(l, mMaxScroll);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -614,6 +618,12 @@ public class FolderPagedView extends PagedView<PageIndicatorDots> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canScroll(float absVScroll, float absHScroll) {
|
||||
return AbstractFloatingView.getTopOpenViewWithType(mFolder.mLauncher,
|
||||
TYPE_ALL & ~TYPE_FOLDER) == null;
|
||||
}
|
||||
|
||||
public int itemsPerPage() {
|
||||
return mOrganizer.getMaxItemsPerPage();
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ public class PreviewBackground extends CellLayout.DelegatedCellDrawing {
|
||||
mBgColor = ta.getColor(R.styleable.FolderIconPreview_folderFillColor, 0);
|
||||
ta.recycle();
|
||||
|
||||
DeviceProfile grid = activity.getWallpaperDeviceProfile();
|
||||
DeviceProfile grid = activity.getDeviceProfile();
|
||||
previewSize = grid.folderIconSizePx;
|
||||
|
||||
basePreviewOffsetX = (availableSpaceX - previewSize) / 2;
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.graphics;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
|
||||
public abstract class RotationMode {
|
||||
|
||||
public static final RotationMode NORMAL = new RotationMode(0) { };
|
||||
|
||||
public final float surfaceRotation;
|
||||
public final boolean isTransposed;
|
||||
|
||||
public RotationMode(float surfaceRotation) {
|
||||
this.surfaceRotation = surfaceRotation;
|
||||
isTransposed = surfaceRotation != 0;
|
||||
}
|
||||
|
||||
public final void mapRect(Rect rect, Rect out) {
|
||||
mapRect(rect.left, rect.top, rect.right, rect.bottom, out);
|
||||
}
|
||||
|
||||
public void mapRect(int left, int top, int right, int bottom, Rect out) {
|
||||
out.set(left, top, right, bottom);
|
||||
}
|
||||
|
||||
public void mapInsets(Context context, Rect insets, Rect out) {
|
||||
out.set(insets);
|
||||
}
|
||||
|
||||
public int toNaturalGravity(int absoluteGravity) {
|
||||
return absoluteGravity;
|
||||
}
|
||||
}
|
||||
@@ -45,8 +45,6 @@ import android.util.LongSparseArray;
|
||||
import android.util.MutableInt;
|
||||
import android.util.TimingLogger;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.FolderInfo;
|
||||
import com.android.launcher3.InstallShortcutReceiver;
|
||||
@@ -282,8 +280,7 @@ public class LoaderTask implements Runnable {
|
||||
this.notify();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void loadWorkspace(List<ShortcutInfo> allDeepShortcuts) {
|
||||
private void loadWorkspace(List<ShortcutInfo> allDeepShortcuts) {
|
||||
loadWorkspace(allDeepShortcuts, LauncherSettings.Favorites.CONTENT_URI);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ public class WorkspacePageIndicator extends View implements Insettable, PageIndi
|
||||
mLinePaint.setAlpha(0);
|
||||
|
||||
mLauncher = Launcher.getLauncher(context);
|
||||
mLineHeight = res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_line_height);
|
||||
mLineHeight = res.getDimensionPixelSize(R.dimen.workspace_page_indicator_line_height);
|
||||
|
||||
boolean darkText = WallpaperColorInfo.INSTANCE.get(context).supportsDarkText();
|
||||
mActiveAlpha = darkText ? BLACK_ALPHA : WHITE_ALPHA;
|
||||
|
||||
@@ -184,6 +184,13 @@ public class PopupContainerWithArrow<T extends BaseDraggingActivity> extends Arr
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we can show the container.
|
||||
*/
|
||||
public static boolean canShow(View icon, ItemInfo item) {
|
||||
return icon instanceof BubbleTextView && ShortcutUtil.supportsShortcuts(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the notifications and deep shortcuts associated with {@param icon}.
|
||||
* @return the container if shown or null.
|
||||
@@ -196,7 +203,7 @@ public class PopupContainerWithArrow<T extends BaseDraggingActivity> extends Arr
|
||||
return null;
|
||||
}
|
||||
ItemInfo item = (ItemInfo) icon.getTag();
|
||||
if (!ShortcutUtil.supportsShortcuts(item)) {
|
||||
if (!canShow(icon, item)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.android.launcher3.states;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
|
||||
@@ -50,8 +51,13 @@ public class HintState extends LauncherState {
|
||||
|
||||
@Override
|
||||
public void onStateTransitionEnd(Launcher launcher) {
|
||||
launcher.getStateManager().goToState(NORMAL);
|
||||
LauncherStateManager stateManager = launcher.getStateManager();
|
||||
Workspace workspace = launcher.getWorkspace();
|
||||
workspace.post(workspace::moveToDefaultScreen);
|
||||
boolean willMoveScreens = workspace.getNextPage() != Workspace.DEFAULT_PAGE;
|
||||
stateManager.goToState(NORMAL, true, willMoveScreens ? null
|
||||
: launcher.getScrimView()::startDragHandleEducationAnim);
|
||||
if (willMoveScreens) {
|
||||
workspace.post(workspace::moveToDefaultScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE;
|
||||
import static com.android.launcher3.config.FeatureFlags.FLAG_ENABLE_FIXED_ROTATION_TRANSFORM;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
@@ -36,12 +37,9 @@ import android.graphics.RectF;
|
||||
import android.provider.Settings;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.util.UiThreadHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -77,7 +75,7 @@ public class RotationHelper implements OnSharedPreferenceChangeListener {
|
||||
public static final int REQUEST_ROTATE = 1;
|
||||
public static final int REQUEST_LOCK = 2;
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final Activity mActivity;
|
||||
private final SharedPreferences mSharedPrefs;
|
||||
private final SharedPreferences mFeatureFlagsPrefs;
|
||||
|
||||
@@ -104,17 +102,16 @@ public class RotationHelper implements OnSharedPreferenceChangeListener {
|
||||
// This is used to defer setting rotation flags until the activity is being created
|
||||
private boolean mInitialized;
|
||||
private boolean mDestroyed;
|
||||
private boolean mRotationHasDifferentUI;
|
||||
|
||||
private int mLastActivityFlags = -1;
|
||||
|
||||
public RotationHelper(Launcher launcher) {
|
||||
mLauncher = launcher;
|
||||
public RotationHelper(Activity activity) {
|
||||
mActivity = activity;
|
||||
|
||||
// On large devices we do not handle auto-rotate differently.
|
||||
mIgnoreAutoRotateSettings = mLauncher.getResources().getBoolean(R.bool.allow_rotation);
|
||||
mIgnoreAutoRotateSettings = mActivity.getResources().getBoolean(R.bool.allow_rotation);
|
||||
if (!mIgnoreAutoRotateSettings) {
|
||||
mSharedPrefs = Utilities.getPrefs(mLauncher);
|
||||
mSharedPrefs = Utilities.getPrefs(mActivity);
|
||||
mSharedPrefs.registerOnSharedPreferenceChangeListener(this);
|
||||
mAutoRotateEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
|
||||
getAllowRotationDefaultValue());
|
||||
@@ -122,8 +119,8 @@ public class RotationHelper implements OnSharedPreferenceChangeListener {
|
||||
mSharedPrefs = null;
|
||||
}
|
||||
|
||||
mContentResolver = launcher.getContentResolver();
|
||||
mFeatureFlagsPrefs = Utilities.getFeatureFlagsPrefs(mLauncher);
|
||||
mContentResolver = activity.getContentResolver();
|
||||
mFeatureFlagsPrefs = Utilities.getFeatureFlagsPrefs(mActivity);
|
||||
mFeatureFlagsPrefs.registerOnSharedPreferenceChangeListener(this);
|
||||
updateForcedRotation(true);
|
||||
}
|
||||
@@ -144,7 +141,7 @@ public class RotationHelper implements OnSharedPreferenceChangeListener {
|
||||
mForcedRotation = isForcedRotation;
|
||||
}
|
||||
UI_HELPER_EXECUTOR.execute(() -> {
|
||||
if (mLauncher.checkSelfPermission(WRITE_SECURE_SETTINGS) == PERMISSION_GRANTED) {
|
||||
if (mActivity.checkSelfPermission(WRITE_SECURE_SETTINGS) == PERMISSION_GRANTED) {
|
||||
Settings.Global.putInt(mContentResolver, FIXED_ROTATION_TRANSFORM_SETTING_NAME,
|
||||
mForcedRotation ? 1 : 0);
|
||||
}
|
||||
@@ -165,29 +162,6 @@ public class RotationHelper implements OnSharedPreferenceChangeListener {
|
||||
mForcedRotationChangedListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void setRotationHadDifferentUI(boolean rotationHasDifferentUI) {
|
||||
mRotationHasDifferentUI = rotationHasDifferentUI;
|
||||
}
|
||||
|
||||
public boolean homeScreenCanRotate() {
|
||||
return mRotationHasDifferentUI || mIgnoreAutoRotateSettings || mAutoRotateEnabled
|
||||
|| mStateHandlerRequest != REQUEST_NONE
|
||||
|| mLauncher.getDeviceProfile().isMultiWindowMode;
|
||||
}
|
||||
|
||||
public void updateRotationAnimation() {
|
||||
if (FeatureFlags.FAKE_LANDSCAPE_UI.get()) {
|
||||
WindowManager.LayoutParams lp = mLauncher.getWindow().getAttributes();
|
||||
int oldAnim = lp.rotationAnimation;
|
||||
lp.rotationAnimation = homeScreenCanRotate()
|
||||
? WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE
|
||||
: WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
|
||||
if (oldAnim != lp.rotationAnimation) {
|
||||
mLauncher.getWindow().setAttributes(lp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
|
||||
if (FLAG_ENABLE_FIXED_ROTATION_TRANSFORM.equals(s)) {
|
||||
@@ -199,17 +173,13 @@ public class RotationHelper implements OnSharedPreferenceChangeListener {
|
||||
mAutoRotateEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
|
||||
getAllowRotationDefaultValue());
|
||||
if (mAutoRotateEnabled != wasRotationEnabled) {
|
||||
|
||||
notifyChange();
|
||||
updateRotationAnimation();
|
||||
mLauncher.reapplyUi();
|
||||
}
|
||||
}
|
||||
|
||||
public void setStateHandlerRequest(int request) {
|
||||
if (mStateHandlerRequest != request) {
|
||||
mStateHandlerRequest = request;
|
||||
updateRotationAnimation();
|
||||
notifyChange();
|
||||
}
|
||||
}
|
||||
@@ -231,7 +201,7 @@ public class RotationHelper implements OnSharedPreferenceChangeListener {
|
||||
// Used by tests only.
|
||||
public void forceAllowRotationForTesting(boolean allowRotation) {
|
||||
mIgnoreAutoRotateSettings =
|
||||
allowRotation || mLauncher.getResources().getBoolean(R.bool.allow_rotation);
|
||||
allowRotation || mActivity.getResources().getBoolean(R.bool.allow_rotation);
|
||||
// TODO(b/150214193) Tests currently expect launcher to be able to be rotated
|
||||
// Modify tests for this new behavior
|
||||
mForcedRotation = !allowRotation;
|
||||
@@ -243,7 +213,6 @@ public class RotationHelper implements OnSharedPreferenceChangeListener {
|
||||
if (!mInitialized) {
|
||||
mInitialized = true;
|
||||
notifyChange();
|
||||
updateRotationAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +254,7 @@ public class RotationHelper implements OnSharedPreferenceChangeListener {
|
||||
}
|
||||
if (activityFlags != mLastActivityFlags) {
|
||||
mLastActivityFlags = activityFlags;
|
||||
UiThreadHelper.setOrientationAsync(mLauncher, activityFlags);
|
||||
UiThreadHelper.setOrientationAsync(mActivity, activityFlags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -184,6 +184,10 @@ public class TestInformationHandler implements ResourceBasedOverride {
|
||||
mDeviceProfile.allAppsCellHeightPx);
|
||||
break;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_MOCK_SENSOR_ROTATION:
|
||||
TestProtocol.sDisableSensorRotation = true;
|
||||
break;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -92,6 +92,9 @@ public final class TestProtocol {
|
||||
|
||||
public static final String REQUEST_OVERVIEW_ACTIONS_ENABLED = "overview-actions-enabled";
|
||||
|
||||
public static boolean sDisableSensorRotation;
|
||||
public static final String REQUEST_MOCK_SENSOR_ROTATION = "mock-sensor-rotation";
|
||||
|
||||
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
|
||||
|
||||
public static final String NO_BACKGROUND_TO_OVERVIEW_TAG = "b/138251824";
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
package com.android.launcher3.touch;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
@@ -32,13 +35,8 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
||||
import com.android.launcher3.PagedView;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.states.RotationHelper;
|
||||
import com.android.launcher3.util.OverScroller;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
|
||||
|
||||
public class LandscapePagedViewHandler implements PagedOrientationHandler {
|
||||
|
||||
@Override
|
||||
@@ -67,12 +65,11 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CurveProperties getCurveProperties(PagedView pagedView, Rect mInsets) {
|
||||
int scroll = pagedView.getScrollY();
|
||||
final int halfPageSize = pagedView.getNormalChildHeight() / 2;
|
||||
final int screenCenter = mInsets.top + pagedView.getPaddingTop() + scroll + halfPageSize;
|
||||
final int halfScreenSize = pagedView.getMeasuredHeight() / 2;
|
||||
return new CurveProperties(scroll, halfPageSize, screenCenter, halfScreenSize);
|
||||
public void getCurveProperties(PagedView view, Rect mInsets, CurveProperties out) {
|
||||
out.scroll = view.getScrollY();
|
||||
out.halfPageSize = view.getNormalChildHeight() / 2;
|
||||
out.halfScreenSize = view.getMeasuredHeight() / 2;
|
||||
out.screenCenter = mInsets.top + view.getPaddingTop() + out.scroll + out.halfPageSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -83,7 +83,7 @@ public interface PagedOrientationHandler {
|
||||
void delegateScrollTo(PagedView pagedView, int primaryScroll);
|
||||
void delegateScrollBy(PagedView pagedView, int unboundedScroll, int x, int y);
|
||||
void scrollerStartScroll(OverScroller scroller, int newPosition);
|
||||
CurveProperties getCurveProperties(PagedView pagedView, Rect insets);
|
||||
void getCurveProperties(PagedView view, Rect mInsets, CurveProperties out);
|
||||
boolean isGoingUp(float displacement);
|
||||
|
||||
/**
|
||||
@@ -92,18 +92,12 @@ public interface PagedOrientationHandler {
|
||||
*/
|
||||
void adjustFloatingIconStartVelocity(PointF velocity);
|
||||
|
||||
class CurveProperties {
|
||||
public final int scroll;
|
||||
public final int halfPageSize;
|
||||
public final int screenCenter;
|
||||
public final int halfScreenSize;
|
||||
|
||||
public CurveProperties(int scroll, int halfPageSize, int screenCenter, int halfScreenSize) {
|
||||
this.scroll = scroll;
|
||||
this.halfPageSize = halfPageSize;
|
||||
this.screenCenter = screenCenter;
|
||||
this.halfScreenSize = halfScreenSize;
|
||||
}
|
||||
class CurveProperties {
|
||||
public int scroll;
|
||||
public int halfPageSize;
|
||||
public int screenCenter;
|
||||
public int halfScreenSize;
|
||||
}
|
||||
|
||||
class ChildBounds {
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
|
||||
package com.android.launcher3.touch;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
@@ -32,13 +35,8 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
||||
import com.android.launcher3.PagedView;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.states.RotationHelper;
|
||||
import com.android.launcher3.util.OverScroller;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
|
||||
|
||||
public class PortraitPagedViewHandler implements PagedOrientationHandler {
|
||||
|
||||
@Override
|
||||
@@ -67,12 +65,11 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CurveProperties getCurveProperties(PagedView pagedView, Rect mInsets) {
|
||||
int scroll = pagedView.getScrollX();
|
||||
final int halfPageSize = pagedView.getNormalChildWidth() / 2;
|
||||
final int screenCenter = mInsets.left + pagedView.getPaddingLeft() + scroll + halfPageSize;
|
||||
final int halfScreenSize = pagedView.getMeasuredWidth() / 2;
|
||||
return new CurveProperties(scroll, halfPageSize, screenCenter, halfScreenSize);
|
||||
public void getCurveProperties(PagedView view, Rect mInsets, CurveProperties out) {
|
||||
out.scroll = view.getScrollX();
|
||||
out.halfPageSize = view.getNormalChildWidth() / 2;
|
||||
out.halfScreenSize = view.getMeasuredWidth() / 2;
|
||||
out.screenCenter = mInsets.left + view.getPaddingLeft() + out.scroll + out.halfPageSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.view.View.AccessibilityDelegate;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
import com.android.launcher3.dot.DotInfo;
|
||||
|
||||
/**
|
||||
@@ -57,19 +56,6 @@ public interface ActivityContext {
|
||||
|
||||
DeviceProfile getDeviceProfile();
|
||||
|
||||
/**
|
||||
* Device profile to be used by UI elements which are shown directly on top of the wallpaper
|
||||
* and whose presentation is tied to the wallpaper (and physical device) and not the activity
|
||||
* configuration.
|
||||
*/
|
||||
default DeviceProfile getWallpaperDeviceProfile() {
|
||||
return getDeviceProfile();
|
||||
}
|
||||
|
||||
default RotationMode getRotationMode() {
|
||||
return RotationMode.NORMAL;
|
||||
}
|
||||
|
||||
static ActivityContext lookupContext(Context context) {
|
||||
if (context instanceof ActivityContext) {
|
||||
return (ActivityContext) context;
|
||||
|
||||
@@ -92,8 +92,6 @@ public class FloatingIconView extends FrameLayout implements
|
||||
private ClipIconView mClipIconView;
|
||||
private @Nullable Drawable mBadge;
|
||||
|
||||
private float mRotation;
|
||||
|
||||
private View mOriginalIcon;
|
||||
private RectF mPositionOut;
|
||||
private Runnable mOnTargetChangeRunnable;
|
||||
@@ -194,18 +192,17 @@ public class FloatingIconView extends FrameLayout implements
|
||||
* @param positionOut Rect that will hold the size and position of v.
|
||||
*/
|
||||
private void matchPositionOf(Launcher launcher, View v, boolean isOpening, RectF positionOut) {
|
||||
float rotation = getLocationBoundsForView(launcher, v, isOpening, positionOut);
|
||||
getLocationBoundsForView(launcher, v, isOpening, positionOut);
|
||||
final InsettableFrameLayout.LayoutParams lp = new InsettableFrameLayout.LayoutParams(
|
||||
Math.round(positionOut.width()),
|
||||
Math.round(positionOut.height()));
|
||||
updatePosition(rotation, positionOut, lp);
|
||||
updatePosition(positionOut, lp);
|
||||
setLayoutParams(lp);
|
||||
|
||||
mClipIconView.setLayoutParams(new FrameLayout.LayoutParams(lp.width, lp.height));
|
||||
}
|
||||
|
||||
private void updatePosition(float rotation, RectF pos, InsettableFrameLayout.LayoutParams lp) {
|
||||
mRotation = rotation;
|
||||
private void updatePosition(RectF pos, InsettableFrameLayout.LayoutParams lp) {
|
||||
mPositionOut.set(pos);
|
||||
lp.ignoreInsets = true;
|
||||
// Position the floating view exactly on top of the original
|
||||
@@ -228,7 +225,7 @@ public class FloatingIconView extends FrameLayout implements
|
||||
* - For DeepShortcutView, we return the bounds of the icon view.
|
||||
* - For BubbleTextView, we return the icon bounds.
|
||||
*/
|
||||
private static float getLocationBoundsForView(Launcher launcher, View v, boolean isOpening,
|
||||
private static void getLocationBoundsForView(Launcher launcher, View v, boolean isOpening,
|
||||
RectF outRect) {
|
||||
boolean ignoreTransform = !isOpening;
|
||||
if (v instanceof DeepShortcutView) {
|
||||
@@ -239,7 +236,7 @@ public class FloatingIconView extends FrameLayout implements
|
||||
ignoreTransform = false;
|
||||
}
|
||||
if (v == null) {
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Rect iconBounds = new Rect();
|
||||
@@ -253,15 +250,13 @@ public class FloatingIconView extends FrameLayout implements
|
||||
|
||||
float[] points = new float[] {iconBounds.left, iconBounds.top, iconBounds.right,
|
||||
iconBounds.bottom};
|
||||
float[] rotation = new float[] {0};
|
||||
Utilities.getDescendantCoordRelativeToAncestor(v, launcher.getDragLayer(), points,
|
||||
false, ignoreTransform, rotation);
|
||||
false, ignoreTransform);
|
||||
outRect.set(
|
||||
Math.min(points[0], points[2]),
|
||||
Math.min(points[1], points[3]),
|
||||
Math.max(points[0], points[2]),
|
||||
Math.max(points[1], points[3]));
|
||||
return rotation[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,14 +438,10 @@ public class FloatingIconView extends FrameLayout implements
|
||||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
int count = canvas.save();
|
||||
canvas.rotate(mRotation,
|
||||
mFinalDrawableBounds.exactCenterX(), mFinalDrawableBounds.exactCenterY());
|
||||
super.dispatchDraw(canvas);
|
||||
if (mBadge != null) {
|
||||
mBadge.draw(canvas);
|
||||
}
|
||||
canvas.restoreToCount(count);
|
||||
}
|
||||
|
||||
public void fastFinish() {
|
||||
@@ -487,11 +478,10 @@ public class FloatingIconView extends FrameLayout implements
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (mOriginalIcon.isAttachedToWindow() && mPositionOut != null) {
|
||||
float rotation = getLocationBoundsForView(mLauncher, mOriginalIcon, mIsOpening,
|
||||
getLocationBoundsForView(mLauncher, mOriginalIcon, mIsOpening,
|
||||
sTmpRectF);
|
||||
if (rotation != mRotation || !sTmpRectF.equals(mPositionOut)) {
|
||||
updatePosition(rotation, sTmpRectF,
|
||||
(InsettableFrameLayout.LayoutParams) getLayoutParams());
|
||||
if (!sTmpRectF.equals(mPositionOut)) {
|
||||
updatePosition(sTmpRectF, (InsettableFrameLayout.LayoutParams) getLayoutParams());
|
||||
if (mOnTargetChangeRunnable != null) {
|
||||
mOnTargetChangeRunnable.run();
|
||||
}
|
||||
|
||||
@@ -22,8 +22,10 @@ import static androidx.core.graphics.ColorUtils.compositeColors;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.Interpolators.clampToProgress;
|
||||
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -33,8 +35,10 @@ import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.animation.RectEvaluator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -98,6 +102,12 @@ public class ScrimView<T extends Launcher> extends View implements Insettable, O
|
||||
private static final int SETTINGS = R.string.settings_button_text;
|
||||
private static final int ALPHA_CHANNEL_COUNT = 1;
|
||||
|
||||
private static final long DRAG_HANDLE_BOUNCE_DURATION_MS = 300;
|
||||
// How much to delay before repeating the bounce.
|
||||
private static final long DRAG_HANDLE_BOUNCE_DELAY_MS = 200;
|
||||
// Repeat this many times (i.e. total number of bounces is 1 + this).
|
||||
private static final int DRAG_HANDLE_BOUNCE_REPEAT_COUNT = 2;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final int[] mTempPos = new int[2];
|
||||
|
||||
@@ -115,10 +125,13 @@ public class ScrimView<T extends Launcher> extends View implements Insettable, O
|
||||
protected int mEndFlatColor;
|
||||
protected int mEndFlatColorAlpha;
|
||||
|
||||
protected final int mDragHandleSize;
|
||||
protected final Point mDragHandleSize;
|
||||
private final int mDragHandleTouchSize;
|
||||
private final int mDragHandlePaddingInVerticalBarLayout;
|
||||
protected float mDragHandleOffset;
|
||||
private final Rect mDragHandleBounds;
|
||||
private final RectF mHitRect = new RectF();
|
||||
private ObjectAnimator mDragHandleAnim;
|
||||
|
||||
private final MultiValueAlpha mMultiValueAlpha;
|
||||
|
||||
@@ -136,9 +149,13 @@ public class ScrimView<T extends Launcher> extends View implements Insettable, O
|
||||
|
||||
mMaxScrimAlpha = 0.7f;
|
||||
|
||||
mDragHandleSize = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.vertical_drag_handle_size);
|
||||
mDragHandleBounds = new Rect(0, 0, mDragHandleSize, mDragHandleSize);
|
||||
Resources res = context.getResources();
|
||||
mDragHandleSize = new Point(res.getDimensionPixelSize(R.dimen.vertical_drag_handle_width),
|
||||
res.getDimensionPixelSize(R.dimen.vertical_drag_handle_height));
|
||||
mDragHandleBounds = new Rect(0, 0, mDragHandleSize.x, mDragHandleSize.y);
|
||||
mDragHandleTouchSize = res.getDimensionPixelSize(R.dimen.vertical_drag_handle_touch_size);
|
||||
mDragHandlePaddingInVerticalBarLayout = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.vertical_drag_handle_padding_in_vertical_bar_layout);
|
||||
|
||||
mAccessibilityHelper = createAccessibilityHelper();
|
||||
ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
|
||||
@@ -204,6 +221,7 @@ public class ScrimView<T extends Launcher> extends View implements Insettable, O
|
||||
public void setProgress(float progress) {
|
||||
if (mProgress != progress) {
|
||||
mProgress = progress;
|
||||
stopDragHandleEducationAnim();
|
||||
updateColors();
|
||||
updateDragHandleAlpha();
|
||||
invalidate();
|
||||
@@ -251,70 +269,103 @@ public class ScrimView<T extends Launcher> extends View implements Insettable, O
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
boolean value = super.onTouchEvent(event);
|
||||
if (!value && mDragHandle != null && event.getAction() == ACTION_DOWN
|
||||
&& mDragHandle.getAlpha() == 255
|
||||
&& mHitRect.contains(event.getX(), event.getY())) {
|
||||
|
||||
final Drawable drawable = mDragHandle;
|
||||
mDragHandle = null;
|
||||
|
||||
Rect bounds = new Rect(mDragHandleBounds);
|
||||
bounds.offset(0, -(int) mDragHandleOffset);
|
||||
drawable.setBounds(bounds);
|
||||
|
||||
Rect topBounds = new Rect(bounds);
|
||||
topBounds.offset(0, -bounds.height() / 2);
|
||||
|
||||
Rect invalidateRegion = new Rect(bounds);
|
||||
invalidateRegion.top = topBounds.top;
|
||||
|
||||
Keyframe frameTop = Keyframe.ofObject(0.6f, topBounds);
|
||||
frameTop.setInterpolator(DEACCEL);
|
||||
Keyframe frameBot = Keyframe.ofObject(1, bounds);
|
||||
frameBot.setInterpolator(ACCEL);
|
||||
PropertyValuesHolder holder = PropertyValuesHolder .ofKeyframe("bounds",
|
||||
Keyframe.ofObject(0, bounds), frameTop, frameBot);
|
||||
holder.setEvaluator(new RectEvaluator());
|
||||
|
||||
ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(drawable, holder);
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
getOverlay().remove(drawable);
|
||||
updateDragHandleVisibility(drawable);
|
||||
boolean superHandledTouch = super.onTouchEvent(event);
|
||||
if (event.getAction() == ACTION_DOWN) {
|
||||
if (!superHandledTouch && mHitRect.contains(event.getX(), event.getY())) {
|
||||
if (startDragHandleEducationAnim()) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
anim.addUpdateListener((v) -> invalidate(invalidateRegion));
|
||||
getOverlay().add(drawable);
|
||||
anim.start();
|
||||
return true;
|
||||
}
|
||||
stopDragHandleEducationAnim();
|
||||
}
|
||||
return superHandledTouch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates the drag handle to demonstrate how to get to all apps.
|
||||
* @return Whether the animation was started (false if drag handle is invisible).
|
||||
*/
|
||||
public boolean startDragHandleEducationAnim() {
|
||||
stopDragHandleEducationAnim();
|
||||
|
||||
if (mDragHandle == null || mDragHandle.getAlpha() != 255) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Drawable drawable = mDragHandle;
|
||||
mDragHandle = null;
|
||||
|
||||
Rect bounds = new Rect(mDragHandleBounds);
|
||||
bounds.offset(0, -(int) mDragHandleOffset);
|
||||
drawable.setBounds(bounds);
|
||||
|
||||
Rect topBounds = new Rect(bounds);
|
||||
topBounds.offset(0, -bounds.height());
|
||||
|
||||
Rect invalidateRegion = new Rect(bounds);
|
||||
invalidateRegion.top = topBounds.top;
|
||||
|
||||
final float progressToReachTop = 0.6f;
|
||||
Keyframe frameTop = Keyframe.ofObject(progressToReachTop, topBounds);
|
||||
frameTop.setInterpolator(DEACCEL);
|
||||
Keyframe frameBot = Keyframe.ofObject(1, bounds);
|
||||
frameBot.setInterpolator(ACCEL_DEACCEL);
|
||||
PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("bounds",
|
||||
Keyframe.ofObject(0, bounds), frameTop, frameBot);
|
||||
holder.setEvaluator(new RectEvaluator());
|
||||
|
||||
mDragHandleAnim = ObjectAnimator.ofPropertyValuesHolder(drawable, holder);
|
||||
long totalBounceDuration = DRAG_HANDLE_BOUNCE_DURATION_MS + DRAG_HANDLE_BOUNCE_DELAY_MS;
|
||||
// The bounce finishes by this progress, the rest of the duration just delays next bounce.
|
||||
float delayStartProgress = 1f - (float) DRAG_HANDLE_BOUNCE_DELAY_MS / totalBounceDuration;
|
||||
mDragHandleAnim.addUpdateListener((v) -> invalidate(invalidateRegion));
|
||||
mDragHandleAnim.setDuration(totalBounceDuration);
|
||||
mDragHandleAnim.setInterpolator(clampToProgress(LINEAR, 0, delayStartProgress));
|
||||
mDragHandleAnim.setRepeatCount(DRAG_HANDLE_BOUNCE_REPEAT_COUNT);
|
||||
getOverlay().add(drawable);
|
||||
|
||||
mDragHandleAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mDragHandleAnim = null;
|
||||
getOverlay().remove(drawable);
|
||||
updateDragHandleVisibility(drawable);
|
||||
}
|
||||
});
|
||||
mDragHandleAnim.start();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void stopDragHandleEducationAnim() {
|
||||
if (mDragHandleAnim != null) {
|
||||
mDragHandleAnim.end();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected void updateDragHandleBounds() {
|
||||
DeviceProfile grid = mLauncher.getDeviceProfile();
|
||||
final int left;
|
||||
final int width = getMeasuredWidth();
|
||||
final int top = getMeasuredHeight() - mDragHandleSize - grid.getInsets().bottom;
|
||||
final int top = getMeasuredHeight() - mDragHandleSize.y - grid.getInsets().bottom;
|
||||
final int topMargin;
|
||||
|
||||
if (grid.isVerticalBarLayout()) {
|
||||
topMargin = grid.workspacePadding.bottom;
|
||||
topMargin = grid.workspacePadding.bottom + mDragHandlePaddingInVerticalBarLayout;
|
||||
if (grid.isSeascape()) {
|
||||
left = width - grid.getInsets().right - mDragHandleSize;
|
||||
left = width - grid.getInsets().right - mDragHandleSize.x
|
||||
- mDragHandlePaddingInVerticalBarLayout;
|
||||
} else {
|
||||
left = mDragHandleSize + grid.getInsets().left;
|
||||
left = grid.getInsets().left + mDragHandlePaddingInVerticalBarLayout;
|
||||
}
|
||||
} else {
|
||||
left = (width - mDragHandleSize) / 2;
|
||||
left = Math.round((width - mDragHandleSize.x) / 2f);
|
||||
topMargin = grid.hotseatBarSizePx;
|
||||
}
|
||||
mDragHandleBounds.offsetTo(left, top - topMargin);
|
||||
mHitRect.set(mDragHandleBounds);
|
||||
float inset = -mDragHandleSize / 2;
|
||||
mHitRect.inset(inset, inset);
|
||||
// Inset outwards to increase touch size.
|
||||
mHitRect.inset((mDragHandleSize.x - mDragHandleTouchSize) / 2f,
|
||||
(mDragHandleSize.y - mDragHandleTouchSize) / 2f);
|
||||
|
||||
if (mDragHandle != null) {
|
||||
mDragHandle.setBounds(mDragHandleBounds);
|
||||
@@ -341,7 +392,7 @@ public class ScrimView<T extends Launcher> extends View implements Insettable, O
|
||||
if (visible != wasVisible) {
|
||||
if (visible) {
|
||||
mDragHandle = recycle != null ? recycle :
|
||||
mLauncher.getDrawable(R.drawable.drag_handle_indicator);
|
||||
mLauncher.getDrawable(R.drawable.drag_handle_indicator_shadow);
|
||||
mDragHandle.setBounds(mDragHandleBounds);
|
||||
|
||||
updateDragHandleAlpha();
|
||||
@@ -397,7 +448,7 @@ public class ScrimView<T extends Launcher> extends View implements Insettable, O
|
||||
|
||||
@Override
|
||||
protected int getVirtualViewAt(float x, float y) {
|
||||
return mDragHandleBounds.contains((int) x, (int) y)
|
||||
return mHitRect.contains((int) x, (int) y)
|
||||
? DRAG_HANDLE_ID : INVALID_ID;
|
||||
}
|
||||
|
||||
@@ -470,7 +521,10 @@ public class ScrimView<T extends Launcher> extends View implements Insettable, O
|
||||
}
|
||||
}
|
||||
|
||||
public int getDragHandleSize() {
|
||||
return mDragHandleSize;
|
||||
/**
|
||||
* @return The top of this scrim view, or {@link Float#MAX_VALUE} if there's no distinct top.
|
||||
*/
|
||||
public float getVisualTop() {
|
||||
return Float.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.views;
|
||||
|
||||
import com.android.launcher3.graphics.RotationMode;
|
||||
|
||||
/**
|
||||
* Indicates that a view can be transposed.
|
||||
*/
|
||||
public interface Transposable {
|
||||
|
||||
RotationMode getRotationMode();
|
||||
}
|
||||
@@ -98,6 +98,11 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
onWidgetsBound();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public WidgetsRecyclerView getRecyclerView() {
|
||||
return mRecyclerView;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<View, String> getAccessibilityTarget() {
|
||||
return Pair.create(mRecyclerView, getContext().getString(
|
||||
|
||||
@@ -19,11 +19,14 @@ package com.android.launcher3.widget;
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.BaseRecyclerView;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
@@ -155,18 +158,66 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch
|
||||
mScrollbar.isHitInParent(e.getX(), e.getY(), mFastScrollerOffset);
|
||||
}
|
||||
if (mTouchDownOnScroller) {
|
||||
return mScrollbar.handleTouchEvent(e, mFastScrollerOffset);
|
||||
final boolean result = mScrollbar.handleTouchEvent(e, mFastScrollerOffset);
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "onInterceptTouchEvent 1 " + result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "onInterceptTouchEvent 2 false");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "WidgetsRecyclerView.onTouchEvent");
|
||||
}
|
||||
if (mTouchDownOnScroller) {
|
||||
mScrollbar.handleTouchEvent(e, mFastScrollerOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { }
|
||||
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "onRequestDisallowInterceptTouchEvent "
|
||||
+ disallowIntercept);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
final boolean result = super.dispatchTouchEvent(ev);
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "WidgetsRecyclerView: state: "
|
||||
+ getScrollState()
|
||||
+ " can scroll: " + getLayoutManager().canScrollVertically()
|
||||
+ " result: " + result
|
||||
+ " layout suppressed: " + isLayoutSuppressed()
|
||||
+ " event: " + ev);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopNestedScroll() {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "stopNestedScroll");
|
||||
}
|
||||
super.stopNestedScroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayoutFrozen(boolean frozen) {
|
||||
if (frozen != isLayoutSuppressed()) {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "setLayoutFrozen " + frozen
|
||||
+ " @ " + android.util.Log.getStackTraceString(new Throwable()));
|
||||
}
|
||||
}
|
||||
super.setLayoutFrozen(frozen);
|
||||
}
|
||||
}
|
||||
@@ -162,6 +162,7 @@ public abstract class AbstractLauncherUiTest {
|
||||
mLauncher.enableDebugTracing();
|
||||
// Avoid double-reporting of Launcher crashes.
|
||||
mLauncher.setOnLauncherCrashed(() -> mLauncherPid = 0);
|
||||
mLauncher.disableSensorRotation();
|
||||
}
|
||||
|
||||
protected final LauncherActivityRule mActivityMonitor = new LauncherActivityRule();
|
||||
@@ -277,6 +278,7 @@ public abstract class AbstractLauncherUiTest {
|
||||
clearPackageData(mDevice.getLauncherPackageName());
|
||||
mLauncher.enableDebugTracing();
|
||||
mLauncherPid = mLauncher.getPid();
|
||||
mLauncher.disableSensorRotation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -275,8 +275,10 @@ public class BindWidgetTest extends AbstractLauncherUiTest {
|
||||
}
|
||||
|
||||
private void verifyPendingWidgetPresent() {
|
||||
final Widget widget = mLauncher.getWorkspace().tryGetPendingWidget(DEFAULT_UI_TIMEOUT);
|
||||
if (widget == null) mLauncher.dumpViewHierarchy(); // b/152645831
|
||||
assertTrue("Pending widget is not present",
|
||||
mLauncher.getWorkspace().tryGetPendingWidget(DEFAULT_UI_TIMEOUT) != null);
|
||||
widget != null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,7 +43,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
AllApps(LauncherInstrumentation launcher) {
|
||||
super(launcher);
|
||||
final UiObject2 allAppsContainer = verifyActiveContainer();
|
||||
mHeight = allAppsContainer.getVisibleBounds().height();
|
||||
mHeight = mLauncher.getVisibleBounds(allAppsContainer).height();
|
||||
final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer,
|
||||
"apps_list_view");
|
||||
// Wait for the recycler to populate.
|
||||
@@ -66,7 +66,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
LauncherInstrumentation.log("hasClickableIcon: icon not visible");
|
||||
return false;
|
||||
}
|
||||
final Rect iconBounds = icon.getVisibleBounds();
|
||||
final Rect iconBounds = mLauncher.getVisibleBounds(icon);
|
||||
LauncherInstrumentation.log("hasClickableIcon: icon bounds: " + iconBounds);
|
||||
if (iconBounds.height() < mIconHeight / 2) {
|
||||
LauncherInstrumentation.log("hasClickableIcon: icon has insufficient height");
|
||||
@@ -86,7 +86,7 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
|
||||
private boolean iconCenterInSearchBox(UiObject2 allAppsContainer, UiObject2 icon) {
|
||||
final Point iconCenter = icon.getVisibleCenter();
|
||||
return getSearchBox(allAppsContainer).getVisibleBounds().contains(
|
||||
return mLauncher.getVisibleBounds(getSearchBox(allAppsContainer)).contains(
|
||||
iconCenter.x, iconCenter.y);
|
||||
}
|
||||
|
||||
@@ -125,11 +125,11 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
mLauncher.getObjectsInContainer(allAppsContainer, "icon")
|
||||
.stream()
|
||||
.filter(icon ->
|
||||
icon.getVisibleBounds().bottom
|
||||
mLauncher.getVisibleBounds(icon).bottom
|
||||
<= displayBottom)
|
||||
.collect(Collectors.toList()),
|
||||
searchBox.getVisibleBounds().bottom
|
||||
- allAppsContainer.getVisibleBounds().top);
|
||||
mLauncher.getVisibleBounds(searchBox).bottom
|
||||
- mLauncher.getVisibleBounds(allAppsContainer).top);
|
||||
final int newScroll = getAllAppsScroll();
|
||||
mLauncher.assertTrue(
|
||||
"Scrolled in a wrong direction in AllApps: from " + scroll + " to "
|
||||
@@ -166,7 +166,8 @@ public class AllApps extends LauncherInstrumentation.VisibleContainer {
|
||||
final UiObject2 searchBox = getSearchBox(allAppsContainer);
|
||||
|
||||
int attempts = 0;
|
||||
final Rect margins = new Rect(0, searchBox.getVisibleBounds().bottom + 1, 0, 5);
|
||||
final Rect margins =
|
||||
new Rect(0, mLauncher.getVisibleBounds(searchBox).bottom + 1, 0, 5);
|
||||
|
||||
for (int scroll = getAllAppsScroll();
|
||||
scroll != 0;
|
||||
|
||||
@@ -117,8 +117,8 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
|
||||
// part) one in the center, and parts of its right and left siblings. Find the
|
||||
// main task view by its width.
|
||||
final UiObject2 widestTask = Collections.max(taskViews,
|
||||
(t1, t2) -> Integer.compare(t1.getVisibleBounds().width(),
|
||||
t2.getVisibleBounds().width()));
|
||||
(t1, t2) -> Integer.compare(mLauncher.getVisibleBounds(t1).width(),
|
||||
mLauncher.getVisibleBounds(t2).width()));
|
||||
|
||||
return new OverviewTask(mLauncher, widestTask, this);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ abstract class Launchable {
|
||||
|
||||
private Background launch(BySelector selector) {
|
||||
LauncherInstrumentation.log("Launchable.launch before click " +
|
||||
mObject.getVisibleCenter() + " in " + mObject.getVisibleBounds());
|
||||
mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
|
||||
|
||||
mLauncher.executeAndWaitForEvent(
|
||||
() -> mLauncher.clickLauncherObject(mObject),
|
||||
|
||||
@@ -977,7 +977,7 @@ public final class LauncherInstrumentation {
|
||||
|
||||
int getBottomGestureMarginInContainer(UiObject2 container) {
|
||||
final int bottomGestureStartOnScreen = getRealDisplaySize().y - getBottomGestureSize();
|
||||
return container.getVisibleBounds().bottom - bottomGestureStartOnScreen;
|
||||
return getVisibleBounds(container).bottom - bottomGestureStartOnScreen;
|
||||
}
|
||||
|
||||
void clickLauncherObject(UiObject2 object) {
|
||||
@@ -995,10 +995,10 @@ public final class LauncherInstrumentation {
|
||||
Collection<UiObject2> items,
|
||||
int topPaddingInContainer) {
|
||||
final UiObject2 lowestItem = Collections.max(items, (i1, i2) ->
|
||||
Integer.compare(i1.getVisibleBounds().top, i2.getVisibleBounds().top));
|
||||
Integer.compare(getVisibleBounds(i1).top, getVisibleBounds(i2).top));
|
||||
|
||||
final int itemRowCurrentTopOnScreen = lowestItem.getVisibleBounds().top;
|
||||
final Rect containerRect = container.getVisibleBounds();
|
||||
final int itemRowCurrentTopOnScreen = getVisibleBounds(lowestItem).top;
|
||||
final Rect containerRect = getVisibleBounds(container);
|
||||
final int itemRowNewTopOnScreen = containerRect.top + topPaddingInContainer;
|
||||
final int distance = itemRowCurrentTopOnScreen - itemRowNewTopOnScreen + getTouchSlop();
|
||||
|
||||
@@ -1017,7 +1017,7 @@ public final class LauncherInstrumentation {
|
||||
|
||||
void scroll(
|
||||
UiObject2 container, Direction direction, Rect margins, int steps, boolean slowDown) {
|
||||
final Rect rect = container.getVisibleBounds();
|
||||
final Rect rect = getVisibleBounds(container);
|
||||
if (margins != null) {
|
||||
rect.left += margins.left;
|
||||
rect.top += margins.top;
|
||||
@@ -1263,6 +1263,10 @@ public final class LauncherInstrumentation {
|
||||
TestProtocol.TEST_INFO_RESPONSE_FIELD);
|
||||
}
|
||||
|
||||
public void disableSensorRotation() {
|
||||
getTestInfo(TestProtocol.REQUEST_MOCK_SENSOR_ROTATION);
|
||||
}
|
||||
|
||||
public void disableDebugTracing() {
|
||||
getTestInfo(TestProtocol.REQUEST_DISABLE_DEBUG_TRACING);
|
||||
}
|
||||
@@ -1330,4 +1334,13 @@ public final class LauncherInstrumentation {
|
||||
void expectEvent(String sequence, Pattern expected) {
|
||||
if (sCheckingEvents) sEventChecker.expectPattern(sequence, expected);
|
||||
}
|
||||
|
||||
Rect getVisibleBounds(UiObject2 object) {
|
||||
try {
|
||||
return object.getVisibleBounds();
|
||||
} catch (Throwable t) {
|
||||
fail(t.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class OptionsPopupMenuItem {
|
||||
public void launch(@NonNull String expectedPackageName) {
|
||||
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
|
||||
LauncherInstrumentation.log("OptionsPopupMenuItem before click "
|
||||
+ mObject.getVisibleCenter() + " in " + mObject.getVisibleBounds());
|
||||
+ mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
|
||||
mLauncher.clickLauncherObject(mObject);
|
||||
if (!Build.MODEL.contains("Cuttlefish") ||
|
||||
Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q &&
|
||||
|
||||
@@ -56,7 +56,7 @@ public final class OverviewTask {
|
||||
"want to dismiss a task")) {
|
||||
verifyActiveContainer();
|
||||
// Dismiss the task via flinging it up.
|
||||
final Rect taskBounds = mTask.getVisibleBounds();
|
||||
final Rect taskBounds = mLauncher.getVisibleBounds(mTask);
|
||||
final int centerX = taskBounds.centerX();
|
||||
final int centerY = taskBounds.centerY();
|
||||
mLauncher.linearGesture(centerX, centerY, centerX, 0, 10, false,
|
||||
|
||||
@@ -73,7 +73,7 @@ public final class Widgets extends LauncherInstrumentation.VisibleContainer {
|
||||
mLauncher.scroll(
|
||||
widgetsContainer,
|
||||
Direction.UP,
|
||||
new Rect(0, 0, widgetsContainer.getVisibleBounds().width(), 0),
|
||||
new Rect(0, 0, mLauncher.getVisibleBounds(widgetsContainer).width(), 0),
|
||||
FLING_STEPS, false);
|
||||
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("flung back")) {
|
||||
verifyActiveContainer();
|
||||
@@ -111,19 +111,19 @@ public final class Widgets extends LauncherInstrumentation.VisibleContainer {
|
||||
|
||||
int maxWidth = 0;
|
||||
for (UiObject2 sibling : widget.getParent().getChildren()) {
|
||||
maxWidth = Math.max(sibling.getVisibleBounds().width(), maxWidth);
|
||||
maxWidth = Math.max(mLauncher.getVisibleBounds(sibling).width(), maxWidth);
|
||||
}
|
||||
|
||||
int visibleDelta = maxWidth - widget.getVisibleBounds().width();
|
||||
int visibleDelta = maxWidth - mLauncher.getVisibleBounds(widget).width();
|
||||
if (visibleDelta > 0) {
|
||||
Rect parentBounds = cell.getVisibleBounds();
|
||||
Rect parentBounds = mLauncher.getVisibleBounds(cell);
|
||||
mLauncher.linearGesture(parentBounds.centerX() + visibleDelta
|
||||
+ mLauncher.getTouchSlop(),
|
||||
parentBounds.centerY(), parentBounds.centerX(),
|
||||
parentBounds.centerY(), 10, true, GestureScope.INSIDE);
|
||||
}
|
||||
|
||||
if (widget.getVisibleBounds().bottom
|
||||
if (mLauncher.getVisibleBounds(widget).bottom
|
||||
<= displaySize.y - mLauncher.getBottomGestureSize()) {
|
||||
return new Widget(mLauncher, widget);
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ public final class Workspace extends Home {
|
||||
mLauncher,
|
||||
getHotseatAppIcon("Chrome"),
|
||||
new Point(mLauncher.getDevice().getDisplayWidth(),
|
||||
workspace.getVisibleBounds().centerY()),
|
||||
mLauncher.getVisibleBounds(workspace).centerY()),
|
||||
"deep_shortcuts_container",
|
||||
false,
|
||||
() -> mLauncher.expectEvent(
|
||||
|
||||
Reference in New Issue
Block a user