Merge "Making QuickScrub work, when the fallback activity is on top" into ub-launcher3-master
diff --git a/proguard.flags b/proguard.flags
index 086337d..e9f6db4 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -107,6 +107,11 @@
public <init>(...);
}
+# MainProcessInitializer
+-keep class com.android.quickstep.QuickstepProcessInitializer {
+ public <init>(...);
+}
+
-keep interface com.android.launcher3.userevent.nano.LauncherLogProto.** {
*;
}
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index ab6d8af..c741913 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -20,7 +20,6 @@
<dimen name="task_thumbnail_icon_size">48dp</dimen>
<dimen name="task_menu_background_radius">12dp</dimen>
<dimen name="task_corner_radius">2dp</dimen>
- <dimen name="task_fade_length">20dp</dimen>
<dimen name="recents_page_spacing">10dp</dimen>
<!-- The speed in dp/s at which the user needs to be scrolling in recents such that we start
@@ -37,4 +36,13 @@
<dimen name="recents_empty_message_text_size">16sp</dimen>
<dimen name="recents_empty_message_text_padding">16dp</dimen>
+ <!-- Total space (start + end) between the task card and the edge of the screen
+ in various configurations -->
+ <dimen name="task_card_vert_space">40dp</dimen>
+ <dimen name="portrait_task_card_horz_space">136dp</dimen>
+ <dimen name="landscape_task_card_horz_space">200dp</dimen>
+ <dimen name="multi_window_task_card_horz_space">100dp</dimen>
+ <!-- Copied from framework resource:
+ docked_stack_divider_thickness - 2 * docked_stack_divider_insets -->
+ <dimen name="multi_window_task_divider_size">10dp</dimen>
</resources>
diff --git a/quickstep/res/values/override.xml b/quickstep/res/values/override.xml
index 2bd9f8f..d683659 100644
--- a/quickstep/res/values/override.xml
+++ b/quickstep/res/values/override.xml
@@ -18,5 +18,7 @@
<string name="app_transition_manager_class" translatable="false">com.android.launcher3.LauncherAppTransitionManagerImpl</string>
<string name="instant_app_resolver_class" translatable="false">com.android.quickstep.InstantAppResolverImpl</string>
+
+ <string name="main_process_initializer_class" translatable="false">com.android.quickstep.QuickstepProcessInitializer</string>
</resources>
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index ec54732..9c7db30 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -19,13 +19,11 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
-import android.graphics.Rect;
import android.view.View;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.Workspace;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.views.RecentsView;
@@ -47,14 +45,8 @@
@Override
public float[] getWorkspaceScaleAndTranslation(Launcher launcher) {
- Rect pageRect = new Rect();
- RecentsView.getPageRect(launcher.getDeviceProfile(), launcher, pageRect);
-
- if (launcher.getWorkspace().getNormalChildWidth() <= 0 || pageRect.isEmpty()) {
- return super.getWorkspaceScaleAndTranslation(launcher);
- }
-
- return getScaleAndTranslationForPageRect(launcher, pageRect);
+ // TODO: provide a valid value
+ return new float[]{1, 0, -launcher.getDeviceProfile().hotseatBarSizePx / 2};
}
@Override
@@ -93,20 +85,6 @@
};
}
- public static float[] getScaleAndTranslationForPageRect(Launcher launcher, Rect pageRect) {
- Workspace ws = launcher.getWorkspace();
- float childWidth = ws.getNormalChildWidth();
-
- float scale = pageRect.width() / childWidth;
- Rect insets = launcher.getDragLayer().getInsets();
-
- float halfHeight = ws.getExpectedHeight() / 2;
- float childTop = halfHeight - scale * (halfHeight - ws.getPaddingTop() - insets.top);
- float translationY = pageRect.top - childTop;
-
- return new float[] {scale, 0, translationY};
- }
-
@Override
public int getVisibleElements(Launcher launcher) {
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 97930f8..5841285 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -43,6 +43,7 @@
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.views.LauncherLayoutListener;
+import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -140,7 +141,7 @@
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
- RecentsView.getPageRect(dp, context, outRect);
+ LauncherRecentsView.getPageRect(dp, context, outRect);
if (dp.isVerticalBarLayout()) {
Rect targetInsets = dp.getInsets();
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
@@ -295,7 +296,7 @@
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
- FallbackRecentsView.getCenterPageRect(dp, context, outRect);
+ FallbackRecentsView.getPageRect(dp, context, outRect);
if (dp.isVerticalBarLayout()) {
Rect targetInsets = dp.getInsets();
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 2fb4127..d76c49a 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -15,7 +15,6 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
@@ -35,11 +34,8 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.states.InternalStateHandler;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.FallbackActivityControllerHelper;
import com.android.quickstep.ActivityControlHelper.LauncherActivityControllerHelper;
@@ -54,7 +50,7 @@
* Helper class to handle various atomic commands for switching between Overview.
*/
@TargetApi(Build.VERSION_CODES.P)
-public class OverviewCommandHelper extends InternalStateHandler {
+public class OverviewCommandHelper {
private static final long RECENTS_LAUNCH_DURATION = 200;
@@ -95,55 +91,18 @@
homeIntent.setComponent(launcher).setPackage(null);
}
- private void openRecents() {
- Intent intent = addToIntent(new Intent(homeIntent));
- mContext.startActivity(intent);
- initWhenReady();
- }
-
public void onOverviewToggle() {
// If currently screen pinning, do not enter overview
- if (ActivityManagerWrapper.getInstance().isScreenPinningActive()) {
+ if (mAM.isScreenPinningActive()) {
return;
}
- ActivityManagerWrapper.getInstance().closeSystemWindows("recentapps");
+ mAM.closeSystemWindows("recentapps");
mMainThreadExecutor.execute(new RecentsActivityCommand<>());
}
public void onOverviewShown() {
- getLauncher().runOnUiThread(() -> {
- if (isOverviewAlmostVisible()) {
- final RecentsView rv = getLauncher().getOverviewPanel();
- rv.snapToTaskAfterNext();
- } else {
- openRecents();
- }
- }
- );
- }
-
- private boolean isOverviewAlmostVisible() {
- if (clearReference()) {
- return true;
- }
- if (!mAM.getRunningTask().topActivity.equals(launcher)) {
- return false;
- }
- Launcher launcher = getLauncher();
- return launcher != null && launcher.isStarted() && launcher.isInState(OVERVIEW);
- }
-
- private Launcher getLauncher() {
- return (Launcher) LauncherAppState.getInstance(mContext).getModel().getCallback();
- }
-
- @Override
- protected boolean init(Launcher launcher, boolean alreadyOnHome) {
- AbstractFloatingView.closeAllOpenViews(launcher, alreadyOnHome);
- launcher.getStateManager().goToState(OVERVIEW, alreadyOnHome);
- clearReference();
- return false;
+ mMainThreadExecutor.execute(new ShowRecentsCommand());
}
public ActivityControlHelper getActivityControlHelper() {
@@ -154,9 +113,23 @@
}
}
+ private class ShowRecentsCommand extends RecentsActivityCommand {
+
+ @Override
+ protected boolean handleCommand(long elapsedTime) {
+ RecentsView recents = mHelper.getVisibleRecentsView();
+ if (recents != null) {
+ recents.snapToTaskAfterNext();
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
private class RecentsActivityCommand<T extends BaseDraggingActivity> implements Runnable {
- private final ActivityControlHelper<T> mHelper;
+ protected final ActivityControlHelper<T> mHelper;
private final long mCreateTime;
private final int mRunningTaskId;
@@ -166,7 +139,7 @@
public RecentsActivityCommand() {
mHelper = getActivityControlHelper();
mCreateTime = SystemClock.elapsedRealtime();
- mRunningTaskId = ActivityManagerWrapper.getInstance().getRunningTask().id;
+ mRunningTaskId = mAM.getRunningTask().id;
// Preload the plan
mRecentsModel.loadTasks(mRunningTaskId, null);
@@ -177,20 +150,7 @@
long elapsedTime = mCreateTime - mLastToggleTime;
mLastToggleTime = mCreateTime;
- // TODO: We need to fix this case with PIP, when an activity first enters PIP, it shows
- // the menu activity which takes window focus, preventing the right condition from
- // being run below
- RecentsView recents = mHelper.getVisibleRecentsView();
- if (recents != null) {
- // Launch the next task
- recents.showNextTask();
- } else {
- if (elapsedTime < ViewConfiguration.getDoubleTapTimeout()) {
- // The user tried to launch back into overview too quickly, either after
- // launching an app, or before overview has actually shown, just ignore for now
- return;
- }
-
+ if (!handleCommand(elapsedTime)) {
// Start overview
if (mHelper.switchToRecentsIfVisible()) {
SysuiEventLogger.writeDummyRecentsTransition(0);
@@ -203,6 +163,23 @@
}
}
+ protected boolean handleCommand(long elapsedTime) {
+ // TODO: We need to fix this case with PIP, when an activity first enters PIP, it shows
+ // the menu activity which takes window focus, preventing the right condition from
+ // being run below
+ RecentsView recents = mHelper.getVisibleRecentsView();
+ if (recents != null) {
+ // Launch the next task
+ recents.showNextTask();
+ return true;
+ } else if (elapsedTime < ViewConfiguration.getDoubleTapTimeout()) {
+ // The user tried to launch back into overview too quickly, either after
+ // launching an app, or before overview has actually shown, just ignore for now
+ return true;
+ }
+ return false;
+ }
+
private boolean onActivityReady(T activity, Boolean wasVisible) {
activity.<RecentsView>getOverviewPanel().setCurrentTask(mRunningTaskId);
AbstractFloatingView.closeAllOpenViews(activity, wasVisible);
diff --git a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
new file mode 100644
index 0000000..aed9959
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 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;
+
+import android.content.Context;
+
+import com.android.launcher3.MainProcessInitializer;
+import com.android.systemui.shared.system.ThreadedRendererCompat;
+
+public class QuickstepProcessInitializer extends MainProcessInitializer {
+
+ public QuickstepProcessInitializer(Context context) { }
+
+ @Override
+ protected void init(Context context) {
+ super.init(context);
+
+ // Elevate GPU priority for Quickstep and Remote animations.
+ ThreadedRendererCompat.setContextPriority(ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 7d7f88f..4ed1656 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -18,15 +18,16 @@
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.support.annotation.AnyThread;
import android.util.AttributeSet;
import android.view.View;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Insettable;
import com.android.quickstep.RecentsActivity;
+import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
-public class FallbackRecentsView extends RecentsView<RecentsActivity> implements Insettable {
+public class FallbackRecentsView extends RecentsView<RecentsActivity> {
public FallbackRecentsView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -56,30 +57,18 @@
}
@Override
- public void setInsets(Rect insets) {
- mInsets.set(insets);
- DeviceProfile dp = mActivity.getDeviceProfile();
- Rect padding = getPadding(dp, getContext());
- verticalCenter(padding, dp);
- setPadding(padding.left, padding.top, padding.right, padding.bottom);
- }
-
- private static void verticalCenter(Rect padding, DeviceProfile dp) {
- Rect insets = dp.getInsets();
- int totalSpace = (padding.top + padding.bottom - insets.top - insets.bottom) / 2;
- padding.top = insets.top + totalSpace;
- padding.bottom = insets.bottom + totalSpace;
- }
-
- public static void getCenterPageRect(DeviceProfile grid, Context context, Rect outRect) {
- Rect targetPadding = getPadding(grid, context);
- verticalCenter(targetPadding, grid);
- getPageRect(grid, context, outRect, targetPadding);
- }
-
- @Override
public void draw(Canvas canvas) {
maybeDrawEmptyMessage(canvas);
super.draw(canvas);
}
+
+ @Override
+ protected void getTaskSize(DeviceProfile dp, Rect outRect) {
+ LayoutUtils.calculateTaskSize(getContext(), dp, 0, outRect);
+ }
+
+ @AnyThread
+ public static void getPageRect(DeviceProfile grid, Context context, Rect outRect) {
+ LayoutUtils.calculateTaskSize(context, grid, 0, outRect);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
new file mode 100644
index 0000000..f29f9e4
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 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 android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.graphics.RectF;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
+
+public class LayoutUtils {
+
+ public static void calculateLauncherTaskSize(Context context, DeviceProfile dp, Rect outRect) {
+ float extraSpace = dp.isVerticalBarLayout() ? 0 : dp.hotseatBarSizePx;
+ calculateTaskSize(context, dp, extraSpace, outRect);
+ }
+
+ public static void calculateTaskSize(Context context, DeviceProfile dp,
+ float extraVerticalSpace, Rect outRect) {
+ float taskWidth, taskHeight, paddingHorz;
+ Resources res = context.getResources();
+ Rect insets = dp.getInsets();
+
+ if (dp.isMultiWindowMode) {
+ DeviceProfile fullDp = dp.getFullScreenProfile();
+ // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
+ // account for system insets
+ taskWidth = fullDp.availableWidthPx;
+ taskHeight = fullDp.availableHeightPx;
+ float halfDividerSize = res.getDimension(R.dimen.multi_window_task_divider_size) / 2;
+
+ if (fullDp.isLandscape) {
+ taskWidth = taskWidth / 2 - halfDividerSize;
+ } else {
+ taskHeight = taskHeight / 2 - halfDividerSize;
+ }
+ paddingHorz = res.getDimension(R.dimen.multi_window_task_card_horz_space);
+ } else {
+ taskWidth = dp.availableWidthPx;
+ taskHeight = dp.availableHeightPx;
+ paddingHorz = res.getDimension(dp.isVerticalBarLayout()
+ ? R.dimen.landscape_task_card_horz_space
+ : R.dimen.portrait_task_card_horz_space);
+ }
+
+ float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
+ float paddingVert = res.getDimension(R.dimen.task_card_vert_space);
+
+ // Note this should be same as dp.availableWidthPx and dp.availableHeightPx unless
+ // we override the insets ourselves.
+ int launcherVisibleWidth = dp.widthPx - insets.left - insets.right;
+ int launcherVisibleHeight = dp.heightPx - insets.top - insets.bottom;
+
+ float availableHeight = launcherVisibleHeight
+ - topIconMargin - extraVerticalSpace - paddingVert;
+ float availableWidth = launcherVisibleWidth - paddingHorz;
+
+ float scale = Math.min(availableWidth / taskWidth, availableHeight / taskHeight);
+ float outWidth = scale * taskWidth;
+ float outHeight = scale * taskHeight;
+
+ // Center in the visible space
+ float x = insets.left + (taskWidth - outWidth) / 2;
+ float y = insets.top + Math.max(topIconMargin,
+ (launcherVisibleHeight - extraVerticalSpace - outHeight) / 2);
+ outRect.set(Math.round(x), Math.round(y),
+ Math.round(x + outWidth), Math.round(y + outHeight));
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 6788827..4b4af3f 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -27,22 +27,22 @@
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Build;
+import android.support.annotation.AnyThread;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.view.View;
import android.view.ViewDebug;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
-import com.android.launcher3.R;
+import com.android.quickstep.util.LayoutUtils;
/**
* {@link RecentsView} used in Launcher activity
*/
@TargetApi(Build.VERSION_CODES.O)
-public class LauncherRecentsView extends RecentsView<Launcher> implements Insettable {
+public class LauncherRecentsView extends RecentsView<Launcher> {
public static final FloatProperty<LauncherRecentsView> TRANSLATION_Y_FACTOR =
new FloatProperty<LauncherRecentsView>("translationYFactor") {
@@ -61,8 +61,6 @@
@ViewDebug.ExportedProperty(category = "launcher")
private float mTranslationYFactor;
- private Rect mPagePadding = new Rect();
-
public LauncherRecentsView(Context context) {
this(context, null);
}
@@ -77,16 +75,6 @@
}
@Override
- public void setInsets(Rect insets) {
- mInsets.set(insets);
- DeviceProfile dp = mActivity.getDeviceProfile();
- Rect padding = getPadding(dp, getContext());
- setPadding(padding.left, padding.top, padding.right, padding.bottom);
- mPagePadding.set(padding);
- mPagePadding.top += getResources().getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
- }
-
- @Override
protected void onAllTasksRemoved() {
mActivity.getStateManager().goToState(NORMAL);
}
@@ -99,7 +87,7 @@
public void setTranslationYFactor(float translationFactor) {
mTranslationYFactor = translationFactor;
- setTranslationY(mTranslationYFactor * (mPagePadding.bottom - mPagePadding.top));
+ setTranslationY(mTranslationYFactor * (getPaddingBottom() - getPaddingTop()));
}
@Override
@@ -138,4 +126,14 @@
mActivity.getAllAppsController(), ALL_APPS_PROGRESS, allAppsProgressOffscreen));
return anim;
}
+
+ @Override
+ protected void getTaskSize(DeviceProfile dp, Rect outRect) {
+ LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect);
+ }
+
+ @AnyThread
+ public static void getPageRect(DeviceProfile grid, Context context, Rect outRect) {
+ LayoutUtils.calculateLauncherTaskSize(context, grid, outRect);
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 6997ec4..7e81ba9 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -53,6 +53,7 @@
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Insettable;
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -75,7 +76,6 @@
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
-import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.ArrayList;
@@ -84,7 +84,9 @@
*/
@TargetApi(Build.VERSION_CODES.P)
public abstract class RecentsView<T extends BaseActivity>
- extends PagedView implements OnSharedPreferenceChangeListener {
+ extends PagedView implements OnSharedPreferenceChangeListener, Insettable {
+
+ private final Rect mTempRect = new Rect();
public static final FloatProperty<RecentsView> CONTENT_ALPHA =
new FloatProperty<RecentsView>("contentAlpha") {
@@ -99,8 +101,6 @@
}
};
-
-
public static final FloatProperty<RecentsView> ADJACENT_SCALE =
new FloatProperty<RecentsView>("adjacentScale") {
@Override
@@ -116,8 +116,6 @@
private static final String PREF_FLIP_RECENTS = "pref_flip_recents";
private static final int DISMISS_TASK_DURATION = 300;
- private static final Rect sTempStableInsets = new Rect();
-
protected final T mActivity;
private final QuickScrubController mQuickScrubController;
private final float mFastFlingVelocity;
@@ -397,69 +395,20 @@
}
}
- protected static Rect getPadding(DeviceProfile profile, Context context) {
- WindowManagerWrapper.getInstance().getStableInsets(sTempStableInsets);
- Rect padding = new Rect(profile.workspacePadding);
-
- float taskWidth = profile.widthPx - sTempStableInsets.left - sTempStableInsets.right;
- float taskHeight = profile.heightPx - sTempStableInsets.top - sTempStableInsets.bottom;
-
- float overviewHeight, overviewWidth;
- if (profile.isVerticalBarLayout()) {
- float maxPadding = Math.max(padding.left, padding.right);
-
- // Use the same padding on both sides for symmetry.
- float availableWidth = taskWidth - 2 * maxPadding;
- float availableHeight = profile.availableHeightPx - padding.top - padding.bottom
- - sTempStableInsets.top;
- float scaledRatio = Math.min(availableWidth / taskWidth, availableHeight / taskHeight);
- overviewHeight = taskHeight * scaledRatio;
- overviewWidth = taskWidth * scaledRatio;
-
- } else {
- overviewHeight = profile.availableHeightPx - padding.top - padding.bottom
- - sTempStableInsets.top;
- overviewWidth = taskWidth * overviewHeight / taskHeight;
- }
-
- padding.bottom = profile.availableHeightPx - padding.top - sTempStableInsets.top
- - Math.round(overviewHeight);
- padding.left = padding.right = (int) ((profile.availableWidthPx - overviewWidth) / 2);
-
- // If the height ratio is larger than the width ratio, the screenshot will get cropped
- // at the bottom when swiping up. In this case, increase the top/bottom padding to make it
- // the same aspect ratio.
- Rect pageRect = new Rect();
- getPageRect(profile, context, pageRect, padding);
- float widthRatio = (float) pageRect.width() / taskWidth;
- float heightRatio = (float) pageRect.height() / taskHeight;
- if (heightRatio > widthRatio) {
- float additionalVerticalPadding = pageRect.height() - widthRatio * taskHeight;
- additionalVerticalPadding = Math.round(additionalVerticalPadding);
- padding.top += additionalVerticalPadding / 2;
- padding.bottom += additionalVerticalPadding / 2;
- }
-
- return padding;
- }
-
- public static void getPageRect(DeviceProfile grid, Context context, Rect outRect) {
- Rect targetPadding = getPadding(grid, context);
- getPageRect(grid, context, outRect, targetPadding);
- }
-
- protected static void getPageRect(DeviceProfile grid, Context context, Rect outRect,
- Rect targetPadding) {
- Rect insets = grid.getInsets();
- outRect.set(
- targetPadding.left + insets.left,
- targetPadding.top + insets.top,
- grid.widthPx - targetPadding.right - insets.right,
- grid.heightPx - targetPadding.bottom - insets.bottom);
- outRect.top += context.getResources()
+ @Override
+ public void setInsets(Rect insets) {
+ mInsets.set(insets);
+ DeviceProfile dp = mActivity.getDeviceProfile();
+ getTaskSize(dp, mTempRect);
+ mTempRect.top -= getResources()
.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
+ setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top,
+ dp.widthPx - mTempRect.right - mInsets.right,
+ dp.heightPx - mTempRect.bottom - mInsets.bottom);
}
+ protected abstract void getTaskSize(DeviceProfile dp, Rect outRect);
+
@Override
protected boolean computeScrollHelper() {
boolean scrolling = super.computeScrollHelper();
@@ -840,11 +789,6 @@
snapToPageRelative(1);
}
- public void launchNextTask() {
- final TaskView nextTask = (TaskView) getChildAt(getNextPage());
- nextTask.launchTask(true);
- }
-
public void setContentAlpha(float alpha) {
if (mContentAlpha == alpha) {
return;
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index 8b41b58..58b7db7 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -22,12 +22,9 @@
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.ComposeShader;
import android.graphics.LightingColorFilter;
-import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
-import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.util.AttributeSet;
@@ -50,14 +47,16 @@
private static final LightingColorFilter[] sDimFilterCache = new LightingColorFilter[256];
private final float mCornerRadius;
- private final float mFadeLength;
+ private final BaseActivity mActivity;
private final TaskOverlay mOverlay;
private final Paint mPaint = new Paint();
- private final Paint mLockedPaint = new Paint();
+ private final Paint mBackgroundPaint = new Paint();
private final Matrix mMatrix = new Matrix();
+ private float mClipBottom = -1;
+
private Task mTask;
private ThumbnailData mThumbnailData;
protected BitmapShader mBitmapShader;
@@ -75,10 +74,10 @@
public TaskThumbnailView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mCornerRadius = getResources().getDimension(R.dimen.task_corner_radius);
- mFadeLength = getResources().getDimension(R.dimen.task_fade_length);
mOverlay = TaskOverlayFactory.get(context).createOverlay(this);
mPaint.setFilterBitmap(true);
- mLockedPaint.setColor(Color.WHITE);
+ mBackgroundPaint.setColor(Color.WHITE);
+ mActivity = BaseActivity.fromContext(context);
}
public void bind() {
@@ -90,7 +89,9 @@
*/
public void setThumbnail(Task task, ThumbnailData thumbnailData) {
mTask = task;
- mPaint.setColor(task == null ? Color.BLACK : task.colorBackground | 0xFF000000);
+ int color = task == null ? Color.BLACK : task.colorBackground | 0xFF000000;
+ mPaint.setColor(color);
+ mBackgroundPaint.setColor(color);
if (thumbnailData != null && thumbnailData.thumbnail != null) {
Bitmap bm = thumbnailData.thumbnail;
@@ -128,8 +129,23 @@
if (mTask == null) {
return;
}
- canvas.drawRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mCornerRadius,
- mCornerRadius, mTask.isLocked ? mLockedPaint : mPaint);
+ int width = getMeasuredWidth();
+ int height = getMeasuredHeight();
+ if (mClipBottom > 0 && !mTask.isLocked) {
+ canvas.save();
+ canvas.clipRect(0, 0, width, mClipBottom);
+
+ canvas.drawRoundRect(0, 0, width, height, mCornerRadius, mCornerRadius, mPaint);
+ canvas.restore();
+ canvas.save();
+ canvas.clipRect(0, mClipBottom, width, height);
+ canvas.drawRoundRect(0, 0, width, height, mCornerRadius, mCornerRadius,
+ mBackgroundPaint);
+ canvas.restore();
+ } else {
+ canvas.drawRoundRect(0, 0, width, height, mCornerRadius,
+ mCornerRadius, mTask.isLocked ? mBackgroundPaint : mPaint);
+ }
}
private void updateThumbnailPaintFilter() {
@@ -137,7 +153,7 @@
if (mBitmapShader != null) {
LightingColorFilter filter = getLightingColorFilter(mul);
mPaint.setColorFilter(filter);
- mLockedPaint.setColorFilter(filter);
+ mBackgroundPaint.setColorFilter(filter);
} else {
mPaint.setColorFilter(null);
mPaint.setColor(Color.argb(255, mul, mul, mul));
@@ -147,47 +163,38 @@
private void updateThumbnailMatrix() {
boolean rotate = false;
+ mClipBottom = -1;
if (mBitmapShader != null && mThumbnailData != null) {
float scale = mThumbnailData.scale;
+ Rect thumbnailInsets = mThumbnailData.insets;
float thumbnailWidth = mThumbnailData.thumbnail.getWidth() -
- (mThumbnailData.insets.left + mThumbnailData.insets.right) * scale;
+ (thumbnailInsets.left + thumbnailInsets.right) * scale;
float thumbnailHeight = mThumbnailData.thumbnail.getHeight() -
- (mThumbnailData.insets.top + mThumbnailData.insets.bottom) * scale;
+ (thumbnailInsets.top + thumbnailInsets.bottom) * scale;
+
final float thumbnailScale;
- final DeviceProfile profile = BaseActivity.fromContext(getContext())
- .getDeviceProfile();
+ final DeviceProfile profile = mActivity.getDeviceProfile();
+
if (getMeasuredWidth() == 0) {
// If we haven't measured , skip the thumbnail drawing and only draw the background
// color
thumbnailScale = 0f;
} else {
final Configuration configuration =
- getContext().getApplicationContext().getResources().getConfiguration();
- if (configuration.orientation == mThumbnailData.orientation) {
- // If we are in the same orientation as the screenshot, just scale it to the
- // width of the task view
- thumbnailScale = getMeasuredWidth() / thumbnailWidth;
- } else {
- if (FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION) {
- rotate = true;
- // Scale the height (will be width after rotation) to the width of this view
- thumbnailScale = getMeasuredWidth() / thumbnailHeight;
- } else {
- if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
- // Scale the landscape thumbnail up to app size, then scale that to the
- // task view size to match other portrait screenshots
- thumbnailScale = ((float) getMeasuredWidth() / profile.widthPx);
- } else {
- // Otherwise, scale the screenshot to fit 1:1 in the current orientation
- thumbnailScale = 1;
- }
- }
- }
+ getContext().getResources().getConfiguration();
+ // Rotate the screenshot if not in multi-window mode
+ rotate = FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION &&
+ configuration.orientation != mThumbnailData.orientation &&
+ !mActivity.isInMultiWindowModeCompat();
+ // Scale the screenshot to always fit the width of the card.
+ thumbnailScale = rotate
+ ? getMeasuredWidth() / thumbnailHeight
+ : getMeasuredWidth() / thumbnailWidth;
}
+
if (rotate) {
int rotationDir = profile.isVerticalBarLayout() && !profile.isSeascape() ? -1 : 1;
mMatrix.setRotate(90 * rotationDir);
- Rect thumbnailInsets = mThumbnailData.insets;
int newLeftInset = rotationDir == 1 ? thumbnailInsets.bottom : thumbnailInsets.top;
int newTopInset = rotationDir == 1 ? thumbnailInsets.left : thumbnailInsets.right;
mMatrix.postTranslate(-newLeftInset * scale, -newTopInset * scale);
@@ -209,27 +216,11 @@
mMatrix.postScale(thumbnailScale, thumbnailScale);
mBitmapShader.setLocalMatrix(mMatrix);
- Shader shader = mBitmapShader;
- if (!FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION) {
- float bitmapHeight = Math.max(thumbnailHeight * thumbnailScale, 0);
- if (Math.round(bitmapHeight) < getMeasuredHeight()) {
- int color = mPaint.getColor();
- LinearGradient fade = new LinearGradient(
- 0, bitmapHeight - mFadeLength, 0, bitmapHeight,
- color & 0x00FFFFFF, color, Shader.TileMode.CLAMP);
- shader = new ComposeShader(fade, shader, Mode.DST_OVER);
- }
-
- float bitmapWidth = Math.max(thumbnailWidth * thumbnailScale, 0);
- if (Math.round(bitmapWidth) < getMeasuredWidth()) {
- int color = mPaint.getColor();
- LinearGradient fade = new LinearGradient(
- bitmapWidth - mFadeLength, 0, bitmapWidth, 0,
- color & 0x00FFFFFF, color, Shader.TileMode.CLAMP);
- shader = new ComposeShader(fade, shader, Mode.DST_OVER);
- }
+ float bitmapHeight = Math.max(thumbnailHeight * thumbnailScale, 0);
+ if (Math.round(bitmapHeight) < getMeasuredHeight()) {
+ mClipBottom = bitmapHeight;
}
- mPaint.setShader(shader);
+ mPaint.setShader(mBitmapShader);
}
if (rotate) {
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 6f35752..4deed73 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -41,7 +41,7 @@
public final boolean transposeLayoutWithOrientation;
// Device properties in current orientation
- private final boolean isLandscape;
+ public final boolean isLandscape;
public final boolean isMultiWindowMode;
public final int widthPx;