Merge "PopupContainerWithArrow should align correctly in RTL mode Test: see attached screenshot in the bug" into ub-launcher3-dorval-polish
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index e836d7d..b211207 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -17,7 +17,6 @@
<resources>
<!-- All Apps -->
<dimen name="all_apps_button_scale_down">8dp</dimen>
- <dimen name="all_apps_search_bar_height">54dp</dimen>
<dimen name="all_apps_empty_search_message_top_offset">64dp</dimen>
<dimen name="all_apps_empty_search_bg_top_offset">180dp</dimen>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index ca5d8e7..2d5f8d0 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -436,7 +436,8 @@
// Since we are only concerned with the overall padding, layout direction does
// not matter.
Point padding = getTotalWorkspacePadding();
- result.x = calculateCellWidth(availableWidthPx - padding.x, inv.numColumns);
+ int cellPadding = cellLayoutPaddingLeftRightPx * 2;
+ result.x = calculateCellWidth(availableWidthPx - padding.x - cellPadding, inv.numColumns);
result.y = calculateCellHeight(availableHeightPx - padding.y, inv.numRows);
return result;
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index fe459bb..c2bddd5 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -3049,7 +3049,6 @@
List<ComponentKey> apps = mLauncherCallbacks.getPredictedApps();
if (apps != null) {
mAppsView.setPredictedApps(apps);
- getUserEventDispatcher().setPredictedApps(apps);
}
}
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 0d7e4fa..f781a3d 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1401,7 +1401,7 @@
@Override
protected boolean shouldFlingForVelocity(int velocityX) {
// When the overlay is moving, the fling or settle transition is controlled by the overlay.
- return Float.compare(mOverlayTranslation, 0) == 0 &&
+ return Float.compare(Math.abs(mOverlayTranslation), 0) == 0 &&
super.shouldFlingForVelocity(velocityX);
}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index ccef4f2..2095192 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -359,7 +359,7 @@
@Override
public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) {
- targetParent.containerType = mAppsRecyclerView.getContainerType(v);
+ // This is filled in {@link AllAppsRecyclerView}
}
@Override
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index fb785fb..2514458 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -30,18 +30,21 @@
import com.android.launcher3.BaseRecyclerView;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.ItemInfo;
import com.android.launcher3.R;
import com.android.launcher3.anim.SpringAnimationHandler;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.DrawableFactory;
+import com.android.launcher3.logging.UserEventDispatcher.LogContainerProvider;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import java.util.List;
/**
* A RecyclerView with custom fast scroll support for the all apps view.
*/
-public class AllAppsRecyclerView extends BaseRecyclerView {
+public class AllAppsRecyclerView extends BaseRecyclerView implements LogContainerProvider {
private AlphabeticalAppsList mApps;
private AllAppsFastScrollHelper mFastScrollHelper;
@@ -231,9 +234,10 @@
updateEmptySearchBackgroundBounds();
}
- public int getContainerType(View v) {
+ @Override
+ public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) {
if (mApps.hasFilter()) {
- return ContainerType.SEARCHRESULT;
+ targetParent.containerType = ContainerType.SEARCHRESULT;
} else {
if (v instanceof BubbleTextView) {
BubbleTextView icon = (BubbleTextView) v;
@@ -242,11 +246,13 @@
List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
AlphabeticalAppsList.AdapterItem item = items.get(position);
if (item.viewType == AllAppsGridAdapter.VIEW_TYPE_PREDICTION_ICON) {
- return ContainerType.PREDICTION;
+ targetParent.containerType = ContainerType.PREDICTION;
+ target.predictedRank = item.rowAppIndex;
+ return;
}
}
}
- return ContainerType.ALLAPPS;
+ targetParent.containerType = ContainerType.ALLAPPS;
}
}
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index 5cb12d5..39e2088 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -202,7 +202,8 @@
if (!dp.isVerticalBarLayout()) {
Rect insets = mLauncher.getDragLayer().getInsets();
int hotseatBottom = bottom - dp.hotseatBarBottomPaddingPx - insets.bottom;
- int searchTopMargin = insets.top + (mMinHeight - mSearchBoxHeight);
+ int searchTopMargin = insets.top + (mMinHeight - mSearchBoxHeight)
+ + ((MarginLayoutParams) getLayoutParams()).bottomMargin;
listener.onScrollRangeChanged(hotseatBottom - searchTopMargin);
} else {
listener.onScrollRangeChanged(bottom);
diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
index 4303302..21eb3fb 100644
--- a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
+++ b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
@@ -20,6 +20,7 @@
import com.android.launcher3.AppInfo;
import com.android.launcher3.util.ComponentKey;
+import java.text.Collator;
import java.util.ArrayList;
import java.util.List;
@@ -61,8 +62,9 @@
// apps that don't match all of the words in the query.
final String queryTextLower = query.toLowerCase();
final ArrayList<ComponentKey> result = new ArrayList<>();
+ StringMatcher matcher = StringMatcher.getInstance();
for (AppInfo info : mApps) {
- if (matches(info, queryTextLower)) {
+ if (matches(info, queryTextLower, matcher)) {
result.add(info.toComponentKey());
}
}
@@ -70,6 +72,10 @@
}
public static boolean matches(AppInfo info, String query) {
+ return matches(info, query, StringMatcher.getInstance());
+ }
+
+ public static boolean matches(AppInfo info, String query, StringMatcher matcher) {
int queryLength = query.length();
String title = info.title.toString();
@@ -90,7 +96,7 @@
nextType = i < (titleLength - 1) ?
Character.getType(title.codePointAt(i + 1)) : Character.UNASSIGNED;
if (isBreak(thisType, lastType, nextType) &&
- title.substring(i, i + queryLength).equalsIgnoreCase(query)) {
+ matcher.matches(query, title.substring(i, i + queryLength))) {
return true;
}
}
@@ -106,6 +112,13 @@
* 4) Any capital character before a small character
*/
private static boolean isBreak(int thisType, int prevType, int nextType) {
+ switch (prevType) {
+ case Character.UNASSIGNED:
+ case Character.SPACE_SEPARATOR:
+ case Character.LINE_SEPARATOR:
+ case Character.PARAGRAPH_SEPARATOR:
+ return true;
+ }
switch (thisType) {
case Character.UPPERCASE_LETTER:
if (nextType == Character.UPPERCASE_LETTER) {
@@ -132,8 +145,44 @@
// Always a break point for a symbol
return true;
default:
- // Always a break point at first character
- return prevType == Character.UNASSIGNED;
+ return false;
+ }
+ }
+
+ public static class StringMatcher {
+
+ private static final char MAX_UNICODE = '\uFFFF';
+
+ private final Collator mCollator;
+
+ StringMatcher() {
+ // On android N and above, Collator uses ICU implementation which has a much better
+ // support for non-latin locales.
+ mCollator = Collator.getInstance();
+ mCollator.setStrength(Collator.PRIMARY);
+ mCollator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+ }
+
+ /**
+ * Returns true if {@param query} is a prefix of {@param target}
+ */
+ public boolean matches(String query, String target) {
+ switch (mCollator.compare(query, target)) {
+ case 0:
+ return true;
+ case -1:
+ // The target string can contain a modifier which would make it larger than
+ // the query string (even though the length is same). If the query becomes
+ // larger after appending a unicode character, it was originally a prefix of
+ // the target string and hence should match.
+ return mCollator.compare(query + MAX_UNICODE, target) > -1;
+ default:
+ return false;
+ }
+ }
+
+ public static StringMatcher getInstance() {
+ return new StringMatcher();
}
}
}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 622cd10..85792d4 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -792,6 +792,7 @@
mFolderIcon.setVisibility(View.VISIBLE);
if (FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) {
mFolderIcon.setBackgroundVisible(true);
+ mFolderIcon.mFolderName.setTextVisibility(true);
}
if (wasAnimated) {
if (FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) {
@@ -1358,8 +1359,11 @@
}
mContent.completePendingPageChanges();
- if (d.dragInfo instanceof PendingAddShortcutInfo) {
- PendingAddShortcutInfo pasi = (PendingAddShortcutInfo) d.dragInfo;
+ PendingAddShortcutInfo pasi = d.dragInfo instanceof PendingAddShortcutInfo
+ ? (PendingAddShortcutInfo) d.dragInfo : null;
+ ShortcutInfo pasiSi = pasi != null ? pasi.activityInfo.createShortcutInfo() : null;
+ if (pasi != null && pasiSi == null) {
+ // There is no ShortcutInfo, so we have to go through a configuration activity.
pasi.container = mInfo.id;
pasi.rank = mEmptyCellRank;
@@ -1369,7 +1373,9 @@
mRearrangeOnClose = true;
} else {
final ShortcutInfo si;
- if (d.dragInfo instanceof AppInfo) {
+ if (pasiSi != null) {
+ si = pasiSi;
+ } else if (d.dragInfo instanceof AppInfo) {
// Came from all apps -- make a copy.
si = ((AppInfo) d.dragInfo).makeShortcut();
} else {
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index 7a05f67..bb23207 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -61,7 +61,7 @@
static final int INITIAL_ITEM_ANIMATION_DURATION = 350;
private static final int FINAL_ITEM_ANIMATION_DURATION = 200;
- private static final int SLIDE_IN_FIRST_PAGE_ANIMATION_DURATION_DELAY = 200;
+ private static final int SLIDE_IN_FIRST_PAGE_ANIMATION_DURATION_DELAY = 100;
private static final int SLIDE_IN_FIRST_PAGE_ANIMATION_DURATION = 300;
private static final int ITEM_SLIDE_IN_OUT_DISTANCE_PX = 200;
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index e28a97a..d5c6515 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -36,10 +36,8 @@
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
-import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.LogConfig;
-import java.util.List;
import java.util.Locale;
import java.util.UUID;
@@ -128,9 +126,6 @@
private boolean mIsInLandscapeMode;
private String mUuidStr;
- // Used for filling in predictedRank on {@link Target}s.
- private List<ComponentKey> mPredictedApps;
-
// APP_ICON SHORTCUT WIDGET
// --------------------------------------------------------------
// packageNameHash required optional required
@@ -138,32 +133,11 @@
// intentHash required
// --------------------------------------------------------------
- protected LauncherEvent createLauncherEvent(View v, int intentHashCode, ComponentName cn) {
- LauncherEvent event = newLauncherEvent(newTouchAction(Action.Touch.TAP),
- newItemTarget(v), newTarget(Target.Type.CONTAINER));
-
- // TODO: make idx percolate up the view hierarchy if needed.
- int idx = 0;
- if (fillInLogContainerData(event, v)) {
- ItemInfo itemInfo = (ItemInfo) v.getTag();
- event.srcTarget[idx].intentHash = intentHashCode;
- if (cn != null) {
- event.srcTarget[idx].packageNameHash = (mUuidStr + cn.getPackageName()).hashCode();
- event.srcTarget[idx].componentHash = (mUuidStr + cn.flattenToString()).hashCode();
- if (mPredictedApps != null) {
- event.srcTarget[idx].predictedRank = mPredictedApps.indexOf(
- new ComponentKey(cn, itemInfo.user));
- }
- }
- }
- return event;
- }
-
/**
* Fills in the container data on the given event if the given view is not null.
* @return whether container data was added.
*/
- private boolean fillInLogContainerData(LauncherEvent event, @Nullable View v) {
+ protected boolean fillInLogContainerData(LauncherEvent event, @Nullable View v) {
// Fill in grid(x,y), pageIndex of the child and container type of the parent
LogContainerProvider provider = getLaunchProviderRecursive(v);
if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
@@ -175,20 +149,31 @@
}
public void logAppLaunch(View v, Intent intent) {
- LauncherEvent ev = createLauncherEvent(v, intent.hashCode(), intent.getComponent());
- if (ev == null) {
- return;
+ LauncherEvent event = newLauncherEvent(newTouchAction(Action.Touch.TAP),
+ newItemTarget(v), newTarget(Target.Type.CONTAINER));
+
+ if (fillInLogContainerData(event, v)) {
+ fillIntentInfo(event.srcTarget[0], intent);
}
- dispatchUserEvent(ev, intent);
+ dispatchUserEvent(event, intent);
+ }
+
+ protected void fillIntentInfo(Target target, Intent intent) {
+ target.intentHash = intent.hashCode();
+ ComponentName cn = intent.getComponent();
+ if (cn != null) {
+ target.packageNameHash = (mUuidStr + cn.getPackageName()).hashCode();
+ target.componentHash = (mUuidStr + cn.flattenToString()).hashCode();
+ }
}
public void logNotificationLaunch(View v, PendingIntent intent) {
- ComponentName dummyComponent = new ComponentName(intent.getCreatorPackage(), "--dummy--");
- LauncherEvent ev = createLauncherEvent(v, intent.hashCode(), dummyComponent);
- if (ev == null) {
- return;
+ LauncherEvent event = newLauncherEvent(newTouchAction(Action.Touch.TAP),
+ newItemTarget(v), newTarget(Target.Type.CONTAINER));
+ if (fillInLogContainerData(event, v)) {
+ event.srcTarget[0].packageNameHash = (mUuidStr + intent.getCreatorPackage()).hashCode();
}
- dispatchUserEvent(ev, null);
+ dispatchUserEvent(event, null);
}
public void logActionCommand(int command, int containerType) {
@@ -273,10 +258,6 @@
resetElapsedContainerMillis();
}
- public void setPredictedApps(List<ComponentKey> predictedApps) {
- mPredictedApps = predictedApps;
- }
-
/* Currently we are only interested in whether this event happens or not and don't
* care about which screen moves to where. */
public void logOverviewReorder() {
@@ -348,7 +329,10 @@
}
private static String getTargetsStr(Target[] targets) {
- return "child:" + LoggerUtils.getTargetStr(targets[0]) +
- (targets.length > 1 ? "\tparent:" + LoggerUtils.getTargetStr(targets[1]) : "");
+ String result = "child:" + LoggerUtils.getTargetStr(targets[0]);
+ for (int i = 1; i < targets.length; i++) {
+ result += "\tparent:" + LoggerUtils.getTargetStr(targets[i]);
+ }
+ return result;
}
}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
index 6b992fc..29834d7 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
@@ -21,7 +21,9 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dynamicui.ExtractedColors;
+import com.android.launcher3.dynamicui.WallpaperColorInfo;
/**
* A PageIndicator that briefly shows a fraction of a line when moving between pages.
@@ -128,6 +130,10 @@
mLauncher = Launcher.getLauncher(context);
mLineHeight = res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_line_height);
setCaretDrawable(new CaretDrawable(context));
+
+ boolean darkText = WallpaperColorInfo.getInstance(context).supportsDarkText();
+ mActiveAlpha = darkText ? BLACK_ALPHA : WHITE_ALPHA;
+ mLinePaint.setColor(darkText ? Color.BLACK : Color.WHITE);
}
@Override
@@ -219,6 +225,9 @@
* - mostly opaque black if the hotseat is black (ignoring alpha)
*/
public void updateColor(ExtractedColors extractedColors) {
+ if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
+ return;
+ }
int originalLineAlpha = mLinePaint.getAlpha();
int color = extractedColors.getColor(ExtractedColors.HOTSEAT_INDEX);
if (color != Color.TRANSPARENT) {
diff --git a/src/com/android/launcher3/widget/PendingAddShortcutInfo.java b/src/com/android/launcher3/widget/PendingAddShortcutInfo.java
index e8f13a1..62b6903 100644
--- a/src/com/android/launcher3/widget/PendingAddShortcutInfo.java
+++ b/src/com/android/launcher3/widget/PendingAddShortcutInfo.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.widget;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.compat.ShortcutConfigActivityInfo;
diff --git a/tests/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithmTest.java b/tests/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithmTest.java
index 58dc0c4..26ec69b 100644
--- a/tests/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithmTest.java
+++ b/tests/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithmTest.java
@@ -19,6 +19,7 @@
import android.test.InstrumentationTestCase;
import com.android.launcher3.AppInfo;
+import com.android.launcher3.Utilities;
import java.util.ArrayList;
import java.util.List;
@@ -75,6 +76,25 @@
assertTrue(mAlgorithm.matches(getInfo("电子邮件"), "电子"));
assertFalse(mAlgorithm.matches(getInfo("电子邮件"), "子"));
assertFalse(mAlgorithm.matches(getInfo("电子邮件"), "邮件"));
+
+ assertFalse(mAlgorithm.matches(getInfo("Bot"), "ba"));
+ assertFalse(mAlgorithm.matches(getInfo("bot"), "ba"));
+ }
+
+ public void testMatchesVN() {
+ if (!Utilities.ATLEAST_NOUGAT) {
+ return;
+ }
+ assertTrue(mAlgorithm.matches(getInfo("다운로드"), "다"));
+ assertTrue(mAlgorithm.matches(getInfo("드라이브"), "드"));
+ assertTrue(mAlgorithm.matches(getInfo("다운로드 드라이브"), "ㄷ"));
+ assertTrue(mAlgorithm.matches(getInfo("운로 드라이브"), "ㄷ"));
+ assertTrue(mAlgorithm.matches(getInfo("abc"), "åbç"));
+ assertTrue(mAlgorithm.matches(getInfo("Alpha"), "ål"));
+
+ assertFalse(mAlgorithm.matches(getInfo("다운로드 드라이브"), "ㄷㄷ"));
+ assertFalse(mAlgorithm.matches(getInfo("로드라이브"), "ㄷ"));
+ assertFalse(mAlgorithm.matches(getInfo("abc"), "åç"));
}
private AppInfo getInfo(String title) {