Snap for 10188272 from 883871e280 to udc-release
Change-Id: I1964b60669656606eab0bc72c6610a2c6a9a9348
This commit is contained in:
@@ -1702,6 +1702,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
QuickStepContract.getWindowCornerRadius(mLauncher),
|
||||
false /* fromPredictiveBack */);
|
||||
|
||||
TaskViewUtils.createSplitAuxiliarySurfacesAnimator(nonAppTargets, false, null);
|
||||
mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL);
|
||||
result.setAnimation(pair.second, mLauncher);
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.quickstep.util.BorderAnimator;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
@@ -43,7 +45,9 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public class KeyboardQuickSwitchTaskView extends ConstraintLayout {
|
||||
|
||||
@NonNull private final BorderAnimator mBorderAnimator;
|
||||
@ColorInt private final int mBorderColor;
|
||||
|
||||
@Nullable private BorderAnimator mBorderAnimator;
|
||||
|
||||
@Nullable private ImageView mThumbnailView1;
|
||||
@Nullable private ImageView mThumbnailView2;
|
||||
@@ -74,29 +78,9 @@ public class KeyboardQuickSwitchTaskView extends ConstraintLayout {
|
||||
attrs, R.styleable.TaskView, defStyleAttr, defStyleRes);
|
||||
|
||||
setWillNotDraw(false);
|
||||
Resources resources = context.getResources();
|
||||
mBorderAnimator = new BorderAnimator(
|
||||
/* borderBoundsBuilder= */ bounds -> bounds.set(0, 0, getWidth(), getHeight()),
|
||||
/* borderWidthPx= */ resources.getDimensionPixelSize(
|
||||
R.dimen.keyboard_quick_switch_border_width),
|
||||
/* borderRadiusPx= */ resources.getDimensionPixelSize(
|
||||
R.dimen.keyboard_quick_switch_task_view_radius),
|
||||
/* borderColor= */ ta.getColor(
|
||||
R.styleable.TaskView_borderColor, DEFAULT_BORDER_COLOR),
|
||||
/* invalidateViewCallback= */ KeyboardQuickSwitchTaskView.this::invalidate,
|
||||
/* viewScaleTargetProvider= */ new BorderAnimator.ViewScaleTargetProvider() {
|
||||
@NonNull
|
||||
@Override
|
||||
public View getContainerView() {
|
||||
return KeyboardQuickSwitchTaskView.this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getContentView() {
|
||||
return mContent;
|
||||
}
|
||||
});
|
||||
mBorderColor = ta.getColor(
|
||||
R.styleable.TaskView_borderColor, DEFAULT_BORDER_COLOR);
|
||||
ta.recycle();
|
||||
}
|
||||
|
||||
@@ -108,17 +92,34 @@ public class KeyboardQuickSwitchTaskView extends ConstraintLayout {
|
||||
mIcon1 = findViewById(R.id.icon1);
|
||||
mIcon2 = findViewById(R.id.icon2);
|
||||
mContent = findViewById(R.id.content);
|
||||
|
||||
Resources resources = mContext.getResources();
|
||||
|
||||
Preconditions.assertNotNull(mContent);
|
||||
mBorderAnimator = new BorderAnimator(
|
||||
/* borderRadiusPx= */ resources.getDimensionPixelSize(
|
||||
R.dimen.keyboard_quick_switch_task_view_radius),
|
||||
/* borderColor= */ mBorderColor,
|
||||
/* borderAnimationParams= */ new BorderAnimator.ScalingParams(
|
||||
/* borderWidthPx= */ resources.getDimensionPixelSize(
|
||||
R.dimen.keyboard_quick_switch_border_width),
|
||||
/* boundsBuilder= */ bounds -> bounds.set(
|
||||
0, 0, getWidth(), getHeight()),
|
||||
/* targetView= */ this,
|
||||
/* contentView= */ mContent));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Nullable
|
||||
protected Animator getFocusAnimator(boolean focused) {
|
||||
return mBorderAnimator.buildAnimator(focused);
|
||||
return mBorderAnimator == null ? null : mBorderAnimator.buildAnimator(focused);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
super.draw(canvas);
|
||||
mBorderAnimator.drawBorder(canvas);
|
||||
if (mBorderAnimator != null) {
|
||||
mBorderAnimator.drawBorder(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setThumbnails(
|
||||
|
||||
@@ -153,6 +153,11 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im
|
||||
return false;
|
||||
}
|
||||
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onTaskbarItemLongClick");
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.TWO_TASKBAR_LONG_CLICKS,
|
||||
"TaskbarDragController.startDragOnLongClick",
|
||||
new Throwable());
|
||||
}
|
||||
BubbleTextView btv = (BubbleTextView) view;
|
||||
mActivity.onDragStart();
|
||||
btv.post(() -> {
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.annotation.ColorInt;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
@@ -37,8 +38,8 @@ import com.android.launcher3.anim.Interpolators;
|
||||
* <p>
|
||||
* To use this class:
|
||||
* 1. Create an instance in the target view. NOTE: The border will animate outwards from the
|
||||
* provided border bounds. If the border will not be visible outside of those bounds, then a
|
||||
* {@link ViewScaleTargetProvider} must be provided in the constructor.
|
||||
* provided border bounds. See {@link SimpleParams} and {@link ScalingParams} to determine
|
||||
* which would be best for your target view.
|
||||
* 2. Override the target view's {@link android.view.View#draw(Canvas)} method and call
|
||||
* {@link BorderAnimator#drawBorder(Canvas)} after {@code super.draw(canvas)}.
|
||||
* 3. Call {@link BorderAnimator#buildAnimator(boolean)} and start the animation or call
|
||||
@@ -46,7 +47,7 @@ import com.android.launcher3.anim.Interpolators;
|
||||
*/
|
||||
public final class BorderAnimator {
|
||||
|
||||
public static final int DEFAULT_BORDER_COLOR = 0xffffffff;
|
||||
public static final int DEFAULT_BORDER_COLOR = Color.WHITE;
|
||||
|
||||
private static final long DEFAULT_APPEARANCE_ANIMATION_DURATION_MS = 300;
|
||||
private static final long DEFAULT_DISAPPEARANCE_ANIMATION_DURATION_MS = 133;
|
||||
@@ -54,68 +55,44 @@ public final class BorderAnimator {
|
||||
|
||||
@NonNull private final AnimatedFloat mBorderAnimationProgress = new AnimatedFloat(
|
||||
this::updateOutline);
|
||||
@NonNull private final Rect mBorderBounds = new Rect();
|
||||
@NonNull private final BorderBoundsBuilder mBorderBoundsBuilder;
|
||||
@Px private final int mBorderWidthPx;
|
||||
@Px private final int mBorderRadiusPx;
|
||||
@NonNull private final Runnable mInvalidateViewCallback;
|
||||
@Nullable private final ViewScaleTargetProvider mViewScaleTargetProvider;
|
||||
@NonNull private final BorderAnimationParams mBorderAnimationParams;
|
||||
private final long mAppearanceDurationMs;
|
||||
private final long mDisappearanceDurationMs;
|
||||
@NonNull private final Interpolator mInterpolator;
|
||||
@NonNull private final Paint mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
private float mAlignmentAdjustment;
|
||||
|
||||
@Nullable private Animator mRunningBorderAnimation;
|
||||
|
||||
public BorderAnimator(
|
||||
@NonNull BorderBoundsBuilder borderBoundsBuilder,
|
||||
int borderWidthPx,
|
||||
int borderRadiusPx,
|
||||
@Px int borderRadiusPx,
|
||||
@ColorInt int borderColor,
|
||||
@NonNull Runnable invalidateViewCallback) {
|
||||
this(borderBoundsBuilder,
|
||||
borderWidthPx,
|
||||
borderRadiusPx,
|
||||
@NonNull BorderAnimationParams borderAnimationParams) {
|
||||
this(borderRadiusPx,
|
||||
borderColor,
|
||||
invalidateViewCallback,
|
||||
/* viewScaleTargetProvider= */ null);
|
||||
}
|
||||
|
||||
public BorderAnimator(
|
||||
@NonNull BorderBoundsBuilder borderBoundsBuilder,
|
||||
int borderWidthPx,
|
||||
int borderRadiusPx,
|
||||
@ColorInt int borderColor,
|
||||
@NonNull Runnable invalidateViewCallback,
|
||||
@Nullable ViewScaleTargetProvider viewScaleTargetProvider) {
|
||||
this(borderBoundsBuilder,
|
||||
borderWidthPx,
|
||||
borderRadiusPx,
|
||||
borderColor,
|
||||
invalidateViewCallback,
|
||||
viewScaleTargetProvider,
|
||||
borderAnimationParams,
|
||||
DEFAULT_APPEARANCE_ANIMATION_DURATION_MS,
|
||||
DEFAULT_DISAPPEARANCE_ANIMATION_DURATION_MS,
|
||||
DEFAULT_INTERPOLATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param borderRadiusPx the radius of the border's corners, in pixels
|
||||
* @param borderColor the border's color
|
||||
* @param borderAnimationParams params for handling different target view layout situation.
|
||||
* @param appearanceDurationMs appearance animation duration, in milliseconds
|
||||
* @param disappearanceDurationMs disappearance animation duration, in milliseconds
|
||||
* @param interpolator animation interpolator
|
||||
*/
|
||||
public BorderAnimator(
|
||||
@NonNull BorderBoundsBuilder borderBoundsBuilder,
|
||||
int borderWidthPx,
|
||||
int borderRadiusPx,
|
||||
@Px int borderRadiusPx,
|
||||
@ColorInt int borderColor,
|
||||
@NonNull Runnable invalidateViewCallback,
|
||||
@Nullable ViewScaleTargetProvider viewScaleTargetProvider,
|
||||
@NonNull BorderAnimationParams borderAnimationParams,
|
||||
long appearanceDurationMs,
|
||||
long disappearanceDurationMs,
|
||||
@NonNull Interpolator interpolator) {
|
||||
mBorderBoundsBuilder = borderBoundsBuilder;
|
||||
mBorderWidthPx = borderWidthPx;
|
||||
mBorderRadiusPx = borderRadiusPx;
|
||||
mInvalidateViewCallback = invalidateViewCallback;
|
||||
mViewScaleTargetProvider = viewScaleTargetProvider;
|
||||
mBorderAnimationParams = borderAnimationParams;
|
||||
mAppearanceDurationMs = appearanceDurationMs;
|
||||
mDisappearanceDurationMs = disappearanceDurationMs;
|
||||
mInterpolator = interpolator;
|
||||
@@ -128,15 +105,11 @@ public final class BorderAnimator {
|
||||
private void updateOutline() {
|
||||
float interpolatedProgress = mInterpolator.getInterpolation(
|
||||
mBorderAnimationProgress.value);
|
||||
float borderWidth = mBorderWidthPx * interpolatedProgress;
|
||||
// Outset the border by half the width to create an outwards-growth animation
|
||||
mAlignmentAdjustment = (-borderWidth / 2f)
|
||||
// Inset the border if we are scaling the container up
|
||||
+ (mViewScaleTargetProvider == null ? 0 : mBorderWidthPx);
|
||||
|
||||
mBorderAnimationParams.setProgress(interpolatedProgress);
|
||||
mBorderPaint.setAlpha(Math.round(255 * interpolatedProgress));
|
||||
mBorderPaint.setStrokeWidth(borderWidth);
|
||||
mInvalidateViewCallback.run();
|
||||
mBorderPaint.setStrokeWidth(mBorderAnimationParams.getBorderWidth());
|
||||
mBorderAnimationParams.mTargetView.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,16 +119,14 @@ public final class BorderAnimator {
|
||||
* calling super.
|
||||
*/
|
||||
public void drawBorder(Canvas canvas) {
|
||||
// Increase the radius if we are scaling the container up
|
||||
float radiusAdjustment = mViewScaleTargetProvider == null
|
||||
? -mAlignmentAdjustment : mAlignmentAdjustment;
|
||||
float alignmentAdjustment = mBorderAnimationParams.getAlignmentAdjustment();
|
||||
canvas.drawRoundRect(
|
||||
/* left= */ mBorderBounds.left + mAlignmentAdjustment,
|
||||
/* top= */ mBorderBounds.top + mAlignmentAdjustment,
|
||||
/* right= */ mBorderBounds.right - mAlignmentAdjustment,
|
||||
/* bottom= */ mBorderBounds.bottom - mAlignmentAdjustment,
|
||||
/* rx= */ mBorderRadiusPx + radiusAdjustment,
|
||||
/* ry= */ mBorderRadiusPx + radiusAdjustment,
|
||||
/* left= */ mBorderAnimationParams.mBorderBounds.left + alignmentAdjustment,
|
||||
/* top= */ mBorderAnimationParams.mBorderBounds.top + alignmentAdjustment,
|
||||
/* right= */ mBorderAnimationParams.mBorderBounds.right - alignmentAdjustment,
|
||||
/* bottom= */ mBorderAnimationParams.mBorderBounds.bottom - alignmentAdjustment,
|
||||
/* rx= */ mBorderRadiusPx + mBorderAnimationParams.getRadiusAdjustment(),
|
||||
/* ry= */ mBorderRadiusPx + mBorderAnimationParams.getRadiusAdjustment(),
|
||||
/* paint= */ mBorderPaint);
|
||||
}
|
||||
|
||||
@@ -164,7 +135,6 @@ public final class BorderAnimator {
|
||||
*/
|
||||
@NonNull
|
||||
public Animator buildAnimator(boolean isAppearing) {
|
||||
mBorderBoundsBuilder.updateBorderBounds(mBorderBounds);
|
||||
mRunningBorderAnimation = mBorderAnimationProgress.animateToValue(isAppearing ? 1f : 0f);
|
||||
mRunningBorderAnimation.setDuration(
|
||||
isAppearing ? mAppearanceDurationMs : mDisappearanceDurationMs);
|
||||
@@ -172,7 +142,7 @@ public final class BorderAnimator {
|
||||
mRunningBorderAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
setViewScales();
|
||||
mBorderAnimationParams.onShowBorder();
|
||||
}
|
||||
});
|
||||
mRunningBorderAnimation.addListener(
|
||||
@@ -181,7 +151,7 @@ public final class BorderAnimator {
|
||||
if (isAppearing) {
|
||||
return;
|
||||
}
|
||||
resetViewScales();
|
||||
mBorderAnimationParams.onHideBorder();
|
||||
}));
|
||||
|
||||
return mRunningBorderAnimation;
|
||||
@@ -196,56 +166,15 @@ public final class BorderAnimator {
|
||||
if (mRunningBorderAnimation != null) {
|
||||
mRunningBorderAnimation.end();
|
||||
}
|
||||
mBorderBoundsBuilder.updateBorderBounds(mBorderBounds);
|
||||
if (visible) {
|
||||
setViewScales();
|
||||
mBorderAnimationParams.onShowBorder();
|
||||
}
|
||||
mBorderAnimationProgress.updateValue(visible ? 1f : 0f);
|
||||
if (!visible) {
|
||||
resetViewScales();
|
||||
mBorderAnimationParams.onHideBorder();
|
||||
}
|
||||
}
|
||||
|
||||
private void setViewScales() {
|
||||
if (mViewScaleTargetProvider == null) {
|
||||
return;
|
||||
}
|
||||
View container = mViewScaleTargetProvider.getContainerView();
|
||||
float width = container.getWidth();
|
||||
float height = container.getHeight();
|
||||
// scale up just enough to make room for the border
|
||||
float scaleX = 1f + ((2 * mBorderWidthPx) / width);
|
||||
float scaleY = 1f + ((2 * mBorderWidthPx) / height);
|
||||
|
||||
container.setPivotX(width / 2);
|
||||
container.setPivotY(height / 2);
|
||||
container.setScaleX(scaleX);
|
||||
container.setScaleY(scaleY);
|
||||
|
||||
View contentView = mViewScaleTargetProvider.getContentView();
|
||||
contentView.setPivotX(contentView.getWidth() / 2f);
|
||||
contentView.setPivotY(contentView.getHeight() / 2f);
|
||||
contentView.setScaleX(1f / scaleX);
|
||||
contentView.setScaleY(1f / scaleY);
|
||||
}
|
||||
|
||||
private void resetViewScales() {
|
||||
if (mViewScaleTargetProvider == null) {
|
||||
return;
|
||||
}
|
||||
View container = mViewScaleTargetProvider.getContainerView();
|
||||
container.setPivotX(container.getWidth());
|
||||
container.setPivotY(container.getHeight());
|
||||
container.setScaleX(1f);
|
||||
container.setScaleY(1f);
|
||||
|
||||
View contentView = mViewScaleTargetProvider.getContentView();
|
||||
contentView.setPivotX(contentView.getWidth() / 2f);
|
||||
contentView.setPivotY(contentView.getHeight() / 2f);
|
||||
contentView.setScaleX(1f);
|
||||
contentView.setScaleY(1f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to update the border bounds when building this animation.
|
||||
*/
|
||||
@@ -258,23 +187,166 @@ public final class BorderAnimator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provider for scaling target views for the beginning and end of this animation.
|
||||
* Params for handling different target view layout situation.
|
||||
*/
|
||||
public interface ViewScaleTargetProvider {
|
||||
private abstract static class BorderAnimationParams {
|
||||
|
||||
@NonNull private final Rect mBorderBounds = new Rect();
|
||||
@NonNull private final BorderBoundsBuilder mBoundsBuilder;
|
||||
|
||||
@NonNull final View mTargetView;
|
||||
@Px final int mBorderWidthPx;
|
||||
|
||||
private float mAnimationProgress = 0f;
|
||||
@Nullable private View.OnLayoutChangeListener mLayoutChangeListener;
|
||||
|
||||
/**
|
||||
* Returns the content view's container. This view will be scaled up to make room for the
|
||||
* border.
|
||||
* @param borderWidthPx the width of the border, in pixels
|
||||
* @param boundsBuilder callback to update the border bounds
|
||||
* @param targetView the view that will be drawing the border
|
||||
*/
|
||||
@NonNull
|
||||
View getContainerView();
|
||||
private BorderAnimationParams(
|
||||
@Px int borderWidthPx,
|
||||
@NonNull BorderBoundsBuilder boundsBuilder,
|
||||
@NonNull View targetView) {
|
||||
mBorderWidthPx = borderWidthPx;
|
||||
mBoundsBuilder = boundsBuilder;
|
||||
mTargetView = targetView;
|
||||
}
|
||||
|
||||
private void setProgress(float progress) {
|
||||
mAnimationProgress = progress;
|
||||
}
|
||||
|
||||
private float getBorderWidth() {
|
||||
return mBorderWidthPx * mAnimationProgress;
|
||||
}
|
||||
|
||||
float getAlignmentAdjustment() {
|
||||
// Outset the border by half the width to create an outwards-growth animation
|
||||
return (-getBorderWidth() / 2f) + getAlignmentAdjustmentInset();
|
||||
}
|
||||
|
||||
|
||||
void onShowBorder() {
|
||||
if (mLayoutChangeListener == null) {
|
||||
mLayoutChangeListener =
|
||||
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
|
||||
onShowBorder();
|
||||
mTargetView.invalidate();
|
||||
};
|
||||
mTargetView.addOnLayoutChangeListener(mLayoutChangeListener);
|
||||
}
|
||||
mBoundsBuilder.updateBorderBounds(mBorderBounds);
|
||||
}
|
||||
|
||||
void onHideBorder() {
|
||||
if (mLayoutChangeListener != null) {
|
||||
mTargetView.removeOnLayoutChangeListener(mLayoutChangeListener);
|
||||
mLayoutChangeListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
abstract int getAlignmentAdjustmentInset();
|
||||
|
||||
abstract float getRadiusAdjustment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an instance of this {@link BorderAnimationParams} if the border can be drawn outside the
|
||||
* target view's bounds without any additional logic.
|
||||
*/
|
||||
public static final class SimpleParams extends BorderAnimationParams {
|
||||
|
||||
public SimpleParams(
|
||||
@Px int borderWidthPx,
|
||||
@NonNull BorderBoundsBuilder boundsBuilder,
|
||||
@NonNull View targetView) {
|
||||
super(borderWidthPx, boundsBuilder, targetView);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getAlignmentAdjustmentInset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
float getRadiusAdjustment() {
|
||||
return -getAlignmentAdjustment();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an instance of this {@link BorderAnimationParams} if the border would other be clipped by
|
||||
* the target view's bound.
|
||||
* <p>
|
||||
* Note: using these params will set the scales and pivots of the
|
||||
* container and content views, however will only reset the scales back to 1.
|
||||
*/
|
||||
public static final class ScalingParams extends BorderAnimationParams {
|
||||
|
||||
@NonNull private final View mContentView;
|
||||
|
||||
/**
|
||||
* Returns the content view. This view will be scaled down reciprocally to the container's
|
||||
* up-scaling to maintain its original size. This should be the view containing all of the
|
||||
* content being surrounded by the border.
|
||||
* @param targetView the view that will be drawing the border. this view will be scaled up
|
||||
* to make room for the border
|
||||
* @param contentView the view around which the border will be drawn. this view will be
|
||||
* scaled down reciprocally to keep its original size and location.
|
||||
*/
|
||||
@NonNull
|
||||
View getContentView();
|
||||
public ScalingParams(
|
||||
@Px int borderWidthPx,
|
||||
@NonNull BorderBoundsBuilder boundsBuilder,
|
||||
@NonNull View targetView,
|
||||
@NonNull View contentView) {
|
||||
super(borderWidthPx, boundsBuilder, targetView);
|
||||
mContentView = contentView;
|
||||
}
|
||||
|
||||
@Override
|
||||
void onShowBorder() {
|
||||
super.onShowBorder();
|
||||
float width = mTargetView.getWidth();
|
||||
float height = mTargetView.getHeight();
|
||||
// Scale up just enough to make room for the border. Fail fast and fix the scaling
|
||||
// onLayout.
|
||||
float scaleX = width == 0 ? 1f : 1f + ((2 * mBorderWidthPx) / width);
|
||||
float scaleY = height == 0 ? 1f : 1f + ((2 * mBorderWidthPx) / height);
|
||||
|
||||
mTargetView.setPivotX(width / 2);
|
||||
mTargetView.setPivotY(height / 2);
|
||||
mTargetView.setScaleX(scaleX);
|
||||
mTargetView.setScaleY(scaleY);
|
||||
|
||||
mContentView.setPivotX(mContentView.getWidth() / 2f);
|
||||
mContentView.setPivotY(mContentView.getHeight() / 2f);
|
||||
mContentView.setScaleX(1f / scaleX);
|
||||
mContentView.setScaleY(1f / scaleY);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onHideBorder() {
|
||||
super.onHideBorder();
|
||||
mTargetView.setPivotX(mTargetView.getWidth());
|
||||
mTargetView.setPivotY(mTargetView.getHeight());
|
||||
mTargetView.setScaleX(1f);
|
||||
mTargetView.setScaleY(1f);
|
||||
|
||||
mContentView.setPivotX(mContentView.getWidth() / 2f);
|
||||
mContentView.setPivotY(mContentView.getHeight() / 2f);
|
||||
mContentView.setScaleX(1f);
|
||||
mContentView.setScaleY(1f);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getAlignmentAdjustmentInset() {
|
||||
// Inset the border since we are scaling the container up
|
||||
return mBorderWidthPx;
|
||||
}
|
||||
|
||||
@Override
|
||||
float getRadiusAdjustment() {
|
||||
// Increase the radius since we are scaling the container up
|
||||
return getAlignmentAdjustment();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,13 +445,14 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
mBorderAnimator = !keyboardFocusHighlightEnabled
|
||||
? null
|
||||
: new BorderAnimator(
|
||||
/* borderBoundsBuilder= */ this::updateBorderBounds,
|
||||
/* borderWidthPx= */ context.getResources().getDimensionPixelSize(
|
||||
R.dimen.keyboard_quick_switch_border_width),
|
||||
/* borderRadiusPx= */ (int) mCurrentFullscreenParams.mCornerRadius,
|
||||
/* borderColor= */ ta.getColor(
|
||||
R.styleable.TaskView_borderColor, DEFAULT_BORDER_COLOR),
|
||||
/* invalidateViewCallback= */ TaskView.this::invalidate);
|
||||
/* borderAnimationParams= */ new BorderAnimator.SimpleParams(
|
||||
/* borderWidthPx= */ context.getResources().getDimensionPixelSize(
|
||||
R.dimen.keyboard_quick_switch_border_width),
|
||||
/* boundsBuilder= */ this::updateBorderBounds,
|
||||
/* targetView= */ this));
|
||||
ta.recycle();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.android.launcher3.util.RaceConditionReproducer;
|
||||
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@@ -56,6 +57,7 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
|
||||
eventProcessor.finishIteration();
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
@NavigationModeSwitch
|
||||
public void testStressPressHome() {
|
||||
@@ -68,6 +70,7 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
@NavigationModeSwitch
|
||||
public void testStressSwipeToOverview() {
|
||||
|
||||
@@ -427,6 +427,55 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest {
|
||||
0, getTaskCount(launcher)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@PortraitLandscape
|
||||
public void testOverviewDeadzones() throws Exception {
|
||||
startTestAppsWithCheck();
|
||||
|
||||
Overview overview = mLauncher.goHome().switchToOverview();
|
||||
assertTrue("Launcher internal state should be Overview",
|
||||
isInState(() -> LauncherState.OVERVIEW));
|
||||
executeOnLauncher(
|
||||
launcher -> assertTrue("Should have at least 3 tasks",
|
||||
getTaskCount(launcher) >= 3));
|
||||
|
||||
// It should not dismiss overview when tapping between tasks
|
||||
overview.touchBetweenTasks();
|
||||
overview = mLauncher.getOverview();
|
||||
assertTrue("Launcher internal state should be Overview",
|
||||
isInState(() -> LauncherState.OVERVIEW));
|
||||
|
||||
// Dismiss when tapping to the right of the focused task
|
||||
overview.touchOutsideFirstTask();
|
||||
assertTrue("Launcher internal state should be Home",
|
||||
isInState(() -> LauncherState.NORMAL));
|
||||
}
|
||||
|
||||
@Test
|
||||
@PortraitLandscape
|
||||
public void testTaskbarDeadzonesForTablet() throws Exception {
|
||||
assumeTrue(mLauncher.isTablet());
|
||||
|
||||
startTestAppsWithCheck();
|
||||
|
||||
Overview overview = mLauncher.goHome().switchToOverview();
|
||||
assertTrue("Launcher internal state should be Overview",
|
||||
isInState(() -> LauncherState.OVERVIEW));
|
||||
executeOnLauncher(
|
||||
launcher -> assertTrue("Should have at least 3 tasks",
|
||||
getTaskCount(launcher) >= 3));
|
||||
|
||||
// On persistent taskbar, it should not dismiss when tapping the taskbar
|
||||
overview.touchTaskbarBottomCorner(/* tapRight= */ false);
|
||||
assertTrue("Launcher internal state should be Overview",
|
||||
isInState(() -> LauncherState.OVERVIEW));
|
||||
|
||||
// On persistent taskbar, it should not dismiss when tapping the taskbar
|
||||
overview.touchTaskbarBottomCorner(/* tapRight= */ true);
|
||||
assertTrue("Launcher internal state should be Overview",
|
||||
isInState(() -> LauncherState.OVERVIEW));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ScreenRecord // b/242163205
|
||||
public void testDisableRotationCheckForPhone() throws Exception {
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
<com.android.launcher3.views.RecyclerViewFastScroller
|
||||
android:id="@+id/fast_scroller"
|
||||
android:layout_width="@dimen/fastscroll_width"
|
||||
android:elevation="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentTop="true"
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/collapse_handle"
|
||||
android:paddingBottom="0dp"
|
||||
android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
|
||||
android:clipToOutline="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
@@ -67,6 +66,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="0.1dp"
|
||||
android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
|
||||
android:background="?attr/widgetPickerPrimarySurfaceColor"
|
||||
android:paddingBottom="8dp"
|
||||
launcher:layout_sticky="true">
|
||||
@@ -78,6 +78,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
|
||||
android:background="@drawable/widgets_surface_background"
|
||||
android:paddingVertical="@dimen/recommended_widgets_table_vertical_padding"
|
||||
android:visibility="gone" />
|
||||
@@ -89,6 +90,7 @@
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="8dp"
|
||||
android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
|
||||
android:background="?attr/widgetPickerPrimarySurfaceColor"
|
||||
style="@style/TextHeadline"
|
||||
launcher:layout_sticky="true">
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/widgets_two_pane_sheet_paged_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="start"
|
||||
android:paddingHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
|
||||
android:layout_gravity="start"
|
||||
android:layout_alignParentStart="true">
|
||||
<com.android.launcher3.widget.picker.WidgetPagedView
|
||||
@@ -29,7 +29,6 @@
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="afterDescendants"
|
||||
android:paddingHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
|
||||
launcher:pageIndicator="@+id/tabs" >
|
||||
|
||||
<com.android.launcher3.widget.picker.WidgetsRecyclerView
|
||||
@@ -62,7 +61,6 @@
|
||||
android:clipToPadding="false"
|
||||
android:elevation="0.1dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
|
||||
launcher:layout_sticky="true">
|
||||
|
||||
<include layout="@layout/widgets_search_bar" />
|
||||
@@ -73,7 +71,6 @@
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/suggestions_header"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
|
||||
android:orientation="horizontal"
|
||||
android:background="?attr/widgetPickerPrimarySurfaceColor"
|
||||
launcher:layout_sticky="true">
|
||||
@@ -86,7 +83,6 @@
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="horizontal"
|
||||
android:paddingVertical="8dp"
|
||||
android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin_two_pane"
|
||||
android:background="?attr/widgetPickerPrimarySurfaceColor"
|
||||
style="@style/TextHeadline"
|
||||
launcher:layout_sticky="true">
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/widgets_two_pane_sheet_recyclerview"
|
||||
|
||||
@@ -60,4 +60,9 @@ public class LogConfig {
|
||||
* When turned on, we enable Gms Play related logging.
|
||||
*/
|
||||
public static final String GMS_PLAY = "GmsPlay";
|
||||
|
||||
/**
|
||||
* When turned on, we enable AGA related session summary logging.
|
||||
*/
|
||||
public static final String AGA_SESSION_SUMMARY_LOG = "AGASessionSummaryLog";
|
||||
}
|
||||
|
||||
@@ -154,6 +154,7 @@ public final class TestProtocol {
|
||||
public static final String PERMANENT_DIAG_TAG = "TaplTarget";
|
||||
public static final String VIEW_AND_ACTIVITY_LEAKS = "b/260260325";
|
||||
public static final String WORK_TAB_MISSING = "b/243688989";
|
||||
public static final String TWO_TASKBAR_LONG_CLICKS = "b/262282528";
|
||||
|
||||
public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
|
||||
public static final String REQUEST_STOP_EMULATE_DISPLAY = "stop-emulate-display";
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.android.launcher3.util.rule;
|
||||
|
||||
import static androidx.test.InstrumentationRegistry.getInstrumentation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.FileUtils;
|
||||
import android.os.ParcelFileDescriptor.AutoCloseInputStream;
|
||||
import android.util.Log;
|
||||
@@ -54,27 +53,9 @@ public class FailureWatcher extends TestWatcher {
|
||||
return new Statement() {
|
||||
@Override
|
||||
public void evaluate() throws Throwable {
|
||||
boolean success = false;
|
||||
try {
|
||||
mDevice.executeShellCommand("cmd statusbar tracing start");
|
||||
FailureWatcher.super.apply(base, description).evaluate();
|
||||
success = true;
|
||||
} finally {
|
||||
// Save artifact for Launcher Winscope trace.
|
||||
mDevice.executeShellCommand("cmd statusbar tracing stop");
|
||||
final Context nexusLauncherContext =
|
||||
getInstrumentation().getTargetContext()
|
||||
.createPackageContext("com.google.android.apps.nexuslauncher",
|
||||
0);
|
||||
final File launcherTrace =
|
||||
new File(nexusLauncherContext.getFilesDir(), "launcher_trace.pb");
|
||||
if (success) {
|
||||
mDevice.executeShellCommand("rm " + launcherTrace);
|
||||
} else {
|
||||
mDevice.executeShellCommand("mv " + launcherTrace + " "
|
||||
+ diagFile(description, "LauncherWinscope", "pb"));
|
||||
}
|
||||
|
||||
// Detect touch events coming from physical screen.
|
||||
if (mLauncher.hadNontestEvents()) {
|
||||
throw new AssertionError(
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.media.permission.SafeCloseable
|
||||
import android.os.Bundle
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.app.viewcapture.SimpleViewCapture
|
||||
import com.android.app.viewcapture.ViewCapture.MAIN_EXECUTOR
|
||||
import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter
|
||||
import org.junit.rules.TestRule
|
||||
import org.junit.runner.Description
|
||||
@@ -69,7 +70,9 @@ class ViewCaptureRule : TestRule {
|
||||
// Clean up ViewCapture references here rather than in onActivityDestroyed so
|
||||
// test code can access view hierarchy capture. onActivityDestroyed would delete
|
||||
// view capture data before FailureWatcher could output it as a test artifact.
|
||||
windowListenerCloseables.onEach(SafeCloseable::close)
|
||||
// This is on the main thread to avoid a race condition where the onDrawListener
|
||||
// is removed while onDraw is running, resulting in an IllegalStateException.
|
||||
MAIN_EXECUTOR.execute { windowListenerCloseables.onEach(SafeCloseable::close) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,44 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flings backward (right) and waits the fling's end.
|
||||
*/
|
||||
public void flingBackward() {
|
||||
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
|
||||
flingBackwardImpl();
|
||||
}
|
||||
}
|
||||
|
||||
private void flingBackwardImpl() {
|
||||
try (LauncherInstrumentation.Closable c =
|
||||
mLauncher.addContextLayer("want to fling backward in overview")) {
|
||||
LauncherInstrumentation.log("Overview.flingBackward before fling");
|
||||
final UiObject2 overview = verifyActiveContainer();
|
||||
final int rightMargin =
|
||||
mLauncher.getTargetInsets().right + mLauncher.getEdgeSensitivityWidth();
|
||||
mLauncher.scroll(
|
||||
overview, Direction.RIGHT, new Rect(0, 0, rightMargin + 1, 0), 20, false);
|
||||
try (LauncherInstrumentation.Closable c2 =
|
||||
mLauncher.addContextLayer("flung backwards")) {
|
||||
verifyActiveContainer();
|
||||
verifyActionsViewVisibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private OverviewTask flingToFirstTask() {
|
||||
OverviewTask currentTask = getCurrentTask();
|
||||
|
||||
while (mLauncher.getRealDisplaySize().x - currentTask.getUiObject().getVisibleBounds().right
|
||||
<= mLauncher.getOverviewPageSpacing()) {
|
||||
flingBackwardImpl();
|
||||
currentTask = getCurrentTask();
|
||||
}
|
||||
|
||||
return currentTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismissed all tasks by scrolling to Clear-all button and pressing it.
|
||||
*/
|
||||
@@ -94,23 +132,57 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Flings backward (right) and waits the fling's end.
|
||||
* Touch to the right of current task. This should dismiss overview and go back to Workspace.
|
||||
*/
|
||||
public void flingBackward() {
|
||||
public Workspace touchOutsideFirstTask() {
|
||||
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
|
||||
LauncherInstrumentation.Closable c =
|
||||
mLauncher.addContextLayer("want to fling backward in overview")) {
|
||||
LauncherInstrumentation.log("Overview.flingBackward before fling");
|
||||
final UiObject2 overview = verifyActiveContainer();
|
||||
final int rightMargin =
|
||||
mLauncher.getTargetInsets().right + mLauncher.getEdgeSensitivityWidth();
|
||||
mLauncher.scroll(
|
||||
overview, Direction.RIGHT, new Rect(0, 0, rightMargin + 1, 0), 20, false);
|
||||
try (LauncherInstrumentation.Closable c2 =
|
||||
mLauncher.addContextLayer("flung backwards")) {
|
||||
verifyActiveContainer();
|
||||
verifyActionsViewVisibility();
|
||||
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
|
||||
"touching outside the focused task")) {
|
||||
|
||||
if (getTaskCount() < 2) {
|
||||
throw new IllegalStateException(
|
||||
"Need to have at least 2 tasks");
|
||||
}
|
||||
|
||||
OverviewTask currentTask = flingToFirstTask();
|
||||
|
||||
mLauncher.touchOutsideContainer(currentTask.getUiObject(),
|
||||
/* tapRight= */ true,
|
||||
/* halfwayToEdge= */ false);
|
||||
|
||||
return new Workspace(mLauncher);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch between two tasks
|
||||
*/
|
||||
public void touchBetweenTasks() {
|
||||
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
|
||||
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
|
||||
"touching outside the focused task")) {
|
||||
if (getTaskCount() < 2) {
|
||||
throw new IllegalStateException(
|
||||
"Need to have at least 2 tasks");
|
||||
}
|
||||
|
||||
OverviewTask currentTask = flingToFirstTask();
|
||||
|
||||
mLauncher.touchOutsideContainer(currentTask.getUiObject(),
|
||||
/* tapRight= */ false,
|
||||
/* halfwayToEdge= */ false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch either on the right or the left corner of the screen, 1 pixel from the bottom and
|
||||
* from the sides.
|
||||
*/
|
||||
public void touchTaskbarBottomCorner(boolean tapRight) {
|
||||
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
|
||||
Taskbar taskbar = new Taskbar(mLauncher);
|
||||
taskbar.touchBottomCorner(tapRight);
|
||||
verifyActiveContainer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2014,21 +2014,41 @@ public final class LauncherInstrumentation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Taps outside container to dismiss.
|
||||
* Taps outside container to dismiss, centered vertically and halfway to the edge of the screen.
|
||||
*
|
||||
* @param container container to be dismissed
|
||||
* @param tapRight tap on the right of the container if true, or left otherwise
|
||||
*/
|
||||
void touchOutsideContainer(UiObject2 container, boolean tapRight) {
|
||||
touchOutsideContainer(container, tapRight, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Taps outside the container, to the right or left, and centered vertically.
|
||||
*
|
||||
* @param tapRight if true touches to the right of the container, otherwise touches on left
|
||||
* @param halfwayToEdge if true touches halfway to the screen edge, if false touches 1 px from
|
||||
* container
|
||||
*/
|
||||
void touchOutsideContainer(UiObject2 container, boolean tapRight, boolean halfwayToEdge) {
|
||||
try (LauncherInstrumentation.Closable c = addContextLayer(
|
||||
"want to tap outside container on the " + (tapRight ? "right" : "left"))) {
|
||||
Rect containerBounds = getVisibleBounds(container);
|
||||
|
||||
int x;
|
||||
if (halfwayToEdge) {
|
||||
x = tapRight
|
||||
? (containerBounds.right + getRealDisplaySize().x) / 2
|
||||
: containerBounds.left / 2;
|
||||
} else {
|
||||
x = tapRight
|
||||
? containerBounds.right + 1
|
||||
: containerBounds.left - 1;
|
||||
}
|
||||
int y = containerBounds.top + containerBounds.height() / 2;
|
||||
|
||||
final long downTime = SystemClock.uptimeMillis();
|
||||
final Point tapTarget = new Point(
|
||||
tapRight
|
||||
? (containerBounds.right + getRealDisplaySize().x) / 2
|
||||
: containerBounds.left / 2,
|
||||
containerBounds.top + 1);
|
||||
final Point tapTarget = new Point(x, y);
|
||||
sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, tapTarget,
|
||||
LauncherInstrumentation.GestureScope.INSIDE);
|
||||
sendPointer(downTime, downTime, MotionEvent.ACTION_UP, tapTarget,
|
||||
|
||||
@@ -71,6 +71,10 @@ public final class OverviewTask {
|
||||
return mTask.getVisibleBounds().exactCenterX();
|
||||
}
|
||||
|
||||
UiObject2 getUiObject() {
|
||||
return mTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismisses the task by swiping up.
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_DISABLE_
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
import android.view.MotionEvent;
|
||||
@@ -122,4 +123,33 @@ public final class Taskbar {
|
||||
// Look for an icon with no text
|
||||
return By.clazz(TextView.class).text("");
|
||||
}
|
||||
|
||||
private Rect getVisibleBounds() {
|
||||
return mLauncher.waitForSystemLauncherObject(TASKBAR_RES_ID).getVisibleBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch either on the right or the left corner of the screen, 1 pixel from the bottom and
|
||||
* from the sides.
|
||||
*/
|
||||
void touchBottomCorner(boolean tapRight) {
|
||||
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
|
||||
"want to tap bottom corner on the " + (tapRight ? "right" : "left"))) {
|
||||
final long downTime = SystemClock.uptimeMillis();
|
||||
final Point tapTarget = new Point(
|
||||
tapRight
|
||||
?
|
||||
getVisibleBounds().right
|
||||
- mLauncher.getTargetInsets().right
|
||||
- 1
|
||||
: getVisibleBounds().left
|
||||
+ 1,
|
||||
mLauncher.getRealDisplaySize().y - 1);
|
||||
|
||||
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, tapTarget,
|
||||
LauncherInstrumentation.GestureScope.INSIDE);
|
||||
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, tapTarget,
|
||||
LauncherInstrumentation.GestureScope.INSIDE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user