Snap for 8581479 from 5b06002027 to tm-qpr1-release
Change-Id: I7d64d69f9740c3bd16976f6b206d5df68fe3410b
This commit is contained in:
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
-->
|
||||
<resources>
|
||||
<!-- Overview actions -->
|
||||
<dimen name="overview_actions_top_margin">12dp</dimen>
|
||||
<dimen name="overview_grid_side_margin">52dp</dimen>
|
||||
<dimen name="overview_page_spacing">38dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
<resources>
|
||||
<dimen name="navigation_key_padding">25dp</dimen>
|
||||
|
||||
<!-- Task View -->
|
||||
<dimen name="task_thumbnail_icon_size">48dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
|
||||
<dimen name="overview_task_margin">12dp</dimen>
|
||||
<dimen name="overview_task_margin_grid">4dp</dimen>
|
||||
<dimen name="overview_actions_button_spacing">36dp</dimen>
|
||||
<dimen name="overview_grid_side_margin">60dp</dimen>
|
||||
<dimen name="overview_grid_row_spacing">36dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
|
||||
<dimen name="overview_task_margin_grid">12dp</dimen>
|
||||
<dimen name="overview_grid_row_spacing">28dp</dimen>
|
||||
<dimen name="overview_page_spacing">36dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_drawable_size_grid">32dp</dimen>
|
||||
<dimen name="overview_grid_side_margin">64dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
* Copyright (c) 2022, 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.
|
||||
*/
|
||||
-->
|
||||
<resources>
|
||||
<!-- Overview actions -->
|
||||
<dimen name="overview_actions_top_margin">20dp</dimen>
|
||||
</resources>
|
||||
@@ -15,11 +15,13 @@
|
||||
*/
|
||||
-->
|
||||
<resources>
|
||||
<!-- Task View -->
|
||||
<dimen name="task_thumbnail_icon_size">48dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
|
||||
<dimen name="overview_task_margin">16dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
|
||||
<dimen name="overview_task_margin_grid">16dp</dimen>
|
||||
<dimen name="overview_grid_side_margin">64dp</dimen>
|
||||
<dimen name="overview_grid_row_spacing">36dp</dimen>
|
||||
<dimen name="overview_page_spacing">44dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
|
||||
<dimen name="overview_grid_side_margin">64dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<dimen name="task_thumbnail_icon_size">48dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_drawable_size">48dp</dimen>
|
||||
<!-- For screens without rounded corners -->
|
||||
<dimen name="task_corner_radius_small">2dp</dimen>
|
||||
<!-- For Launchers that want to override the default dialog corner radius -->
|
||||
@@ -32,18 +30,20 @@
|
||||
<dimen name="overview_proactive_row_bottom_margin">16dp</dimen>
|
||||
|
||||
<dimen name="overview_minimum_next_prev_size">50dp</dimen>
|
||||
|
||||
<!-- Task View -->
|
||||
<dimen name="task_thumbnail_icon_size">48dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
|
||||
<dimen name="overview_task_margin">16dp</dimen>
|
||||
<dimen name="overview_task_margin_grid">0dp</dimen>
|
||||
<dimen name="overview_page_spacing">16dp</dimen>
|
||||
|
||||
<item name="overview_max_scale" format="float" type="dimen">0.7</item>
|
||||
<item name="overview_modal_max_scale" format="float" type="dimen">1.1</item>
|
||||
|
||||
<!-- Overrideable in overlay that provides the Overview Actions. -->
|
||||
<dimen name="overview_actions_height">48dp</dimen>
|
||||
<dimen name="overview_actions_button_spacing">32dp</dimen>
|
||||
<dimen name="overview_actions_top_margin">24dp</dimen>
|
||||
<dimen name="overview_actions_horizontal_margin">16dp</dimen>
|
||||
|
||||
<dimen name="overview_page_spacing">16dp</dimen>
|
||||
<dimen name="overview_actions_height">48dp</dimen>
|
||||
<dimen name="overview_actions_button_spacing">36dp</dimen>
|
||||
|
||||
<!-- These speeds are in dp/s -->
|
||||
<dimen name="max_task_dismiss_drag_velocity">2.25dp</dimen>
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.launcher3.appprediction;
|
||||
import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKER;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
@@ -38,8 +39,8 @@ public class InstantAppItemInfo extends AppInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorkspaceItemInfo makeWorkspaceItem() {
|
||||
WorkspaceItemInfo workspaceItemInfo = super.makeWorkspaceItem();
|
||||
public WorkspaceItemInfo makeWorkspaceItem(Context context) {
|
||||
WorkspaceItemInfo workspaceItemInfo = super.makeWorkspaceItem(context);
|
||||
workspaceItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
|
||||
workspaceItemInfo.status = WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON
|
||||
| WorkspaceItemInfo.FLAG_RESTORE_STARTED
|
||||
|
||||
@@ -85,7 +85,7 @@ public class PredictionUpdateTask extends BaseModelUpdateTask {
|
||||
.filter(info -> user.equals(info.user) && cn.equals(info.componentName))
|
||||
.map(ai -> {
|
||||
app.getIconCache().getTitleAndIcon(ai, false);
|
||||
return ai.makeWorkspaceItem();
|
||||
return ai.makeWorkspaceItem(context);
|
||||
})
|
||||
.findAny()
|
||||
.orElseGet(() -> {
|
||||
@@ -96,7 +96,7 @@ public class PredictionUpdateTask extends BaseModelUpdateTask {
|
||||
}
|
||||
AppInfo ai = new AppInfo(context, lai, user);
|
||||
app.getIconCache().getTitleAndIcon(ai, lai, false);
|
||||
return ai.makeWorkspaceItem();
|
||||
return ai.makeWorkspaceItem(context);
|
||||
});
|
||||
|
||||
if (itemInfo == null) {
|
||||
|
||||
@@ -460,7 +460,7 @@ public class QuickstepModelDelegate extends ModelDelegate {
|
||||
AppInfo info = new AppInfo(lai, user, mUMS.isUserQuiet(user));
|
||||
mAppState.getIconCache().getTitleAndIcon(info, lai, false);
|
||||
mReadCount++;
|
||||
return info.makeWorkspaceItem();
|
||||
return info.makeWorkspaceItem(mAppState.getContext());
|
||||
}
|
||||
case ITEM_TYPE_DEEP_SHORTCUT: {
|
||||
ShortcutKey key = ShortcutKey.fromIntent(intent, user);
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.android.launcher3.shortcuts.DeepShortcutView;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.LauncherBindableItemsContainer;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
import com.android.launcher3.util.ShortcutUtil;
|
||||
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
@@ -136,7 +137,7 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba
|
||||
return null;
|
||||
}
|
||||
ItemInfo item = (ItemInfo) icon.getTag();
|
||||
if (!PopupContainerWithArrow.canShow(icon, item)) {
|
||||
if (!ShortcutUtil.supportsShortcuts(item)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView {
|
||||
: null;
|
||||
super.applyFromWorkspaceItem(info, animate, staggerIndex);
|
||||
int oldPlateColor = mPlateColor;
|
||||
int newPlateColor = ColorUtils.setAlphaComponent(mDotParams.color, 200);
|
||||
int newPlateColor = ColorUtils.setAlphaComponent(mDotParams.appColor, 200);
|
||||
if (!animate) {
|
||||
mPlateColor = newPlateColor;
|
||||
}
|
||||
|
||||
@@ -66,9 +66,9 @@ public class OverviewState extends LauncherState {
|
||||
@Override
|
||||
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
|
||||
RecentsView recentsView = launcher.getOverviewPanel();
|
||||
float workspacePageWidth = launcher.getDeviceProfile().getWorkspaceWidth();
|
||||
float workspacePageHeight = launcher.getDeviceProfile().getCellLayoutHeight();
|
||||
recentsView.getTaskSize(sTempRect);
|
||||
float scale = (float) sTempRect.width() / workspacePageWidth;
|
||||
float scale = (float) sTempRect.height() / workspacePageHeight;
|
||||
float parallaxFactor = 0.5f;
|
||||
return new ScaleAndTranslation(scale, 0, -getDefaultSwipeHeight(launcher) * parallaxFactor);
|
||||
}
|
||||
|
||||
@@ -222,32 +222,27 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
*/
|
||||
public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) {
|
||||
Resources res = context.getResources();
|
||||
float maxScale = res.getFloat(R.dimen.overview_max_scale);
|
||||
if (dp.isTablet) {
|
||||
Rect gridRect = new Rect();
|
||||
calculateGridSize(dp, gridRect);
|
||||
|
||||
PointF taskDimension = getTaskDimension(context, dp);
|
||||
float scale = gridRect.height() / taskDimension.y;
|
||||
scale = Math.min(scale, res.getFloat(R.dimen.overview_max_scale));
|
||||
int outWidth = Math.round(scale * taskDimension.x);
|
||||
int outHeight = Math.round(scale * taskDimension.y);
|
||||
|
||||
int gravity = Gravity.CENTER;
|
||||
Gravity.apply(gravity, outWidth, outHeight, gridRect, outRect);
|
||||
calculateTaskSizeInternal(context, dp, gridRect, maxScale, Gravity.CENTER, outRect);
|
||||
} else {
|
||||
int taskMargin = dp.overviewTaskMarginPx;
|
||||
calculateTaskSizeInternal(context, dp,
|
||||
dp.overviewTaskThumbnailTopMarginPx,
|
||||
dp.getOverviewActionsClaimedSpace(),
|
||||
res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
|
||||
maxScale,
|
||||
Gravity.CENTER,
|
||||
outRect);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove,
|
||||
int claimedSpaceBelow, int minimumHorizontalPadding, int gravity, Rect outRect) {
|
||||
PointF taskDimension = getTaskDimension(context, dp);
|
||||
int claimedSpaceBelow, int minimumHorizontalPadding, float maxScale, int gravity,
|
||||
Rect outRect) {
|
||||
Rect insets = dp.getInsets();
|
||||
|
||||
Rect potentialTaskRect = new Rect(0, 0, dp.widthPx, dp.heightPx);
|
||||
@@ -258,9 +253,17 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
minimumHorizontalPadding,
|
||||
claimedSpaceBelow);
|
||||
|
||||
calculateTaskSizeInternal(context, dp, potentialTaskRect, maxScale, gravity, outRect);
|
||||
}
|
||||
|
||||
private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
|
||||
Rect potentialTaskRect, float maxScale, int gravity, Rect outRect) {
|
||||
PointF taskDimension = getTaskDimension(context, dp);
|
||||
|
||||
float scale = Math.min(
|
||||
potentialTaskRect.width() / taskDimension.x,
|
||||
potentialTaskRect.height() / taskDimension.y);
|
||||
scale = Math.min(scale, maxScale);
|
||||
int outWidth = Math.round(scale * taskDimension.x);
|
||||
int outHeight = Math.round(scale * taskDimension.y);
|
||||
|
||||
@@ -359,6 +362,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
dp.overviewTaskMarginPx,
|
||||
dp.heightPx - outRect.bottom - dp.getInsets().bottom,
|
||||
Math.round((dp.availableWidthPx - outRect.width() * maxScale) / 2),
|
||||
1f /*maxScale*/,
|
||||
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM,
|
||||
outRect);
|
||||
}
|
||||
|
||||
@@ -418,6 +418,13 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener {
|
||||
return (mSystemUiStateFlags & SYSUI_STATE_BUBBLES_EXPANDED) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether notification panel is expanded
|
||||
*/
|
||||
public boolean isNotificationPanelExpanded() {
|
||||
return (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the global actions dialog is showing
|
||||
*/
|
||||
|
||||
@@ -256,7 +256,7 @@ public class TaskIconCache implements DisplayInfoChangeListener {
|
||||
private BaseIconFactory getIconFactory() {
|
||||
if (mIconFactory == null) {
|
||||
mIconFactory = new BaseIconFactory(mContext,
|
||||
DisplayController.INSTANCE.get(mContext).getInfo().densityDpi,
|
||||
DisplayController.INSTANCE.get(mContext).getInfo().getDensityDpi(),
|
||||
mContext.getResources().getDimensionPixelSize(R.dimen.taskbar_icon_size));
|
||||
}
|
||||
return mIconFactory;
|
||||
|
||||
@@ -700,7 +700,10 @@ public class TouchInteractionService extends Service
|
||||
|
||||
// If Bubbles is expanded, use the overlay input consumer, which will close Bubbles
|
||||
// instead of going all the way home when a swipe up is detected.
|
||||
if (mDeviceState.isBubblesExpanded() || mDeviceState.isSystemUiDialogShowing()) {
|
||||
// Notification panel can be expanded on top of expanded bubbles. Bubbles remain
|
||||
// expanded in the back. Make sure swipe up is not passed to bubbles in this case.
|
||||
if ((mDeviceState.isBubblesExpanded() && !mDeviceState.isNotificationPanelExpanded())
|
||||
|| mDeviceState.isSystemUiDialogShowing()) {
|
||||
base = new SysUiOverlayInputConsumer(
|
||||
getBaseContext(), mDeviceState, mInputMonitorCompat);
|
||||
}
|
||||
|
||||
@@ -159,6 +159,17 @@
|
||||
defaults to 2 * numHotseatIcons -->
|
||||
<attr name="numExtendedHotseatIcons" format="integer" />
|
||||
|
||||
<!-- alignment of hotseat to the grid.
|
||||
Not applicable for 3 button mode when taskbar is enabled -->
|
||||
<!-- defaults to numColumns, if not specified -->
|
||||
<attr name="hotseatColumnSpan" format="integer" />
|
||||
<!-- defaults to numColumns, if not specified -->
|
||||
<attr name="hotseatColumnSpanLandscape" format="integer" />
|
||||
<!-- defaults to numColumns, if not specified -->
|
||||
<attr name="hotseatColumnSpanTwoPanelLandscape" format="integer" />
|
||||
<!-- defaults to numColumns, if not specified -->
|
||||
<attr name="hotseatColumnSpanTwoPanelPortrait" format="integer" />
|
||||
|
||||
<attr name="dbFile" format="string" />
|
||||
<attr name="defaultLayoutId" format="reference" />
|
||||
<attr name="defaultSplitDisplayLayoutId" format="reference" />
|
||||
|
||||
@@ -277,6 +277,9 @@
|
||||
<!-- Summary for Notification dots setting. Tapping this will link enable/disable notification dots feature on the home screen. [CHAR LIMIT=50] -->
|
||||
<string name="notification_dots_service_title">Show notification dots</string>
|
||||
|
||||
<!-- Title for Developer Options setting. [CHAR LIMIT=50] -->
|
||||
<string name="developer_options_title">Developer Options</string>
|
||||
|
||||
<!-- Label for the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=60] -->
|
||||
<string name="auto_add_shortcuts_label">Add app icons to home screen</string>
|
||||
<!-- Text description of the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=NONE] -->
|
||||
|
||||
@@ -144,6 +144,7 @@
|
||||
launcher:numFolderRows="3"
|
||||
launcher:numFolderColumns="3"
|
||||
launcher:numHotseatIcons="6"
|
||||
launcher:hotseatColumnSpanLandscape="4"
|
||||
launcher:numAllAppsColumns="6"
|
||||
launcher:isScalable="true"
|
||||
launcher:devicePaddingId="@xml/paddings_6x5"
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<androidx.preference.PreferenceScreen
|
||||
android:key="pref_developer_options"
|
||||
android:persistent="false"
|
||||
android:title="Developer Options"
|
||||
android:title="@string/developer_options_title"
|
||||
android:fragment="com.android.launcher3.settings.DeveloperOptionsFragment"/>
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
||||
|
||||
@@ -53,6 +53,7 @@ import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
|
||||
import com.android.launcher3.dot.DotInfo;
|
||||
import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
@@ -65,12 +66,11 @@ import com.android.launcher3.icons.cache.HandlerRunnable;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.model.data.SearchActionItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
import com.android.launcher3.util.ShortcutUtil;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.BubbleTextHolder;
|
||||
import com.android.launcher3.views.IconLabelDotView;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
@@ -174,7 +174,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
private HandlerRunnable mIconLoadRequest;
|
||||
|
||||
private boolean mEnableIconUpdateAnimation = false;
|
||||
private BubbleTextHolder mBubbleTextHolder;
|
||||
|
||||
public BubbleTextView(Context context) {
|
||||
this(context, null, 0);
|
||||
@@ -253,7 +252,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
*/
|
||||
public void reset() {
|
||||
mDotInfo = null;
|
||||
mDotParams.color = Color.TRANSPARENT;
|
||||
mDotParams.dotColor = Color.TRANSPARENT;
|
||||
mDotParams.appColor = Color.TRANSPARENT;
|
||||
cancelDotScaleAnim();
|
||||
mDotParams.scale = 0f;
|
||||
mForceHideDot = false;
|
||||
@@ -361,15 +361,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
setDownloadStateContentDescription(info, info.getProgressLevel());
|
||||
}
|
||||
|
||||
private void setItemInfo(ItemInfoWithIcon itemInfo) {
|
||||
protected void setItemInfo(ItemInfoWithIcon itemInfo) {
|
||||
setTag(itemInfo);
|
||||
if (mBubbleTextHolder != null) {
|
||||
mBubbleTextHolder.onItemInfoUpdated(itemInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBubbleTextHolder(BubbleTextHolder bubbleTextHolder) {
|
||||
mBubbleTextHolder = bubbleTextHolder;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@@ -381,7 +374,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
flags |= FLAG_NO_BADGE;
|
||||
}
|
||||
FastBitmapDrawable iconDrawable = info.newIcon(getContext(), flags);
|
||||
mDotParams.color = iconDrawable.getIconColor();
|
||||
mDotParams.appColor = iconDrawable.getIconColor();
|
||||
mDotParams.dotColor = getContext().getResources()
|
||||
.getColor(android.R.color.system_accent3_100, getContext().getTheme());
|
||||
setIcon(iconDrawable);
|
||||
applyLabel(info);
|
||||
}
|
||||
@@ -917,10 +912,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
} else if (info instanceof WorkspaceItemInfo) {
|
||||
applyFromWorkspaceItem((WorkspaceItemInfo) info);
|
||||
mActivity.invalidateParent(info);
|
||||
} else if (info instanceof PackageItemInfo) {
|
||||
applyFromItemInfoWithIcon((PackageItemInfo) info);
|
||||
} else if (info instanceof SearchActionItemInfo) {
|
||||
applyFromItemInfoWithIcon((SearchActionItemInfo) info);
|
||||
} else if (info != null) {
|
||||
applyFromItemInfoWithIcon(info);
|
||||
}
|
||||
|
||||
mDisableRelayout = false;
|
||||
@@ -1058,4 +1051,19 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
args.put("count", notificationCount);
|
||||
return icuCountFormat.format(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a long press action and returns the corresponding pre-drag condition
|
||||
*/
|
||||
public PreDragCondition startLongPressAction() {
|
||||
PopupContainerWithArrow popup = PopupContainerWithArrow.showForIcon(this);
|
||||
return popup != null ? popup.createPreDragCondition(true) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the view can show long-press popup
|
||||
*/
|
||||
public boolean canShowLongPressPopup() {
|
||||
return getTag() instanceof ItemInfo && ShortcutUtil.supportsShortcuts((ItemInfo) getTag());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.folder.PreviewBackground;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.util.CellAndSpan;
|
||||
import com.android.launcher3.util.GridOccupancy;
|
||||
import com.android.launcher3.util.ParcelableSparseArray;
|
||||
@@ -290,7 +291,7 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
for (int i = 0; i < mDragOutlineAnims.length; i++) {
|
||||
final InterruptibleInOutAnimator anim =
|
||||
new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
|
||||
new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
|
||||
anim.getAnimator().setInterpolator(mEaseOutInterpolator);
|
||||
final int thisIndex = i;
|
||||
anim.getAnimator().addUpdateListener(new AnimatorUpdateListener() {
|
||||
@@ -2440,7 +2441,7 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
// First we determine if things have moved enough to cause a different layout
|
||||
ItemConfiguration swapSolution = findReorderSolution(pixelXY[0], pixelXY[1], spanX, spanY,
|
||||
spanX, spanY, direction, dragView, true, new ItemConfiguration());
|
||||
spanX, spanY, direction, dragView, true, new ItemConfiguration());
|
||||
|
||||
setUseTempCoords(true);
|
||||
if (swapSolution != null && swapSolution.isSolution) {
|
||||
@@ -2477,7 +2478,7 @@ public class CellLayout extends ViewGroup {
|
||||
// direction vector, since we want the solution to match the preview, and it's possible
|
||||
// that the exact position of the item has changed to result in a new reordering outcome.
|
||||
if ((mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL || mode == MODE_ACCEPT_DROP)
|
||||
&& mPreviousReorderDirection[0] != INVALID_DIRECTION) {
|
||||
&& mPreviousReorderDirection[0] != INVALID_DIRECTION) {
|
||||
mDirectionVector[0] = mPreviousReorderDirection[0];
|
||||
mDirectionVector[1] = mPreviousReorderDirection[1];
|
||||
// We reset this vector after drop
|
||||
@@ -2493,7 +2494,7 @@ public class CellLayout extends ViewGroup {
|
||||
|
||||
// Find a solution involving pushing / displacing any items in the way
|
||||
ItemConfiguration swapSolution = findReorderSolution(pixelX, pixelY, minSpanX, minSpanY,
|
||||
spanX, spanY, mDirectionVector, dragView, true, new ItemConfiguration());
|
||||
spanX, spanY, mDirectionVector, dragView, true, new ItemConfiguration());
|
||||
|
||||
// We attempt the approach which doesn't shuffle views at all
|
||||
ItemConfiguration noShuffleSolution = findConfigurationNoShuffle(pixelX, pixelY, minSpanX,
|
||||
@@ -2733,12 +2734,24 @@ public class CellLayout extends ViewGroup {
|
||||
}
|
||||
|
||||
public void markCellsAsOccupiedForView(View view) {
|
||||
if (view instanceof LauncherAppWidgetHostView
|
||||
&& view.getTag() instanceof LauncherAppWidgetInfo) {
|
||||
LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) view.getTag();
|
||||
mOccupied.markCells(info.cellX, info.cellY, info.spanX, info.spanY, true);
|
||||
return;
|
||||
}
|
||||
if (view == null || view.getParent() != mShortcutsAndWidgets) return;
|
||||
LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
||||
mOccupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, true);
|
||||
}
|
||||
|
||||
public void markCellsAsUnoccupiedForView(View view) {
|
||||
if (view instanceof LauncherAppWidgetHostView
|
||||
&& view.getTag() instanceof LauncherAppWidgetInfo) {
|
||||
LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) view.getTag();
|
||||
mOccupied.markCells(info.cellX, info.cellY, info.spanX, info.spanY, false);
|
||||
return;
|
||||
}
|
||||
if (view == null || view.getParent() != mShortcutsAndWidgets) return;
|
||||
LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
||||
mOccupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false);
|
||||
|
||||
@@ -158,6 +158,7 @@ public class DeviceProfile {
|
||||
public final int numShownHotseatIcons;
|
||||
public int hotseatCellHeightPx;
|
||||
private final int hotseatExtraVerticalSize;
|
||||
private final boolean areNavButtonsInline;
|
||||
// In portrait: size = height, in landscape: size = width
|
||||
public int hotseatBarSizePx;
|
||||
public int hotseatBarTopPaddingPx;
|
||||
@@ -358,7 +359,7 @@ public class DeviceProfile {
|
||||
|
||||
// We shrink hotseat sizes regardless of orientation, if nav buttons are inline and QSB
|
||||
// might be inline in either orientations, to keep hotseat size consistent across rotation.
|
||||
boolean areNavButtonsInline = isTaskbarPresent && !isGestureMode;
|
||||
areNavButtonsInline = isTaskbarPresent && !isGestureMode;
|
||||
if (areNavButtonsInline && canQsbInline) {
|
||||
numShownHotseatIcons = inv.numShrunkenHotseatIcons;
|
||||
} else {
|
||||
@@ -373,15 +374,14 @@ public class DeviceProfile {
|
||||
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
|
||||
if (isQsbInline) {
|
||||
hotseatBarBottomPaddingPx = res.getDimensionPixelSize(R.dimen.inline_qsb_bottom_margin);
|
||||
qsbWidth = calculateQsbWidth();
|
||||
} else {
|
||||
hotseatBarBottomPaddingPx = (isTallDevice ? res.getDimensionPixelSize(
|
||||
R.dimen.dynamic_grid_hotseat_bottom_tall_padding)
|
||||
: res.getDimensionPixelSize(
|
||||
R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding))
|
||||
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
|
||||
qsbWidth = 0;
|
||||
}
|
||||
|
||||
springLoadedHotseatBarTopMarginPx = res.getDimensionPixelSize(
|
||||
R.dimen.spring_loaded_hotseat_top_margin);
|
||||
hotseatBarSidePaddingEndPx =
|
||||
@@ -390,9 +390,7 @@ public class DeviceProfile {
|
||||
hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
|
||||
hotseatExtraVerticalSize =
|
||||
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
|
||||
hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
|
||||
updateHotseatIconSize(
|
||||
pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
|
||||
updateHotseatIconSize(pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
|
||||
|
||||
qsbBottomMarginOriginalPx = isScalableGrid
|
||||
? res.getDimensionPixelSize(R.dimen.scalable_grid_qsb_bottom_margin)
|
||||
@@ -483,6 +481,10 @@ public class DeviceProfile {
|
||||
cellLayoutPadding);
|
||||
updateWorkspacePadding();
|
||||
|
||||
// Hotseat and QSB width depends on updated cellSize and workspace padding
|
||||
hotseatBorderSpace = calculateHotseatBorderSpace();
|
||||
qsbWidth = calculateQsbWidth();
|
||||
|
||||
flingToDeleteThresholdVelocity = res.getDimensionPixelSize(
|
||||
R.dimen.drag_flingToDeleteMinVelocity);
|
||||
|
||||
@@ -493,14 +495,26 @@ public class DeviceProfile {
|
||||
new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* QSB width is always calculated because when in 3 button nav the width doesn't follow the
|
||||
* width of the hotseat.
|
||||
*/
|
||||
private int calculateQsbWidth() {
|
||||
int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
|
||||
if (isQsbInline) {
|
||||
int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
|
||||
return getIconToIconWidthForColumns(columns)
|
||||
- iconSizePx * numShownHotseatIcons
|
||||
- hotseatBorderSpace * numShownHotseatIcons;
|
||||
} else {
|
||||
int columns = inv.hotseatColumnSpan[mTypeIndex];
|
||||
return getIconToIconWidthForColumns(columns);
|
||||
}
|
||||
}
|
||||
|
||||
return cellWidthPx * columns
|
||||
+ cellLayoutBorderSpacePx.x * (columns - 1)
|
||||
- (cellWidthPx - iconSizePx) // left and right cell space
|
||||
- iconSizePx * numShownHotseatIcons
|
||||
- hotseatBorderSpace * numShownHotseatIcons;
|
||||
private int getIconToIconWidthForColumns(int columns) {
|
||||
return columns * getCellSize().x
|
||||
+ (columns - 1) * cellLayoutBorderSpacePx.x
|
||||
- (getCellSize().x - iconSizePx); // left and right cell space
|
||||
}
|
||||
|
||||
private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
|
||||
@@ -651,11 +665,10 @@ public class DeviceProfile {
|
||||
updateIconSize(1f, res);
|
||||
|
||||
updateWorkspacePadding();
|
||||
Point workspacePadding = getTotalWorkspacePadding();
|
||||
|
||||
// Check to see if the icons fit within the available height.
|
||||
float usedHeight = getCellLayoutHeightSpecification();
|
||||
final int maxHeight = getWorkspaceHeight(workspacePadding);
|
||||
final int maxHeight = getCellLayoutHeight();
|
||||
float extraHeight = Math.max(0, maxHeight - usedHeight);
|
||||
float scaleY = maxHeight / usedHeight;
|
||||
boolean shouldScale = scaleY < 1f;
|
||||
@@ -688,7 +701,7 @@ public class DeviceProfile {
|
||||
}
|
||||
|
||||
private int getCellLayoutWidthSpecification() {
|
||||
int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
|
||||
int numColumns = getPanelCount() * inv.numColumns;
|
||||
return (cellWidthPx * numColumns) + (cellLayoutBorderSpacePx.x * (numColumns - 1))
|
||||
+ cellLayoutPaddingPx.left + cellLayoutPaddingPx.right;
|
||||
}
|
||||
@@ -741,13 +754,6 @@ public class DeviceProfile {
|
||||
// All apps
|
||||
updateAllAppsIconSize(scale, res);
|
||||
|
||||
// Hotseat
|
||||
hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics, scale);
|
||||
if (isQsbInline) {
|
||||
qsbWidth = calculateQsbWidth();
|
||||
} else {
|
||||
qsbWidth = 0;
|
||||
}
|
||||
updateHotseatIconSize(iconSizePx);
|
||||
|
||||
// Folder icon
|
||||
@@ -755,6 +761,23 @@ public class DeviceProfile {
|
||||
folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hotseat width spans a certain number of columns on scalable grids.
|
||||
* This method calculates the space between the icons to achieve that width.
|
||||
*/
|
||||
private int calculateHotseatBorderSpace() {
|
||||
if (!isScalableGrid) return 0;
|
||||
//TODO(http://b/228998082) remove this when 3 button spaces are fixed
|
||||
if (areNavButtonsInline) {
|
||||
return pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
|
||||
} else {
|
||||
int columns = inv.hotseatColumnSpan[mTypeIndex];
|
||||
float hotseatWidthPx = getIconToIconWidthForColumns(columns);
|
||||
float hotseatIconsTotalPx = iconSizePx * numShownHotseatIcons;
|
||||
return (int) (hotseatWidthPx - hotseatIconsTotalPx) / (numShownHotseatIcons - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the iconSize for allApps* variants.
|
||||
@@ -878,18 +901,24 @@ public class DeviceProfile {
|
||||
result = new Point();
|
||||
}
|
||||
|
||||
// Since we are only concerned with the overall padding, layout direction does
|
||||
// not matter.
|
||||
Point padding = getTotalWorkspacePadding();
|
||||
|
||||
int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
|
||||
int screenWidthPx = getWorkspaceWidth(padding);
|
||||
result.x = calculateCellWidth(screenWidthPx, cellLayoutBorderSpacePx.x, numColumns);
|
||||
int screenHeightPx = getWorkspaceHeight(padding);
|
||||
result.y = calculateCellHeight(screenHeightPx, cellLayoutBorderSpacePx.y, inv.numRows);
|
||||
int shortcutAndWidgetContainerWidth =
|
||||
getCellLayoutWidth() - (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right);
|
||||
result.x = calculateCellWidth(shortcutAndWidgetContainerWidth, cellLayoutBorderSpacePx.x,
|
||||
inv.numColumns);
|
||||
int shortcutAndWidgetContainerHeight =
|
||||
getCellLayoutHeight() - (cellLayoutPaddingPx.top + cellLayoutPaddingPx.bottom);
|
||||
result.y = calculateCellHeight(shortcutAndWidgetContainerHeight, cellLayoutBorderSpacePx.y,
|
||||
inv.numRows);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of panels within the workspace.
|
||||
*/
|
||||
public int getPanelCount() {
|
||||
return isTwoPanels ? 2 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the space in px from the bottom of last item in the vertical-bar hotseat to the
|
||||
* bottom of the screen.
|
||||
@@ -908,7 +937,7 @@ public class DeviceProfile {
|
||||
/**
|
||||
* Gets the scaled top of the workspace in px for the spring-loaded edit state.
|
||||
*/
|
||||
public float getWorkspaceSpringLoadShrunkTop() {
|
||||
public float getCellLayoutSpringLoadShrunkTop() {
|
||||
workspaceSpringLoadShrunkTop = mInsets.top + dropTargetBarTopMarginPx + dropTargetBarSizePx
|
||||
+ dropTargetBarBottomMarginPx;
|
||||
return workspaceSpringLoadShrunkTop;
|
||||
@@ -917,7 +946,7 @@ public class DeviceProfile {
|
||||
/**
|
||||
* Gets the scaled bottom of the workspace in px for the spring-loaded edit state.
|
||||
*/
|
||||
private float getWorkspaceSpringLoadShrunkBottom() {
|
||||
private float getCellLayoutSpringLoadShrunkBottom() {
|
||||
int topOfHotseat = hotseatBarSizePx + springLoadedHotseatBarTopMarginPx;
|
||||
workspaceSpringLoadShrunkBottom =
|
||||
heightPx - (isVerticalBarLayout() ? getVerticalHotseatLastItemBottomOffset()
|
||||
@@ -936,13 +965,12 @@ public class DeviceProfile {
|
||||
* Gets the scale of the workspace for the spring-loaded edit state.
|
||||
*/
|
||||
public float getWorkspaceSpringLoadScale() {
|
||||
float cellLayoutHeight = availableHeightPx - workspacePadding.top - workspacePadding.bottom;
|
||||
float scale = (getWorkspaceSpringLoadShrunkBottom() - getWorkspaceSpringLoadShrunkTop())
|
||||
/ cellLayoutHeight;
|
||||
float scale = (getCellLayoutSpringLoadShrunkBottom() - getCellLayoutSpringLoadShrunkTop())
|
||||
/ getCellLayoutHeight();
|
||||
scale = Math.min(scale, 1f);
|
||||
|
||||
// Reduce scale if next pages would not be visible after scaling the workspace
|
||||
int workspaceWidth = getWorkspaceWidth();
|
||||
int workspaceWidth = availableWidthPx;
|
||||
float scaledWorkspaceWidth = workspaceWidth * scale;
|
||||
float maxAvailableWidth =
|
||||
workspaceWidth - (2 * getWorkspaceSpringLoadedMinimumNextPageVisible());
|
||||
@@ -952,19 +980,23 @@ public class DeviceProfile {
|
||||
return scale;
|
||||
}
|
||||
|
||||
public int getWorkspaceWidth() {
|
||||
return getWorkspaceWidth(getTotalWorkspacePadding());
|
||||
/**
|
||||
* Gets the width of a single Cell Layout, aka a single panel within a Workspace.
|
||||
*
|
||||
* <p>This is the width of a Workspace, less its horizontal padding. Note that two-panel
|
||||
* layouts have two Cell Layouts per workspace.
|
||||
*/
|
||||
public int getCellLayoutWidth() {
|
||||
return (availableWidthPx - getTotalWorkspacePadding().x) / getPanelCount();
|
||||
}
|
||||
|
||||
public int getWorkspaceWidth(Point workspacePadding) {
|
||||
int cellLayoutTotalPadding =
|
||||
(isTwoPanels ? 2 : 1) * (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right);
|
||||
return availableWidthPx - workspacePadding.x - cellLayoutTotalPadding;
|
||||
}
|
||||
|
||||
private int getWorkspaceHeight(Point workspacePadding) {
|
||||
return availableHeightPx - workspacePadding.y - (cellLayoutPaddingPx.top
|
||||
+ cellLayoutPaddingPx.bottom);
|
||||
/**
|
||||
* Gets the height of a single Cell Layout, aka a single panel within a Workspace.
|
||||
*
|
||||
* <p>This is the height of a Workspace, less its vertical padding.
|
||||
*/
|
||||
public int getCellLayoutHeight() {
|
||||
return availableHeightPx - getTotalWorkspacePadding().y;
|
||||
}
|
||||
|
||||
public Point getTotalWorkspacePadding() {
|
||||
@@ -1070,6 +1102,13 @@ public class DeviceProfile {
|
||||
mHotseatPadding.left -= diff;
|
||||
mHotseatPadding.right += diff;
|
||||
}
|
||||
} else if (isScalableGrid) {
|
||||
int sideSpacing = (availableWidthPx - qsbWidth) / 2;
|
||||
mHotseatPadding.set(sideSpacing,
|
||||
hotseatBarTopPaddingPx,
|
||||
sideSpacing,
|
||||
hotseatBarSizePx - hotseatCellHeightPx - hotseatBarTopPaddingPx
|
||||
+ mInsets.bottom);
|
||||
} else {
|
||||
// We want the edges of the hotseat to line up with the edges of the workspace, but the
|
||||
// icons in the hotseat are a different size, and so don't line up perfectly. To account
|
||||
@@ -1129,7 +1168,7 @@ public class DeviceProfile {
|
||||
return ((taskbarSize - overviewActionsHeight) / 2) + getTaskbarOffsetY();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return isTaskbarPresent ? stashedTaskbarSize : mInsets.bottom;
|
||||
}
|
||||
|
||||
/** Gets the space that the overview actions will take, including bottom margin. */
|
||||
@@ -1306,6 +1345,7 @@ public class DeviceProfile {
|
||||
writer.println(prefix + pxToDpStr("allAppsLeftRightMargin", allAppsLeftRightMargin));
|
||||
|
||||
writer.println(prefix + pxToDpStr("hotseatBarSizePx", hotseatBarSizePx));
|
||||
writer.println(prefix + "\tinv.hotseatColumnSpan: " + inv.hotseatColumnSpan[mTypeIndex]);
|
||||
writer.println(prefix + pxToDpStr("hotseatCellHeightPx", hotseatCellHeightPx));
|
||||
writer.println(prefix + pxToDpStr("hotseatBarTopPaddingPx", hotseatBarTopPaddingPx));
|
||||
writer.println(prefix + pxToDpStr("hotseatBarBottomPaddingPx", hotseatBarBottomPaddingPx));
|
||||
@@ -1384,7 +1424,7 @@ public class DeviceProfile {
|
||||
private static Context getContext(Context c, Info info, int orientation, WindowBounds bounds) {
|
||||
Configuration config = new Configuration(c.getResources().getConfiguration());
|
||||
config.orientation = orientation;
|
||||
config.densityDpi = info.densityDpi;
|
||||
config.densityDpi = info.getDensityDpi();
|
||||
config.smallestScreenWidthDp = (int) info.smallestSizeDp(bounds);
|
||||
return c.createConfigurationContext(config);
|
||||
}
|
||||
|
||||
@@ -173,17 +173,9 @@ public class Hotseat extends CellLayout implements Insettable {
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
int width;
|
||||
if (mActivity.getDeviceProfile().isQsbInline) {
|
||||
width = mActivity.getDeviceProfile().qsbWidth;
|
||||
} else {
|
||||
MarginLayoutParams qsbParams = (MarginLayoutParams) mQsb.getLayoutParams();
|
||||
width = getShortcutsAndWidgets().getMeasuredWidth()
|
||||
- qsbParams.getMarginStart()
|
||||
- qsbParams.getMarginEnd();
|
||||
}
|
||||
int qsbWidth = mActivity.getDeviceProfile().qsbWidth;
|
||||
|
||||
mQsb.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
||||
mQsb.measure(MeasureSpec.makeMeasureSpec(qsbWidth, MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(mQsbHeight, MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
|
||||
@@ -154,6 +154,8 @@ public class InvariantDeviceProfile {
|
||||
*/
|
||||
public int numDatabaseHotseatIcons;
|
||||
|
||||
public int[] hotseatColumnSpan;
|
||||
|
||||
/**
|
||||
* Number of columns in the all apps list.
|
||||
*/
|
||||
@@ -357,6 +359,7 @@ public class InvariantDeviceProfile {
|
||||
numShrunkenHotseatIcons = closestProfile.numShrunkenHotseatIcons;
|
||||
numDatabaseHotseatIcons = deviceType == TYPE_MULTI_DISPLAY
|
||||
? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons;
|
||||
hotseatColumnSpan = closestProfile.hotseatColumnSpan;
|
||||
hotseatBorderSpaces = displayOption.hotseatBorderSpaces;
|
||||
|
||||
numAllAppsColumns = closestProfile.numAllAppsColumns;
|
||||
@@ -398,7 +401,8 @@ public class InvariantDeviceProfile {
|
||||
// We need to ensure that there is enough extra space in the wallpaper
|
||||
// for the intended parallax effects
|
||||
float parallaxFactor =
|
||||
dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.densityDpi) < 720
|
||||
dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.getDensityDpi())
|
||||
< 720
|
||||
? 2
|
||||
: wallpaperTravelToScreenWidthRatio(displayWidth, displayHeight);
|
||||
defaultWallpaperSize.x =
|
||||
@@ -587,8 +591,8 @@ public class InvariantDeviceProfile {
|
||||
}
|
||||
}
|
||||
|
||||
float width = dpiFromPx(minWidthPx, displayInfo.densityDpi);
|
||||
float height = dpiFromPx(minHeightPx, displayInfo.densityDpi);
|
||||
float width = dpiFromPx(minWidthPx, displayInfo.getDensityDpi());
|
||||
float height = dpiFromPx(minHeightPx, displayInfo.getDensityDpi());
|
||||
|
||||
// Sort the profiles based on the closeness to the device size
|
||||
Collections.sort(points, (a, b) ->
|
||||
@@ -735,6 +739,7 @@ public class InvariantDeviceProfile {
|
||||
private final int numHotseatIcons;
|
||||
private final int numShrunkenHotseatIcons;
|
||||
private final int numDatabaseHotseatIcons;
|
||||
private final int[] hotseatColumnSpan = new int[COUNT_SIZES];
|
||||
|
||||
private final String dbFile;
|
||||
|
||||
@@ -774,6 +779,16 @@ public class InvariantDeviceProfile {
|
||||
R.styleable.GridDisplayOption_numShrunkenHotseatIcons, numHotseatIcons / 2);
|
||||
numDatabaseHotseatIcons = a.getInt(
|
||||
R.styleable.GridDisplayOption_numExtendedHotseatIcons, 2 * numHotseatIcons);
|
||||
hotseatColumnSpan[INDEX_DEFAULT] = a.getInt(
|
||||
R.styleable.GridDisplayOption_hotseatColumnSpan, numColumns);
|
||||
hotseatColumnSpan[INDEX_LANDSCAPE] = a.getInt(
|
||||
R.styleable.GridDisplayOption_hotseatColumnSpanLandscape, numColumns);
|
||||
hotseatColumnSpan[INDEX_TWO_PANEL_LANDSCAPE] = a.getInt(
|
||||
R.styleable.GridDisplayOption_hotseatColumnSpanTwoPanelLandscape,
|
||||
numColumns);
|
||||
hotseatColumnSpan[INDEX_TWO_PANEL_PORTRAIT] = a.getInt(
|
||||
R.styleable.GridDisplayOption_hotseatColumnSpanTwoPanelPortrait,
|
||||
numColumns);
|
||||
|
||||
numFolderRows = a.getInt(
|
||||
R.styleable.GridDisplayOption_numFolderRows, numRows);
|
||||
@@ -821,6 +836,7 @@ public class InvariantDeviceProfile {
|
||||
private float folderBorderSpace;
|
||||
private final PointF[] borderSpaces = new PointF[COUNT_SIZES];
|
||||
private final float[] horizontalMargin = new float[COUNT_SIZES];
|
||||
//TODO(http://b/228998082) remove this when 3 button spaces are fixed
|
||||
private final float[] hotseatBorderSpaces = new float[COUNT_SIZES];
|
||||
|
||||
private final float[] iconSizes = new float[COUNT_SIZES];
|
||||
|
||||
@@ -1169,6 +1169,7 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
}
|
||||
|
||||
AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
|
||||
DragView.removeAllViews(this);
|
||||
TraceHelper.INSTANCE.endSection(traceToken);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,14 +85,12 @@ import com.android.launcher3.logger.LauncherAtom;
|
||||
import com.android.launcher3.logging.InstanceId;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.SearchActionItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemFactory;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.pageindicators.PageIndicator;
|
||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
@@ -1680,11 +1678,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
|
||||
}
|
||||
|
||||
if (child instanceof BubbleTextView && !dragOptions.isAccessibleDrag) {
|
||||
PopupContainerWithArrow<Launcher> popupContainer = PopupContainerWithArrow
|
||||
.showForIcon((BubbleTextView) child);
|
||||
if (popupContainer != null) {
|
||||
dragOptions.preDragCondition = popupContainer.createPreDragCondition(true);
|
||||
}
|
||||
dragOptions.preDragCondition = ((BubbleTextView) child).startLongPressAction();
|
||||
}
|
||||
|
||||
final DragView dv;
|
||||
@@ -2777,9 +2771,9 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION:
|
||||
if (info instanceof AppInfo) {
|
||||
if (info instanceof WorkspaceItemFactory) {
|
||||
// Came from all apps -- make a copy
|
||||
info = ((AppInfo) info).makeWorkspaceItem();
|
||||
info = ((WorkspaceItemFactory) info).makeWorkspaceItem(mLauncher);
|
||||
d.dragInfo = info;
|
||||
}
|
||||
if (info instanceof WorkspaceItemInfo
|
||||
@@ -2788,11 +2782,6 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
|
||||
info = new WorkspaceItemInfo((WorkspaceItemInfo) info);
|
||||
d.dragInfo = info;
|
||||
}
|
||||
if (info instanceof SearchActionItemInfo) {
|
||||
info = ((SearchActionItemInfo) info).createWorkspaceItem(
|
||||
mLauncher.getModel());
|
||||
d.dragInfo = info;
|
||||
}
|
||||
view = mLauncher.createShortcut(cellLayout, (WorkspaceItemInfo) info);
|
||||
break;
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.DropTarget;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.dragndrop.DragController;
|
||||
@@ -31,9 +32,9 @@ import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.BubbleTextHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -72,7 +73,7 @@ public abstract class BaseAccessibilityDelegate<T extends Context & ActivityCont
|
||||
getSupportedActions(host, item, actions);
|
||||
actions.forEach(la -> info.addAction(la.accessibilityAction));
|
||||
|
||||
if (!itemSupportsLongClick(host, item)) {
|
||||
if (!itemSupportsLongClick(host)) {
|
||||
info.setLongClickable(false);
|
||||
info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
|
||||
}
|
||||
@@ -84,8 +85,15 @@ public abstract class BaseAccessibilityDelegate<T extends Context & ActivityCont
|
||||
*/
|
||||
protected abstract void getSupportedActions(View host, ItemInfo item, List<LauncherAction> out);
|
||||
|
||||
private boolean itemSupportsLongClick(View host, ItemInfo info) {
|
||||
return PopupContainerWithArrow.canShow(host, info);
|
||||
private boolean itemSupportsLongClick(View host) {
|
||||
if (host instanceof BubbleTextView) {
|
||||
return ((BubbleTextView) host).canShowLongPressPopup();
|
||||
} else if (host instanceof BubbleTextHolder) {
|
||||
BubbleTextHolder holder = (BubbleTextHolder) host;
|
||||
return holder.getBubbleText() != null && holder.getBubbleText().canShowLongPressPopup();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean itemSupportsAccessibleDrag(ItemInfo item) {
|
||||
@@ -113,7 +121,6 @@ public abstract class BaseAccessibilityDelegate<T extends Context & ActivityCont
|
||||
@Thunk
|
||||
protected void announceConfirmation(String confirmation) {
|
||||
mContext.getDragLayer().announceForAccessibility(confirmation);
|
||||
|
||||
}
|
||||
|
||||
public boolean isInAccessibleDrag() {
|
||||
|
||||
@@ -24,13 +24,14 @@ import com.android.launcher3.PendingAddItemInfo;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
|
||||
import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.keyboard.KeyboardDragAndDropView;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemFactory;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.notification.NotificationListener;
|
||||
import com.android.launcher3.popup.ArrowPopup;
|
||||
@@ -40,6 +41,7 @@ import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.IntSet;
|
||||
import com.android.launcher3.util.ShortcutUtil;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
import com.android.launcher3.views.BubbleTextHolder;
|
||||
import com.android.launcher3.views.OptionsPopupView;
|
||||
import com.android.launcher3.views.OptionsPopupView.OptionItem;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHostView;
|
||||
@@ -118,7 +120,7 @@ public class LauncherAccessibilityDelegate extends BaseAccessibilityDelegate<Lau
|
||||
}
|
||||
}
|
||||
|
||||
if ((item instanceof AppInfo) || (item instanceof WorkspaceItemInfo)
|
||||
if ((item instanceof WorkspaceItemFactory) || (item instanceof WorkspaceItemInfo)
|
||||
|| (item instanceof PendingAddItemInfo)) {
|
||||
out.add(mActions.get(ADD_TO_WORKSPACE));
|
||||
}
|
||||
@@ -143,13 +145,18 @@ public class LauncherAccessibilityDelegate extends BaseAccessibilityDelegate<Lau
|
||||
protected boolean performAction(final View host, final ItemInfo item, int action,
|
||||
boolean fromKeyboard) {
|
||||
if (action == ACTION_LONG_CLICK) {
|
||||
if (PopupContainerWithArrow.canShow(host, item)) {
|
||||
// Long press should be consumed for workspace items, and it should invoke the
|
||||
// Shortcuts / Notifications / Actions pop-up menu, and not start a drag as the
|
||||
// standard long press path does.
|
||||
PopupContainerWithArrow.showForIcon((BubbleTextView) host);
|
||||
return true;
|
||||
PreDragCondition dragCondition = null;
|
||||
// Long press should be consumed for workspace items, and it should invoke the
|
||||
// Shortcuts / Notifications / Actions pop-up menu, and not start a drag as the
|
||||
// standard long press path does.
|
||||
if (host instanceof BubbleTextView) {
|
||||
dragCondition = ((BubbleTextView) host).startLongPressAction();
|
||||
} else if (host instanceof BubbleTextHolder) {
|
||||
BubbleTextHolder holder = (BubbleTextHolder) host;
|
||||
dragCondition = holder.getBubbleText() == null ? null
|
||||
: holder.getBubbleText().startLongPressAction();
|
||||
}
|
||||
return dragCondition != null;
|
||||
} else if (action == MOVE) {
|
||||
return beginAccessibleDrag(host, item, fromKeyboard);
|
||||
} else if (action == ADD_TO_WORKSPACE) {
|
||||
@@ -166,7 +173,10 @@ public class LauncherAccessibilityDelegate extends BaseAccessibilityDelegate<Lau
|
||||
popup.setOnCloseCallback(host::requestFocus);
|
||||
return true;
|
||||
} else if (action == DEEP_SHORTCUTS || action == SHORTCUTS_AND_NOTIFICATIONS) {
|
||||
return PopupContainerWithArrow.showForIcon((BubbleTextView) host) != null;
|
||||
BubbleTextView btv = host instanceof BubbleTextView ? (BubbleTextView) host
|
||||
: (host instanceof BubbleTextHolder
|
||||
? ((BubbleTextHolder) host).getBubbleText() : null);
|
||||
return btv != null && PopupContainerWithArrow.showForIcon(btv) != null;
|
||||
} else {
|
||||
for (ButtonDropTarget dropTarget : mContext.getDropTargetBar().getDropTargets()) {
|
||||
if (dropTarget.supportsAccessibilityDrop(item, host)
|
||||
@@ -367,8 +377,8 @@ public class LauncherAccessibilityDelegate extends BaseAccessibilityDelegate<Lau
|
||||
return false;
|
||||
}
|
||||
mContext.getStateManager().goToState(NORMAL, true, forSuccessCallback(() -> {
|
||||
if (item instanceof AppInfo) {
|
||||
WorkspaceItemInfo info = ((AppInfo) item).makeWorkspaceItem();
|
||||
if (item instanceof WorkspaceItemFactory) {
|
||||
WorkspaceItemInfo info = ((WorkspaceItemFactory) item).makeWorkspaceItem(mContext);
|
||||
mContext.getModelWriter().addItemToDatabase(info,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
||||
screenId, coordinates[0], coordinates[1]);
|
||||
|
||||
@@ -228,6 +228,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
||||
requestFocus();
|
||||
mgr.logger().sendToInteractionJankMonitor(
|
||||
LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN, this);
|
||||
hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
|
||||
getApplicationWindowToken());
|
||||
break;
|
||||
case SCROLL_STATE_IDLE:
|
||||
mgr.logger().sendToInteractionJankMonitor(
|
||||
@@ -243,8 +245,6 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
||||
&& mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) {
|
||||
mEmptySearchBackground.setHotspot(e.getX(), e.getY());
|
||||
}
|
||||
hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
|
||||
getApplicationWindowToken());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.android.launcher3.allapps;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB;
|
||||
import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -458,6 +459,8 @@ public abstract class BaseAllAppsContainerView<T extends Context & ActivityConte
|
||||
mActivityContext.getStatsLogManager().logger()
|
||||
.log(LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB);
|
||||
}
|
||||
hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
|
||||
getApplicationWindowToken());
|
||||
});
|
||||
findViewById(R.id.tab_work)
|
||||
.setOnClickListener((View view) -> {
|
||||
@@ -465,6 +468,8 @@ public abstract class BaseAllAppsContainerView<T extends Context & ActivityConte
|
||||
mActivityContext.getStatsLogManager().logger()
|
||||
.log(LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB);
|
||||
}
|
||||
hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
|
||||
getApplicationWindowToken());
|
||||
});
|
||||
setDeviceManagementResources();
|
||||
onActivePageChanged(mViewPager.getNextPage());
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.android.launcher3.anim;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
|
||||
/**
|
||||
* Extension of {@link AnimatorListenerAdapter} for listening for non-cancelled animations
|
||||
*/
|
||||
@@ -27,6 +29,7 @@ public abstract class AnimationSuccessListener extends AnimatorListenerAdapter {
|
||||
protected boolean mCancelled = false;
|
||||
|
||||
@Override
|
||||
@CallSuper
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
mCancelled = true;
|
||||
}
|
||||
|
||||
@@ -578,4 +578,19 @@ public abstract class DragView<T extends Context & ActivityContext> extends Fram
|
||||
iv.setImageDrawable(drawable);
|
||||
return iv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes any stray DragView from the DragLayer.
|
||||
*/
|
||||
public static void removeAllViews(ActivityContext activity) {
|
||||
BaseDragLayer dragLayer = activity.getDragLayer();
|
||||
// Iterate in reverse order. DragView is added later to the dragLayer,
|
||||
// and will be one of the last views.
|
||||
for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
|
||||
View child = dragLayer.getChildAt(i);
|
||||
if (child instanceof DragView) {
|
||||
dragLayer.removeView(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,10 +88,10 @@ import com.android.launcher3.logger.LauncherAtom.FromState;
|
||||
import com.android.launcher3.logger.LauncherAtom.ToState;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo.FolderListener;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemFactory;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.pageindicators.PageIndicatorDots;
|
||||
import com.android.launcher3.util.Executors;
|
||||
@@ -1283,9 +1283,9 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
|
||||
final WorkspaceItemInfo si;
|
||||
if (pasiSi != null) {
|
||||
si = pasiSi;
|
||||
} else if (d.dragInfo instanceof AppInfo) {
|
||||
} else if (d.dragInfo instanceof WorkspaceItemFactory) {
|
||||
// Came from all apps -- make a copy.
|
||||
si = ((AppInfo) d.dragInfo).makeWorkspaceItem();
|
||||
si = ((WorkspaceItemFactory) d.dragInfo).makeWorkspaceItem(launcher);
|
||||
} else {
|
||||
// WorkspaceItemInfo
|
||||
si = (WorkspaceItemInfo) d.dragInfo;
|
||||
|
||||
@@ -68,11 +68,11 @@ import com.android.launcher3.logger.LauncherAtom.FromState;
|
||||
import com.android.launcher3.logger.LauncherAtom.ToState;
|
||||
import com.android.launcher3.logging.InstanceId;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo.FolderListener;
|
||||
import com.android.launcher3.model.data.FolderInfo.LabelState;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemFactory;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.util.Executors;
|
||||
@@ -284,7 +284,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
||||
mBackground.animateToAccept(cl, lp.cellX, lp.cellY);
|
||||
mOpenAlarm.setOnAlarmListener(mOnOpenListener);
|
||||
if (SPRING_LOADING_ENABLED &&
|
||||
((dragInfo instanceof AppInfo)
|
||||
((dragInfo instanceof WorkspaceItemFactory)
|
||||
|| (dragInfo instanceof WorkspaceItemInfo)
|
||||
|| (dragInfo instanceof PendingAddShortcutInfo))) {
|
||||
mOpenAlarm.setAlarm(ON_OPEN_DELAY);
|
||||
@@ -486,9 +486,9 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
||||
|
||||
public void onDrop(DragObject d, boolean itemReturnedOnFailedDrop) {
|
||||
WorkspaceItemInfo item;
|
||||
if (d.dragInfo instanceof AppInfo) {
|
||||
if (d.dragInfo instanceof WorkspaceItemFactory) {
|
||||
// Came from all apps -- make a copy
|
||||
item = ((AppInfo) d.dragInfo).makeWorkspaceItem();
|
||||
item = ((WorkspaceItemFactory) d.dragInfo).makeWorkspaceItem(getContext());
|
||||
} else if (d.dragSource instanceof BaseItemDragListener){
|
||||
// Came from a different window -- make a copy
|
||||
item = new WorkspaceItemInfo((WorkspaceItemInfo) d.dragInfo);
|
||||
@@ -637,7 +637,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
||||
|
||||
// If we are animating to the accepting state, animate the dot out.
|
||||
mDotParams.scale = Math.max(0, mDotScale - mBackground.getScaleProgress());
|
||||
mDotParams.color = mBackground.getDotColor();
|
||||
mDotParams.dotColor = mBackground.getDotColor();
|
||||
mDotRenderer.draw(canvas, mDotParams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemFactory;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.pm.InstallSessionHelper;
|
||||
import com.android.launcher3.pm.PackageInstallInfo;
|
||||
@@ -107,8 +108,8 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
|
||||
}
|
||||
|
||||
if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
|
||||
if (item instanceof AppInfo) {
|
||||
item = ((AppInfo) item).makeWorkspaceItem();
|
||||
if (item instanceof WorkspaceItemFactory) {
|
||||
item = ((WorkspaceItemFactory) item).makeWorkspaceItem(app.getContext());
|
||||
}
|
||||
}
|
||||
if (item != null) {
|
||||
@@ -130,8 +131,8 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
|
||||
if (item instanceof WorkspaceItemInfo || item instanceof FolderInfo ||
|
||||
item instanceof LauncherAppWidgetInfo) {
|
||||
itemInfo = item;
|
||||
} else if (item instanceof AppInfo) {
|
||||
itemInfo = ((AppInfo) item).makeWorkspaceItem();
|
||||
} else if (item instanceof WorkspaceItemFactory) {
|
||||
itemInfo = ((WorkspaceItemFactory) item).makeWorkspaceItem(app.getContext());
|
||||
} else {
|
||||
throw new RuntimeException("Unexpected info type");
|
||||
}
|
||||
@@ -180,7 +181,7 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
|
||||
// App was installed while launcher was in the background,
|
||||
// or app was already installed for another user.
|
||||
itemInfo = new AppInfo(app.getContext(), activities.get(0), item.user)
|
||||
.makeWorkspaceItem();
|
||||
.makeWorkspaceItem(app.getContext());
|
||||
|
||||
if (shortcutExists(dataModel, itemInfo.getIntent(), itemInfo.user)) {
|
||||
// We need this additional check here since we treat all auto added
|
||||
|
||||
@@ -35,7 +35,6 @@ import androidx.annotation.VisibleForTesting;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.pm.PackageInstallInfo;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
|
||||
import java.util.Comparator;
|
||||
@@ -43,7 +42,7 @@ import java.util.Comparator;
|
||||
/**
|
||||
* Represents an app in AllAppsView.
|
||||
*/
|
||||
public class AppInfo extends ItemInfoWithIcon {
|
||||
public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
|
||||
|
||||
public static final AppInfo[] EMPTY_ARRAY = new AppInfo[0];
|
||||
public static final Comparator<AppInfo> COMPONENT_KEY_COMPARATOR = (a, b) -> {
|
||||
@@ -121,7 +120,8 @@ public class AppInfo extends ItemInfoWithIcon {
|
||||
return super.dumpProperties() + " componentName=" + componentName;
|
||||
}
|
||||
|
||||
public WorkspaceItemInfo makeWorkspaceItem() {
|
||||
@Override
|
||||
public WorkspaceItemInfo makeWorkspaceItem(Context context) {
|
||||
WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(this);
|
||||
|
||||
if ((runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) {
|
||||
@@ -139,10 +139,6 @@ public class AppInfo extends ItemInfoWithIcon {
|
||||
return workspaceItemInfo;
|
||||
}
|
||||
|
||||
public ComponentKey toComponentKey() {
|
||||
return new ComponentKey(componentName, user);
|
||||
}
|
||||
|
||||
public static Intent makeLaunchIntent(LauncherActivityInfo info) {
|
||||
return makeLaunchIntent(info.getComponentName());
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.launcher3.model.data;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.EXTENDED_CONTAINERS;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Process;
|
||||
@@ -26,18 +27,14 @@ import android.os.UserHandle;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherModel;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.logger.LauncherAtom.ItemInfo;
|
||||
import com.android.launcher3.logger.LauncherAtom.SearchActionItem;
|
||||
import com.android.launcher3.model.AllAppsList;
|
||||
import com.android.launcher3.model.BaseModelUpdateTask;
|
||||
import com.android.launcher3.model.BgDataModel;
|
||||
|
||||
/**
|
||||
* Represents a SearchAction with in launcher
|
||||
*/
|
||||
public class SearchActionItemInfo extends ItemInfoWithIcon {
|
||||
public class SearchActionItemInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
|
||||
|
||||
public static final int FLAG_SHOULD_START = 1 << 1;
|
||||
public static final int FLAG_SHOULD_START_FOR_RESULT = FLAG_SHOULD_START | 1 << 2;
|
||||
@@ -158,7 +155,8 @@ public class SearchActionItemInfo extends ItemInfoWithIcon {
|
||||
/**
|
||||
* Creates a {@link WorkspaceItemInfo} coorsponding to search action to be stored in launcher db
|
||||
*/
|
||||
public WorkspaceItemInfo createWorkspaceItem(LauncherModel model) {
|
||||
@Override
|
||||
public WorkspaceItemInfo makeWorkspaceItem(Context context) {
|
||||
WorkspaceItemInfo info = new WorkspaceItemInfo();
|
||||
info.title = title;
|
||||
info.bitmap = bitmap;
|
||||
@@ -167,18 +165,12 @@ public class SearchActionItemInfo extends ItemInfoWithIcon {
|
||||
if (hasFlags(FLAG_SHOULD_START_FOR_RESULT)) {
|
||||
info.options |= WorkspaceItemInfo.FLAG_START_FOR_RESULT;
|
||||
}
|
||||
|
||||
model.enqueueModelUpdateTask(new BaseModelUpdateTask() {
|
||||
@Override
|
||||
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
|
||||
|
||||
model.updateAndBindWorkspaceItem(() -> {
|
||||
PackageItemInfo pkgInfo = new PackageItemInfo(getIntentPackageName(), user);
|
||||
app.getIconCache().getTitleAndIconForApp(pkgInfo, false);
|
||||
info.bitmap = info.bitmap.withBadgeInfo(pkgInfo.bitmap);
|
||||
return info;
|
||||
});
|
||||
}
|
||||
LauncherAppState app = LauncherAppState.getInstance(context);
|
||||
app.getModel().updateAndBindWorkspaceItem(() -> {
|
||||
PackageItemInfo pkgInfo = new PackageItemInfo(getIntentPackageName(), user);
|
||||
app.getIconCache().getTitleAndIconForApp(pkgInfo, false);
|
||||
info.bitmap = info.bitmap.withBadgeInfo(pkgInfo.bitmap);
|
||||
return info;
|
||||
});
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.model.data;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* Interface to objects capable of generating workspace item
|
||||
*/
|
||||
public interface WorkspaceItemFactory {
|
||||
|
||||
/**
|
||||
* Called to create a pinnable item info
|
||||
*/
|
||||
WorkspaceItemInfo makeWorkspaceItem(Context context);
|
||||
}
|
||||
@@ -187,7 +187,10 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
|
||||
/**
|
||||
* Returns true if we can show the container.
|
||||
*
|
||||
* @deprecated Left here since some dependent projects are using this method
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean canShow(View icon, ItemInfo item) {
|
||||
return icon instanceof BubbleTextView && ShortcutUtil.supportsShortcuts(item);
|
||||
}
|
||||
@@ -204,7 +207,7 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
return null;
|
||||
}
|
||||
ItemInfo item = (ItemInfo) icon.getTag();
|
||||
if (!canShow(icon, item)) {
|
||||
if (!ShortcutUtil.supportsShortcuts(item)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -538,7 +541,7 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
public static void dismissInvalidPopup(BaseDraggingActivity activity) {
|
||||
PopupContainerWithArrow popup = getOpen(activity);
|
||||
if (popup != null && (!popup.mOriginalIcon.isAttachedToWindow()
|
||||
|| !canShow(popup.mOriginalIcon, (ItemInfo) popup.mOriginalIcon.getTag()))) {
|
||||
|| !ShortcutUtil.supportsShortcuts((ItemInfo) popup.mOriginalIcon.getTag()))) {
|
||||
popup.animateClose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +335,13 @@ public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
// Change the internal state only when the transition actually starts
|
||||
onStateTransitionStart(state);
|
||||
onStateTransitionStart(mCancelled ? mCurrentStableState : state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
super.onAnimationCancel(animation);
|
||||
mState = mCurrentStableState;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -51,7 +51,7 @@ public class SpringLoadedState extends LauncherState {
|
||||
return super.getWorkspaceScaleAndTranslation(launcher);
|
||||
}
|
||||
|
||||
float shrunkTop = grid.getWorkspaceSpringLoadShrunkTop();
|
||||
float shrunkTop = grid.getCellLayoutSpringLoadShrunkTop();
|
||||
float scale = grid.getWorkspaceSpringLoadScale();
|
||||
|
||||
float halfHeight = ws.getHeight() / 2;
|
||||
|
||||
@@ -100,8 +100,7 @@ public class ItemClickHandler {
|
||||
onClickFolderIcon(v);
|
||||
}
|
||||
} else if (tag instanceof AppInfo) {
|
||||
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher
|
||||
);
|
||||
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);
|
||||
} else if (tag instanceof LauncherAppWidgetInfo) {
|
||||
if (v instanceof PendingAppWidgetHostView) {
|
||||
onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.android.launcher3.logging.StatsLogManager.StatsLogger;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.views.BubbleTextHolder;
|
||||
|
||||
/**
|
||||
* Class to handle long-clicks on workspace items and start drag as a result.
|
||||
@@ -79,9 +80,12 @@ public class ItemLongClickListener {
|
||||
launcher.getWorkspace().startDrag(longClickCellInfo, dragOptions);
|
||||
}
|
||||
|
||||
private static boolean onAllAppsItemLongClick(View v) {
|
||||
private static boolean onAllAppsItemLongClick(View view) {
|
||||
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onAllAppsItemLongClick");
|
||||
v.cancelLongPress();
|
||||
view.cancelLongPress();
|
||||
View v = (view instanceof BubbleTextHolder)
|
||||
? ((BubbleTextHolder) view).getBubbleText()
|
||||
: view;
|
||||
Launcher launcher = Launcher.getLauncher(v.getContext());
|
||||
if (!canStartDrag(launcher)) return false;
|
||||
// When we have exited all apps or are in transition, disregard long clicks
|
||||
|
||||
@@ -290,7 +290,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
|
||||
|
||||
// Configuration property
|
||||
public final float fontScale;
|
||||
public final int densityDpi;
|
||||
private final int densityDpi;
|
||||
public final NavigationMode navigationMode;
|
||||
|
||||
private final PortraitSize mScreenSizeDp;
|
||||
@@ -357,6 +357,10 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
|
||||
public float smallestSizeDp(WindowBounds bounds) {
|
||||
return dpiFromPx(Math.min(bounds.bounds.width(), bounds.bounds.height()), densityDpi);
|
||||
}
|
||||
|
||||
public int getDensityDpi() {
|
||||
return densityDpi;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
package com.android.launcher3.views;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
|
||||
/**
|
||||
* Views that contain {@link BubbleTextView} should implement this interface.
|
||||
@@ -25,14 +23,6 @@ import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
public interface BubbleTextHolder extends IconLabelDotView {
|
||||
BubbleTextView getBubbleText();
|
||||
|
||||
/**
|
||||
* Called when new {@link ItemInfo} is set to {@link BubbleTextView}
|
||||
*
|
||||
* @param itemInfo the new itemInfo
|
||||
*/
|
||||
default void onItemInfoUpdated(ItemInfoWithIcon itemInfo) {
|
||||
}
|
||||
|
||||
@Override
|
||||
default void setIconVisible(boolean visible) {
|
||||
getBubbleText().setIconVisible(visible);
|
||||
|
||||
@@ -20,6 +20,8 @@ import static android.view.HapticFeedbackConstants.CLOCK_TICK;
|
||||
|
||||
import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
|
||||
|
||||
import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
@@ -283,6 +285,9 @@ public class RecyclerViewFastScroller extends View {
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
|
||||
getApplicationWindowToken());
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
mRv.onFastScrollCompleted();
|
||||
mTouchOffsetY = 0;
|
||||
|
||||
@@ -64,6 +64,7 @@ abstract class DeviceProfileBaseTest {
|
||||
windowBounds = WindowBounds(x, y, x, y - 100, 0)
|
||||
|
||||
whenever(info.isTablet(any())).thenReturn(false)
|
||||
whenever(info.getDensityDpi()).thenReturn(560)
|
||||
|
||||
inv = newScalableInvariantDeviceProfile()
|
||||
}
|
||||
@@ -77,6 +78,7 @@ abstract class DeviceProfileBaseTest {
|
||||
windowBounds = WindowBounds(x, y, x, y - 100, 0)
|
||||
|
||||
whenever(info.isTablet(any())).thenReturn(true)
|
||||
whenever(info.getDensityDpi()).thenReturn(320)
|
||||
|
||||
inv = newScalableInvariantDeviceProfile()
|
||||
}
|
||||
@@ -107,6 +109,7 @@ abstract class DeviceProfileBaseTest {
|
||||
PointF(16f, 16f)
|
||||
).toTypedArray()
|
||||
hotseatBorderSpaces = FloatArray(4) { 16f }
|
||||
hotseatColumnSpan = IntArray(4) { 4 }
|
||||
iconSize = FloatArray(4) { 56f }
|
||||
allAppsIconSize = FloatArray(4) { 56f }
|
||||
iconTextSize = FloatArray(4) { 14f }
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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
|
||||
|
||||
import android.graphics.PointF
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.launcher3.util.WindowBounds
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
/**
|
||||
* Test for [DeviceProfile] grid dimensions.
|
||||
*
|
||||
* This includes workspace, cell layout, shortcut and widget container, cell sizes, etc.
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class DeviceProfileGridDimensionsTest : DeviceProfileBaseTest() {
|
||||
|
||||
@Test
|
||||
fun getCellLayoutWidth_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelWidth() {
|
||||
val tabletWidth = 2560
|
||||
val tabletHeight = 1600
|
||||
val availableWidth = 2560
|
||||
val availableHeight = 1500
|
||||
windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
|
||||
useTwoPanels = true
|
||||
whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
|
||||
whenever(info.densityDpi).thenReturn(320)
|
||||
inv = newScalableInvariantDeviceProfile()
|
||||
|
||||
val dp = newDP()
|
||||
|
||||
val expectedWorkspaceWidth = availableWidth
|
||||
val expectedCellLayoutWidth =
|
||||
(expectedWorkspaceWidth - (dp.workspacePadding.right + dp.workspacePadding.left)) /
|
||||
dp.panelCount
|
||||
assertThat(dp.cellLayoutWidth).isEqualTo(expectedCellLayoutWidth)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getCellLayoutHeight_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelHeight() {
|
||||
val tabletWidth = 2560
|
||||
val tabletHeight = 1600
|
||||
val availableWidth = 2560
|
||||
val availableHeight = 1500
|
||||
windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
|
||||
useTwoPanels = true
|
||||
whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
|
||||
whenever(info.densityDpi).thenReturn(320)
|
||||
inv = newScalableInvariantDeviceProfile()
|
||||
|
||||
val dp = newDP()
|
||||
|
||||
val expectedWorkspaceHeight = availableHeight
|
||||
val expectedCellLayoutHeight =
|
||||
expectedWorkspaceHeight - (dp.workspacePadding.top + dp.workspacePadding.bottom)
|
||||
assertThat(dp.cellLayoutHeight).isEqualTo(expectedCellLayoutHeight)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getCellSize_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelWidth() {
|
||||
val tabletWidth = 2560
|
||||
val tabletHeight = 1600
|
||||
val availableWidth = 2560
|
||||
val availableHeight = 1500
|
||||
windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
|
||||
useTwoPanels = true
|
||||
whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
|
||||
whenever(info.densityDpi).thenReturn(320)
|
||||
inv = newScalableInvariantDeviceProfile()
|
||||
|
||||
val dp = newDP()
|
||||
|
||||
val expectedWorkspaceWidth = availableWidth
|
||||
val expectedCellLayoutWidth =
|
||||
(expectedWorkspaceWidth - (dp.workspacePadding.right + dp.workspacePadding.left)) /
|
||||
dp.panelCount
|
||||
val expectedShortcutAndWidgetContainerWidth =
|
||||
expectedCellLayoutWidth -
|
||||
(dp.cellLayoutPaddingPx.left + dp.cellLayoutPaddingPx.right)
|
||||
assertThat(dp.getCellSize().x).isEqualTo(
|
||||
(expectedShortcutAndWidgetContainerWidth -
|
||||
((inv!!.numColumns - 1) * dp.cellLayoutBorderSpacePx.x)) / inv!!.numColumns)
|
||||
val expectedWorkspaceHeight = availableHeight
|
||||
val expectedCellLayoutHeight =
|
||||
expectedWorkspaceHeight - (dp.workspacePadding.top + dp.workspacePadding.bottom)
|
||||
val expectedShortcutAndWidgetContainerHeight = expectedCellLayoutHeight -
|
||||
(dp.cellLayoutPaddingPx.top + dp.cellLayoutPaddingPx.bottom)
|
||||
assertThat(dp.getCellSize().y).isEqualTo(
|
||||
(expectedShortcutAndWidgetContainerHeight -
|
||||
((inv!!.numRows - 1) * dp.cellLayoutBorderSpacePx.y)) / inv!!.numRows)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPanelCount_twoPanelLandscapeScalable4By4GridTablet_equalsTwoPanels() {
|
||||
val tabletWidth = 2560
|
||||
val tabletHeight = 1600
|
||||
val availableWidth = 2560
|
||||
val availableHeight = 1500
|
||||
windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
|
||||
useTwoPanels = true
|
||||
whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
|
||||
whenever(info.densityDpi).thenReturn(320)
|
||||
inv = newScalableInvariantDeviceProfile()
|
||||
|
||||
val dp = newDP()
|
||||
|
||||
assertThat(dp.panelCount).isEqualTo(2)
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -23,15 +23,13 @@ import com.android.launcher3.InvariantDeviceProfile.TYPE_TABLET
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
/**
|
||||
* Test for [DeviceProfile]
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class HotseatSizeTest : DeviceProfileBaseTest() {
|
||||
class HotseatShownIconsTest : DeviceProfileBaseTest() {
|
||||
|
||||
@Test
|
||||
fun hotseat_size_is_normal_for_handhelds() {
|
||||
@@ -29,17 +29,16 @@ import org.junit.runner.RunWith
|
||||
class InlineQsbTest : DeviceProfileBaseTest() {
|
||||
|
||||
@Test
|
||||
fun qsbWidth_is_match_parent_for_phones() {
|
||||
fun qsb_is_not_inline_for_phones() {
|
||||
initializeVarsForPhone()
|
||||
|
||||
val dp = newDP()
|
||||
|
||||
assertThat(dp.isQsbInline).isFalse()
|
||||
assertThat(dp.qsbWidth).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun qsbWidth_is_match_parent_for_tablet_portrait() {
|
||||
fun qsb_is_inline_for_tablet_portrait() {
|
||||
initializeVarsForTablet()
|
||||
inv = newScalableInvariantDeviceProfile().apply {
|
||||
inlineQsb = booleanArrayOf(
|
||||
@@ -62,11 +61,10 @@ class InlineQsbTest : DeviceProfileBaseTest() {
|
||||
)
|
||||
|
||||
assertThat(dp.isQsbInline).isFalse()
|
||||
assertThat(dp.qsbWidth).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun qsbWidth_has_size_for_tablet_landscape() {
|
||||
fun qsb_is_inline_for_tablet_landscape() {
|
||||
initializeVarsForTablet(isLandscape = true)
|
||||
inv = newScalableInvariantDeviceProfile().apply {
|
||||
inlineQsb = booleanArrayOf(
|
||||
@@ -75,16 +73,17 @@ class InlineQsbTest : DeviceProfileBaseTest() {
|
||||
false,
|
||||
false
|
||||
)
|
||||
numColumns = 6
|
||||
numRows = 5
|
||||
numShownHotseatIcons = 6
|
||||
}
|
||||
|
||||
val dp = newDP()
|
||||
|
||||
if (dp.hotseatQsbHeight > 0) {
|
||||
assertThat(dp.isQsbInline).isTrue()
|
||||
assertThat(dp.qsbWidth).isGreaterThan(0)
|
||||
} else { // Launcher3 doesn't have QSB height
|
||||
assertThat(dp.isQsbInline).isFalse()
|
||||
assertThat(dp.qsbWidth).isEqualTo(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,14 +91,13 @@ class InlineQsbTest : DeviceProfileBaseTest() {
|
||||
* This test is to make sure that a tablet doesn't inline the QSB if the layout doesn't support
|
||||
*/
|
||||
@Test
|
||||
fun qsbWidth_is_match_parent_for_tablet_landscape_without_inline() {
|
||||
fun qsb_is_not_inline_for_tablet_landscape_without_inline() {
|
||||
initializeVarsForTablet(isLandscape = true)
|
||||
useTwoPanels = true
|
||||
|
||||
val dp = newDP()
|
||||
|
||||
assertThat(dp.isQsbInline).isFalse()
|
||||
assertThat(dp.qsbWidth).isEqualTo(0)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -135,7 +135,7 @@ public class DeviceEmulationData {
|
||||
resourceOverrides.put(s, getDimenByName(s, context.getResources(), 0));
|
||||
}
|
||||
return new DeviceEmulationData(info.currentSize.x, info.currentSize.y,
|
||||
info.densityDpi, info.cutout, code, grids, resourceOverrides);
|
||||
info.getDensityDpi(), info.cutout, code, grids, resourceOverrides);
|
||||
}
|
||||
|
||||
public static DeviceEmulationData getDevice(String deviceCode) throws Exception {
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.launcher3.tapl;
|
||||
|
||||
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
|
||||
|
||||
import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
|
||||
|
||||
import android.graphics.Point;
|
||||
@@ -64,35 +62,25 @@ public abstract class Launchable {
|
||||
protected abstract String launchableType();
|
||||
|
||||
private LaunchedAppState launch(BySelector selector) {
|
||||
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
|
||||
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
|
||||
"want to launch an app from " + launchableType())) {
|
||||
LauncherInstrumentation.log("Launchable.launch before click "
|
||||
+ mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
|
||||
final String label = mObject.getText();
|
||||
|
||||
executeAndWaitForWindowChange(() -> {
|
||||
mLauncher.clickLauncherObject(mObject);
|
||||
expectActivityStartEvents();
|
||||
}, label, "clicking " + launchableType());
|
||||
mLauncher.clickLauncherObject(mObject);
|
||||
|
||||
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("clicked")) {
|
||||
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
|
||||
expectActivityStartEvents();
|
||||
return assertAppLaunched(label, selector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void executeAndWaitForWindowChange(Runnable command, String label, String action) {
|
||||
mLauncher.executeAndWaitForEvent(
|
||||
command,
|
||||
event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
|
||||
() -> "Launching an app didn't open a new window: " + label,
|
||||
action);
|
||||
}
|
||||
|
||||
protected LaunchedAppState assertAppLaunched(String label, BySelector selector) {
|
||||
mLauncher.assertTrue(
|
||||
"App didn't start: " + label + " (" + selector + ")",
|
||||
TestHelpers.wait(Until.hasObject(selector),
|
||||
mLauncher.getDevice().wait(Until.hasObject(selector),
|
||||
LauncherInstrumentation.WAIT_TIME_MS));
|
||||
return new LaunchedAppState(mLauncher);
|
||||
}
|
||||
|
||||
@@ -129,42 +129,25 @@ public final class LaunchedAppState extends Background {
|
||||
|
||||
try (LauncherInstrumentation.Closable c3 = launcher.addContextLayer(
|
||||
"moved pointer to drop point")) {
|
||||
dropDraggedItem(
|
||||
launcher,
|
||||
launchable,
|
||||
expectedNewPackageName,
|
||||
endPoint, downTime,
|
||||
itemVisibleCenter,
|
||||
itemVisibleBounds,
|
||||
itemLabel,
|
||||
expectedExistingPackageName);
|
||||
LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
|
||||
+ "before drop " + itemVisibleCenter + " in " + itemVisibleBounds);
|
||||
launcher.sendPointer(
|
||||
downTime,
|
||||
SystemClock.uptimeMillis(),
|
||||
MotionEvent.ACTION_UP,
|
||||
endPoint,
|
||||
LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER);
|
||||
LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
|
||||
+ "after drop");
|
||||
|
||||
try (LauncherInstrumentation.Closable c4 = launcher.addContextLayer(
|
||||
"dropped item")) {
|
||||
launchable.assertAppLaunched(itemLabel, By.pkg(expectedNewPackageName));
|
||||
launchable.assertAppLaunched(
|
||||
itemLabel, By.pkg(expectedExistingPackageName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void dropDraggedItem(
|
||||
LauncherInstrumentation launcher, Launchable launchable, String expectedNewPackageName,
|
||||
Point endPoint, long downTime, Point itemVisibleCenter, Rect itemVisibleBounds,
|
||||
String itemLabel, String expectedExistingPackageName) {
|
||||
LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen before drop "
|
||||
+ itemVisibleCenter + " in " + itemVisibleBounds);
|
||||
|
||||
launchable.executeAndWaitForWindowChange(() -> {
|
||||
launcher.sendPointer(
|
||||
downTime,
|
||||
SystemClock.uptimeMillis(),
|
||||
MotionEvent.ACTION_UP,
|
||||
endPoint,
|
||||
LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER);
|
||||
LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: after "
|
||||
+ "drop");
|
||||
}, itemLabel, "dropping taskbar item");
|
||||
|
||||
try (LauncherInstrumentation.Closable c = launcher.addContextLayer("dropped item")) {
|
||||
launchable.assertAppLaunched(itemLabel, By.pkg(expectedNewPackageName));
|
||||
launcher.checkPackagesVisible(
|
||||
new String[] {expectedNewPackageName, expectedExistingPackageName});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,6 @@ import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Consumer;
|
||||
@@ -92,7 +91,6 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* The main tapl object. The only object that can be explicitly constructed by the using code. It
|
||||
@@ -501,29 +499,16 @@ public final class LauncherInstrumentation {
|
||||
}
|
||||
}
|
||||
|
||||
void checkPackagesVisible(String[] expectedVisiblePackages) {
|
||||
Set<String> actualVisiblePackages =
|
||||
getVisiblePackagesStream().collect(Collectors.toSet());
|
||||
|
||||
for (String expectedVisible : expectedVisiblePackages) {
|
||||
assertTrue("Expected package not visible: " + expectedVisible,
|
||||
actualVisiblePackages.contains(expectedVisible));
|
||||
}
|
||||
}
|
||||
|
||||
private String getVisiblePackages() {
|
||||
final String apps = getVisiblePackagesStream().collect(Collectors.joining(", "));
|
||||
return !apps.isEmpty()
|
||||
? "active app: " + apps
|
||||
: "the test doesn't see views from any app, including Launcher";
|
||||
}
|
||||
|
||||
private Stream<String> getVisiblePackagesStream() {
|
||||
return mDevice.findObjects(getAnyObjectSelector())
|
||||
final String apps = mDevice.findObjects(getAnyObjectSelector())
|
||||
.stream()
|
||||
.map(LauncherInstrumentation::getApplicationPackageSafe)
|
||||
.distinct()
|
||||
.filter(pkg -> pkg != null && !SYSTEMUI_PACKAGE.equals(pkg));
|
||||
.filter(pkg -> pkg != null && !SYSTEMUI_PACKAGE.equals(pkg))
|
||||
.collect(Collectors.joining(", "));
|
||||
return !apps.isEmpty()
|
||||
? "active app: " + apps
|
||||
: "the test doesn't see views from any app, including Launcher";
|
||||
}
|
||||
|
||||
private static String getApplicationPackageSafe(UiObject2 object) {
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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.tapl;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.test.uiautomator.By;
|
||||
import androidx.test.uiautomator.UiObject2;
|
||||
import androidx.test.uiautomator.Until;
|
||||
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
|
||||
public class OptionsPopupMenuItem {
|
||||
|
||||
private final LauncherInstrumentation mLauncher;
|
||||
private final UiObject2 mObject;
|
||||
|
||||
OptionsPopupMenuItem(@NonNull LauncherInstrumentation launcher, @NonNull UiObject2 shortcut) {
|
||||
mLauncher = launcher;
|
||||
mObject = shortcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks the option.
|
||||
*/
|
||||
@NonNull
|
||||
public void launch(@NonNull String expectedPackageName) {
|
||||
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
|
||||
LauncherInstrumentation.log("OptionsPopupMenuItem before click "
|
||||
+ mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
|
||||
mLauncher.clickLauncherObject(mObject);
|
||||
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
|
||||
mLauncher.assertTrue(
|
||||
"App didn't start: " + By.pkg(expectedPackageName),
|
||||
mLauncher.getDevice().wait(Until.hasObject(By.pkg(expectedPackageName)),
|
||||
LauncherInstrumentation.WAIT_TIME_MS));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user