mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-28 07:46:55 +00:00
Merge "Fixing jump when swiping up in landscape and in waterfall cutout" into ub-launcher3-rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a5e45ad485
@@ -121,6 +121,10 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend
|
||||
});
|
||||
|
||||
mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
|
||||
// Wait until the first scroll event before applying scroll to taskViewSimulator.
|
||||
// Since, by default the current/running task already centered, this ensures that we
|
||||
// do not move the running task, in case RecentsView has not yet laid out completely.
|
||||
mRecentsViewScrollLinked = true;
|
||||
if (moveWindowWithRecentsScroll()) {
|
||||
updateFinalShift();
|
||||
}
|
||||
@@ -128,7 +132,6 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend
|
||||
runOnRecentsAnimationStart(() ->
|
||||
mRecentsView.setRecentsAnimationTargets(mRecentsAnimationController,
|
||||
mRecentsAnimationTargets));
|
||||
mRecentsViewScrollLinked = true;
|
||||
}
|
||||
|
||||
protected void startNewTask(Consumer<Boolean> resultCallback) {
|
||||
@@ -205,26 +208,30 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend
|
||||
mRecentsAnimationController = recentsAnimationController;
|
||||
mRecentsAnimationTargets = targets;
|
||||
mTransformParams.setTargetSet(mRecentsAnimationTargets);
|
||||
DeviceProfile dp = mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile();
|
||||
RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(
|
||||
mGestureState.getRunningTaskId());
|
||||
|
||||
if (targets.minimizedHomeBounds != null && runningTaskTarget != null) {
|
||||
Rect overviewStackBounds = mActivityInterface
|
||||
.getOverviewWindowBounds(targets.minimizedHomeBounds, runningTaskTarget);
|
||||
dp = dp.getMultiWindowProfile(mContext,
|
||||
new WindowBounds(overviewStackBounds, targets.homeContentInsets));
|
||||
} else {
|
||||
// If we are not in multi-window mode, home insets should be same as system insets.
|
||||
dp = dp.copy(mContext);
|
||||
}
|
||||
dp.updateInsets(targets.homeContentInsets);
|
||||
dp.updateIsSeascape(mContext);
|
||||
if (runningTaskTarget != null) {
|
||||
mTaskViewSimulator.setPreview(runningTaskTarget);
|
||||
}
|
||||
|
||||
initTransitionEndpoints(dp);
|
||||
// Only initialize the device profile, if it has not been initialized before, as in some
|
||||
// configurations targets.homeContentInsets may not be correct.
|
||||
if (mActivity == null) {
|
||||
DeviceProfile dp = mTaskViewSimulator.getOrientationState().getLauncherDeviceProfile();
|
||||
if (targets.minimizedHomeBounds != null && runningTaskTarget != null) {
|
||||
Rect overviewStackBounds = mActivityInterface
|
||||
.getOverviewWindowBounds(targets.minimizedHomeBounds, runningTaskTarget);
|
||||
dp = dp.getMultiWindowProfile(mContext,
|
||||
new WindowBounds(overviewStackBounds, targets.homeContentInsets));
|
||||
} else {
|
||||
// If we are not in multi-window mode, home insets should be same as system insets.
|
||||
dp = dp.copy(mContext);
|
||||
}
|
||||
dp.updateInsets(targets.homeContentInsets);
|
||||
dp.updateIsSeascape(mContext);
|
||||
initTransitionEndpoints(dp);
|
||||
}
|
||||
|
||||
// Notify when the animation starts
|
||||
if (!mRecentsAnimationStartCallbacks.isEmpty()) {
|
||||
|
||||
@@ -256,8 +256,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
||||
float taskHeight = mTaskRect.height();
|
||||
|
||||
mMatrix.set(mPositionHelper.getMatrix());
|
||||
mMatrix.postScale(scale, scale);
|
||||
mMatrix.postTranslate(insets.left, insets.top);
|
||||
mMatrix.postScale(scale, scale);
|
||||
|
||||
// Apply TaskView matrix: translate, scale, scroll
|
||||
mMatrix.postTranslate(mTaskRect.left, mTaskRect.top);
|
||||
|
||||
@@ -1000,6 +1000,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
mDwbToastShown = false;
|
||||
mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, 0);
|
||||
LayoutUtils.setViewEnabled(mActionsView, true);
|
||||
mOrientationState.setGestureActive(false);
|
||||
}
|
||||
|
||||
public @Nullable TaskView getRunningTaskView() {
|
||||
@@ -1037,6 +1038,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
*/
|
||||
public void onGestureAnimationStart(int runningTaskId) {
|
||||
// This needs to be called before the other states are set since it can create the task view
|
||||
mOrientationState.setGestureActive(true);
|
||||
showCurrentTask(runningTaskId);
|
||||
setEnableFreeScroll(false);
|
||||
setEnableDrawingLiveTile(false);
|
||||
@@ -1099,6 +1101,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
* Called when a gesture from an app has finished.
|
||||
*/
|
||||
public void onGestureAnimationEnd() {
|
||||
mOrientationState.setGestureActive(false);
|
||||
|
||||
setOnScrollChangeListener(null);
|
||||
setEnableFreeScroll(true);
|
||||
setEnableDrawingLiveTile(true);
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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.quickstep.util;
|
||||
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.shadows.LShadowDisplay;
|
||||
import com.android.launcher3.util.DefaultDisplay;
|
||||
import com.android.quickstep.LauncherActivityInterface;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.annotation.LooperMode.Mode;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.shadows.ShadowDisplayManager;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@LooperMode(Mode.PAUSED)
|
||||
public class TaskViewSimulatorTest {
|
||||
|
||||
@Test
|
||||
public void taskProperlyScaled_portrait_noRotation_sameInsets1() {
|
||||
new TaskMatrixVerifier()
|
||||
.withLauncherSize(1200, 2450)
|
||||
.withInsets(new Rect(0, 80, 0, 120))
|
||||
.verifyNoTransforms();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void taskProperlyScaled_portrait_noRotation_sameInsets2() {
|
||||
new TaskMatrixVerifier()
|
||||
.withLauncherSize(1200, 2450)
|
||||
.withInsets(new Rect(55, 80, 55, 120))
|
||||
.verifyNoTransforms();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void taskProperlyScaled_landscape_noRotation_sameInsets1() {
|
||||
new TaskMatrixVerifier()
|
||||
.withLauncherSize(2450, 1250)
|
||||
.withInsets(new Rect(0, 80, 0, 40))
|
||||
.verifyNoTransforms();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void taskProperlyScaled_landscape_noRotation_sameInsets2() {
|
||||
new TaskMatrixVerifier()
|
||||
.withLauncherSize(2450, 1250)
|
||||
.withInsets(new Rect(0, 80, 120, 0))
|
||||
.verifyNoTransforms();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void taskProperlyScaled_landscape_noRotation_sameInsets3() {
|
||||
new TaskMatrixVerifier()
|
||||
.withLauncherSize(2450, 1250)
|
||||
.withInsets(new Rect(55, 80, 55, 120))
|
||||
.verifyNoTransforms();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void taskProperlyScaled_landscape_rotated() {
|
||||
new TaskMatrixVerifier()
|
||||
.withLauncherSize(1200, 2450)
|
||||
.withInsets(new Rect(0, 80, 0, 120))
|
||||
.withAppBounds(
|
||||
new Rect(0, 0, 2450, 1200),
|
||||
new Rect(0, 80, 0, 120),
|
||||
Surface.ROTATION_90)
|
||||
.verifyNoTransforms();
|
||||
}
|
||||
|
||||
private static class TaskMatrixVerifier extends TransformParams {
|
||||
|
||||
private final Context mContext = RuntimeEnvironment.application;
|
||||
|
||||
private Rect mAppBounds = new Rect();
|
||||
private Rect mLauncherInsets = new Rect();
|
||||
|
||||
private Rect mAppInsets;
|
||||
|
||||
private int mAppRotation = -1;
|
||||
private DeviceProfile mDeviceProfile;
|
||||
|
||||
TaskMatrixVerifier withLauncherSize(int width, int height) {
|
||||
ShadowDisplayManager.changeDisplay(DEFAULT_DISPLAY,
|
||||
String.format("w%sdp-h%sdp-mdpi", width, height));
|
||||
if (mAppBounds.isEmpty()) {
|
||||
mAppBounds.set(0, 0, width, height);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
TaskMatrixVerifier withInsets(Rect insets) {
|
||||
LShadowDisplay shadowDisplay = Shadow.extract(
|
||||
mContext.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY));
|
||||
shadowDisplay.setInsets(insets);
|
||||
mLauncherInsets.set(insets);
|
||||
return this;
|
||||
}
|
||||
|
||||
TaskMatrixVerifier withAppBounds(Rect bounds, Rect insets, int appRotation) {
|
||||
mAppBounds.set(bounds);
|
||||
mAppInsets = insets;
|
||||
mAppRotation = appRotation;
|
||||
return this;
|
||||
}
|
||||
|
||||
void verifyNoTransforms() {
|
||||
mDeviceProfile = InvariantDeviceProfile.INSTANCE.get(mContext)
|
||||
.getDeviceProfile(mContext);
|
||||
mDeviceProfile.updateInsets(mLauncherInsets);
|
||||
|
||||
TaskViewSimulator tvs = new TaskViewSimulator(mContext,
|
||||
LauncherActivityInterface.INSTANCE);
|
||||
tvs.setDp(mDeviceProfile);
|
||||
|
||||
int launcherRotation = DefaultDisplay.INSTANCE.get(mContext).getInfo().rotation;
|
||||
if (mAppRotation < 0) {
|
||||
mAppRotation = launcherRotation;
|
||||
}
|
||||
tvs.setLayoutRotation(launcherRotation, mAppRotation);
|
||||
if (mAppInsets == null) {
|
||||
mAppInsets = new Rect(mLauncherInsets);
|
||||
}
|
||||
tvs.setPreviewBounds(mAppBounds, mAppInsets);
|
||||
|
||||
tvs.fullScreenProgress.value = 1;
|
||||
tvs.recentsViewScale.value = tvs.getFullScreenScale();
|
||||
tvs.apply(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceParams[] createSurfaceParams(BuilderProxy proxy) {
|
||||
SurfaceParams.Builder builder = new SurfaceParams.Builder((SurfaceControl) null);
|
||||
proxy.onBuildTargetParams(builder, null, this);
|
||||
return new SurfaceParams[] {builder.build()};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySurfaceParams(SurfaceParams[] params) {
|
||||
// Verify that the task position remains the same
|
||||
RectF newAppBounds = new RectF(mAppBounds);
|
||||
params[0].matrix.mapRect(newAppBounds);
|
||||
Assert.assertThat(newAppBounds, new AlmostSame(mAppBounds));
|
||||
|
||||
System.err.println("Bounds mapped: " + mAppBounds + " => " + newAppBounds);
|
||||
}
|
||||
}
|
||||
|
||||
private static class AlmostSame extends TypeSafeMatcher<RectF> {
|
||||
|
||||
// Allow 1px error margin to account for float to int conversions
|
||||
private final float mError = 1f;
|
||||
private final Rect mExpected;
|
||||
|
||||
AlmostSame(Rect expected) {
|
||||
mExpected = expected;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(RectF item) {
|
||||
return Math.abs(item.left - mExpected.left) < mError
|
||||
&& Math.abs(item.top - mExpected.top) < mError
|
||||
&& Math.abs(item.right - mExpected.right) < mError
|
||||
&& Math.abs(item.bottom - mExpected.bottom) < mError;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendValue(mExpected);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,9 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
||||
private static final int FLAG_ROTATION_WATCHER_ENABLED = 1 << 6;
|
||||
// Enable home rotation for UI tests, ignoring home rotation value from prefs
|
||||
private static final int FLAG_HOME_ROTATION_FORCE_ENABLED_FOR_TESTING = 1 << 7;
|
||||
// Whether the swipe gesture is running, so the recents would stay locked in the
|
||||
// current orientation
|
||||
private static final int FLAG_SWIPE_UP_NOT_RUNNING = 1 << 8;
|
||||
|
||||
private static final int MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE =
|
||||
FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY
|
||||
@@ -114,7 +117,8 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
||||
// multi-window is enabled as in that case, activity itself rotates.
|
||||
private static final int VALUE_ROTATION_WATCHER_ENABLED =
|
||||
MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE | FLAG_SYSTEM_ROTATION_ALLOWED
|
||||
| FLAG_ROTATION_WATCHER_SUPPORTED | FLAG_ROTATION_WATCHER_ENABLED;
|
||||
| FLAG_ROTATION_WATCHER_SUPPORTED | FLAG_ROTATION_WATCHER_ENABLED
|
||||
| FLAG_SWIPE_UP_NOT_RUNNING;
|
||||
|
||||
private final Context mContext;
|
||||
private final ContentResolver mContentResolver;
|
||||
@@ -156,6 +160,7 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
||||
if (originalSmallestWidth < 600) {
|
||||
mFlags |= FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_DENSITY;
|
||||
}
|
||||
mFlags |= FLAG_SWIPE_UP_NOT_RUNNING;
|
||||
initFlags();
|
||||
}
|
||||
|
||||
@@ -166,6 +171,13 @@ public final class RecentsOrientedState implements SharedPreferences.OnSharedPre
|
||||
setFlag(FLAG_MULTIWINDOW_ROTATION_ALLOWED, isMultiWindow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the swipe up gesture is currently running or not
|
||||
*/
|
||||
public void setGestureActive(boolean isGestureActive) {
|
||||
setFlag(FLAG_SWIPE_UP_NOT_RUNNING, !isGestureActive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the appropriate {@link PagedOrientationHandler} for {@link #mOrientationHandler}
|
||||
* @param touchRotation The rotation the nav bar region that is touched is in
|
||||
|
||||
@@ -5,6 +5,7 @@ shadows= \
|
||||
com.android.launcher3.shadows.LShadowAppWidgetManager \
|
||||
com.android.launcher3.shadows.LShadowBackupManager \
|
||||
com.android.launcher3.shadows.LShadowBitmap \
|
||||
com.android.launcher3.shadows.LShadowDisplay \
|
||||
com.android.launcher3.shadows.LShadowLauncherApps \
|
||||
com.android.launcher3.shadows.LShadowTypeface \
|
||||
com.android.launcher3.shadows.LShadowUserManager \
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 static org.robolectric.shadow.api.Shadow.directlyOn;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.view.Display;
|
||||
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.annotation.RealObject;
|
||||
import org.robolectric.shadows.ShadowDisplay;
|
||||
|
||||
/**
|
||||
* Extension of {@link ShadowDisplay} with missing shadow methods
|
||||
*/
|
||||
@Implements(value = Display.class)
|
||||
public class LShadowDisplay extends ShadowDisplay {
|
||||
|
||||
private final Rect mInsets = new Rect();
|
||||
|
||||
@RealObject Display realObject;
|
||||
|
||||
/**
|
||||
* Sets the insets for the display
|
||||
*/
|
||||
public void setInsets(Rect insets) {
|
||||
mInsets.set(insets);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) {
|
||||
directlyOn(realObject, Display.class).getCurrentSizeRange(outSmallestSize, outLargestSize);
|
||||
outSmallestSize.x -= mInsets.left + mInsets.right;
|
||||
outLargestSize.x -= mInsets.left + mInsets.right;
|
||||
|
||||
outSmallestSize.y -= mInsets.top + mInsets.bottom;
|
||||
outLargestSize.y -= mInsets.top + mInsets.bottom;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user