Merge "Set PreloadIconDrawable disabled = false when restore is complete" into ub-launcher3-master
diff --git a/res/values/config.xml b/res/values/config.xml
index 5b3ee46..d270def 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -79,6 +79,9 @@
<!-- Name of an icon provider class. -->
<string name="icon_provider_class" translatable="false"></string>
+ <!-- Name of a drawable factory class. -->
+ <string name="drawable_factory_class" translatable="false"></string>
+
<!-- Package name of the default wallpaper picker. -->
<string name="wallpaper_picker_package" translatable="false"></string>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index dbb797d..51cd052 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -16,7 +16,6 @@
package com.android.launcher3;
-import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -26,9 +25,7 @@
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Region;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.TypedValue;
@@ -42,6 +39,7 @@
import com.android.launcher3.IconCache.IconLoadRequest;
import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.graphics.DrawableFactory;
import com.android.launcher3.graphics.HolographicOutlineHelper;
import com.android.launcher3.model.PackageItemInfo;
@@ -190,7 +188,7 @@
}
private void applyIconAndLabel(Bitmap icon, ItemInfo info) {
- FastBitmapDrawable iconDrawable = mLauncher.createIconDrawable(icon);
+ FastBitmapDrawable iconDrawable = DrawableFactory.get(getContext()).newIcon(icon, info);
iconDrawable.setIsDisabled(info.isDisabled());
setIcon(iconDrawable);
setText(info.title);
@@ -202,15 +200,6 @@
}
/**
- * Used for measurement only, sets some dummy values on this view.
- */
- public void applyDummyInfo() {
- ColorDrawable d = new ColorDrawable();
- setIcon(mLauncher.resizeIconDrawable(d));
- setText("");
- }
-
- /**
* Overrides the default long press timeout.
*/
public void setLongPressTimeout(int longPressTimeout) {
@@ -528,12 +517,9 @@
/**
* Sets the icon for this view based on the layout direction.
*/
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private void setIcon(Drawable icon) {
mIcon = icon;
- if (mIconSize != -1) {
- mIcon.setBounds(0, 0, mIconSize, mIconSize);
- }
+ mIcon.setBounds(0, 0, mIconSize, mIconSize);
applyCompoundDrawables(mIcon);
}
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 9eaef90..866d239 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -1041,7 +1041,7 @@
// Offsets due to the size difference between the View and the dragOutline.
// There is a size difference to account for the outer blur, which may lie
// outside the bounds of the view.
- top += (v.getHeight() - dragOutline.getHeight()) / 2;
+ top += ((mCellHeight * spanY) - dragOutline.getHeight()) / 2;
// We center about the x axis
left += ((mCellWidth * spanX) - dragOutline.getWidth()) / 2;
} else {
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index 270d539..0cefc57 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -94,7 +94,7 @@
private static final ColorMatrix sTempBrightnessMatrix = new ColorMatrix();
private static final ColorMatrix sTempFilterMatrix = new ColorMatrix();
- private final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
+ protected final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
private final Bitmap mBitmap;
private State mState = State.NORMAL;
private boolean mIsDisabled;
@@ -116,6 +116,17 @@
@Override
public void draw(Canvas canvas) {
+ drawInternal(canvas);
+ }
+
+ public void drawWithBrightness(Canvas canvas, float brightness) {
+ float oldBrightness = getBrightness();
+ setBrightness(brightness);
+ drawInternal(canvas);
+ setBrightness(oldBrightness);
+ }
+
+ protected void drawInternal(Canvas canvas) {
canvas.drawBitmap(mBitmap, null, getBounds(), mPaint);
}
@@ -278,7 +289,7 @@
/**
* Sets the saturation of this icon, 0 [full color] -> 1 [desaturated]
*/
- public void setDesaturation(float desaturation) {
+ private void setDesaturation(float desaturation) {
int newDesaturation = (int) Math.floor(desaturation * REDUCED_FILTER_VALUE_SPACE);
if (mDesaturation != newDesaturation) {
mDesaturation = newDesaturation;
@@ -293,7 +304,7 @@
/**
* Sets the brightness of this icon, 0 [no add. brightness] -> 1 [2bright2furious]
*/
- public void setBrightness(float brightness) {
+ private void setBrightness(float brightness) {
int newBrightness = (int) Math.floor(brightness * REDUCED_FILTER_VALUE_SPACE);
if (mBrightness != newBrightness) {
mBrightness = newBrightness;
@@ -301,7 +312,7 @@
}
}
- public float getBrightness() {
+ private float getBrightness() {
return (float) mBrightness / REDUCED_FILTER_VALUE_SPACE;
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index b93c6df..5c96dde 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -129,14 +129,15 @@
if (!FeatureFlags.NO_ALL_APPS_ICON) {
// Add the Apps button
Context context = getContext();
- int allAppsButtonRank = mLauncher.getDeviceProfile().inv.getAllAppsButtonRank();
+ DeviceProfile grid = mLauncher.getDeviceProfile();
+ int allAppsButtonRank = grid.inv.getAllAppsButtonRank();
LayoutInflater inflater = LayoutInflater.from(context);
TextView allAppsButton = (TextView)
inflater.inflate(R.layout.all_apps_button, mContent, false);
Drawable d = context.getResources().getDrawable(R.drawable.all_apps_button_icon);
+ d.setBounds(0, 0, grid.iconSizePx, grid.iconSizePx);
- mLauncher.resizeIconDrawable(d);
int scaleDownPx = getResources().getDimensionPixelSize(R.dimen.all_apps_button_scale_down);
Rect bounds = d.getBounds();
d.setBounds(bounds.left, bounds.top + scaleDownPx / 2, bounds.right - scaleDownPx,
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index d2f25a4..46df0b2 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -32,6 +32,9 @@
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.shortcuts.DeepShortcutManager;
+import com.android.launcher3.shortcuts.ShortcutInfoCompat;
+import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
@@ -40,10 +43,10 @@
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONStringer;
-import org.json.JSONTokener;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -63,6 +66,7 @@
private static final String ICON_RESOURCE_PACKAGE_NAME_KEY = "iconResourcePackage";
private static final String APP_SHORTCUT_TYPE_KEY = "isAppShortcut";
+ private static final String DEEPSHORTCUT_TYPE_KEY = "isDeepShortcut";
private static final String USER_HANDLE_KEY = "userHandle";
// The set of shortcuts that are pending install
@@ -98,19 +102,25 @@
Log.d(TAG, "APPS_PENDING_INSTALL: " + strings
+ ", removing packages: " + packageNames);
}
- if (strings != null) {
- Set<String> newStrings = new HashSet<String>(strings);
- Iterator<String> newStringsIter = newStrings.iterator();
- while (newStringsIter.hasNext()) {
- String encoded = newStringsIter.next();
- PendingInstallShortcutInfo info = decode(encoded, context);
- if (info == null || (packageNames.contains(info.getTargetPackage())
- && user.equals(info.user))) {
+ if (Utilities.isEmpty(strings)) {
+ return;
+ }
+ Set<String> newStrings = new HashSet<>(strings);
+ Iterator<String> newStringsIter = newStrings.iterator();
+ while (newStringsIter.hasNext()) {
+ String encoded = newStringsIter.next();
+ try {
+ Decoder decoder = new Decoder(encoded, context);
+ if (packageNames.contains(getIntentPackage(decoder.launcherIntent)) &&
+ user.equals(decoder.user)) {
newStringsIter.remove();
}
+ } catch (JSONException | URISyntaxException e) {
+ Log.d(TAG, "Exception reading shortcut to add: " + e);
+ newStringsIter.remove();
}
- sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply();
}
+ sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply();
}
}
@@ -178,7 +188,8 @@
return null;
}
- PendingInstallShortcutInfo info = new PendingInstallShortcutInfo(data, context);
+ PendingInstallShortcutInfo info = new PendingInstallShortcutInfo(
+ data, UserHandleCompat.myUserHandle(), context);
if (info.launchIntent == null || info.label == null) {
if (DBG) Log.e(TAG, "Invalid install shortcut intent");
return null;
@@ -192,6 +203,31 @@
return info == null ? null : info.getShortcutInfo();
}
+ public static void queueShortcut(ShortcutInfoCompat info, Context context) {
+ queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, context), context);
+ }
+
+ public static HashSet<ShortcutKey> getPendingShortcuts(Context context) {
+ HashSet<ShortcutKey> result = new HashSet<>();
+
+ Set<String> strings = Utilities.getPrefs(context).getStringSet(APPS_PENDING_INSTALL, null);
+ if (Utilities.isEmpty(strings)) {
+ return result;
+ }
+
+ for (String encoded : strings) {
+ try {
+ Decoder decoder = new Decoder(encoded, context);
+ if (decoder.optBoolean(DEEPSHORTCUT_TYPE_KEY)) {
+ result.add(ShortcutKey.fromIntent(decoder.launcherIntent, decoder.user));
+ }
+ } catch (JSONException | URISyntaxException e) {
+ Log.d(TAG, "Exception reading shortcut to add: " + e);
+ }
+ }
+ return result;
+ }
+
private static void queuePendingShortcutInfo(PendingInstallShortcutInfo info, Context context) {
// Queue the item up for adding if launcher has not loaded properly yet
LauncherAppState app = LauncherAppState.getInstance();
@@ -239,6 +275,7 @@
private static class PendingInstallShortcutInfo {
final LauncherActivityInfoCompat activityInfo;
+ final ShortcutInfoCompat shortcutInfo;
final Intent data;
final Context mContext;
@@ -249,14 +286,15 @@
/**
* Initializes a PendingInstallShortcutInfo received from a different app.
*/
- public PendingInstallShortcutInfo(Intent data, Context context) {
+ public PendingInstallShortcutInfo(Intent data, UserHandleCompat user, Context context) {
this.data = data;
+ this.user = user;
mContext = context;
launchIntent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
label = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
- user = UserHandleCompat.myUserHandle();
activityInfo = null;
+ shortcutInfo = null;
}
/**
@@ -266,15 +304,30 @@
this.data = null;
mContext = context;
activityInfo = info;
+ shortcutInfo = null;
user = info.getUser();
launchIntent = AppInfo.makeLaunchIntent(context, info, user);
label = info.getLabel().toString();
}
+ /**
+ * Initializes a PendingInstallShortcutInfo to represent a launcher target.
+ */
+ public PendingInstallShortcutInfo(ShortcutInfoCompat info, Context context) {
+ this.data = null;
+ shortcutInfo = info;
+ mContext = context;
+ activityInfo = null;
+ user = info.getUserHandle();
+
+ launchIntent = info.makeIntent(context);
+ label = info.getShortLabel().toString();
+ }
+
public String encodeToString() {
- if (activityInfo != null) {
- try {
+ try {
+ if (activityInfo != null) {
// If it a launcher target, we only need component name, and user to
// recreate this.
return new JSONStringer()
@@ -284,30 +337,35 @@
.key(USER_HANDLE_KEY).value(UserManagerCompat.getInstance(mContext)
.getSerialNumberForUser(user))
.endObject().toString();
- } catch (JSONException e) {
- Log.d(TAG, "Exception when adding shortcut: " + e);
- return null;
+ } else if (shortcutInfo != null) {
+ // If it a launcher target, we only need component name, and user to
+ // recreate this.
+ return new JSONStringer()
+ .object()
+ .key(LAUNCH_INTENT_KEY).value(launchIntent.toUri(0))
+ .key(DEEPSHORTCUT_TYPE_KEY).value(true)
+ .key(USER_HANDLE_KEY).value(UserManagerCompat.getInstance(mContext)
+ .getSerialNumberForUser(user))
+ .endObject().toString();
}
- }
- if (launchIntent.getAction() == null) {
- launchIntent.setAction(Intent.ACTION_VIEW);
- } else if (launchIntent.getAction().equals(Intent.ACTION_MAIN) &&
- launchIntent.getCategories() != null &&
- launchIntent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
- launchIntent.addFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- }
+ if (launchIntent.getAction() == null) {
+ launchIntent.setAction(Intent.ACTION_VIEW);
+ } else if (launchIntent.getAction().equals(Intent.ACTION_MAIN) &&
+ launchIntent.getCategories() != null &&
+ launchIntent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
+ launchIntent.addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ }
- // This name is only used for comparisons and notifications, so fall back to activity
- // name if not supplied
- String name = ensureValidName(mContext, launchIntent, label).toString();
- Bitmap icon = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
- Intent.ShortcutIconResource iconResource =
- data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
+ // This name is only used for comparisons and notifications, so fall back to activity
+ // name if not supplied
+ String name = ensureValidName(mContext, launchIntent, label).toString();
+ Bitmap icon = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
+ Intent.ShortcutIconResource iconResource =
+ data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
- // Only encode the parameters which are supported by the API.
- try {
+ // Only encode the parameters which are supported by the API.
JSONStringer json = new JSONStringer()
.object()
.key(LAUNCH_INTENT_KEY).value(launchIntent.toUri(0))
@@ -326,57 +384,56 @@
return json.endObject().toString();
} catch (JSONException e) {
Log.d(TAG, "Exception when adding shortcut: " + e);
+ return null;
}
- return null;
}
public ShortcutInfo getShortcutInfo() {
if (activityInfo != null) {
return new ShortcutInfo(activityInfo, mContext);
+ } else if (shortcutInfo != null) {
+ return new ShortcutInfo(shortcutInfo, mContext);
} else {
return LauncherAppState.getInstance().getModel().infoFromShortcutIntent(mContext, data);
}
}
- public String getTargetPackage() {
- String packageName = launchIntent.getPackage();
- if (packageName == null) {
- packageName = launchIntent.getComponent() == null ? null :
- launchIntent.getComponent().getPackageName();
- }
- return packageName;
- }
-
public boolean isLauncherActivity() {
return activityInfo != null;
}
}
+ private static String getIntentPackage(Intent intent) {
+ return intent.getComponent() == null
+ ? intent.getPackage() : intent.getComponent().getPackageName();
+ }
+
private static PendingInstallShortcutInfo decode(String encoded, Context context) {
try {
- JSONObject object = (JSONObject) new JSONTokener(encoded).nextValue();
- Intent launcherIntent = Intent.parseUri(object.getString(LAUNCH_INTENT_KEY), 0);
-
- if (object.optBoolean(APP_SHORTCUT_TYPE_KEY)) {
- // The is an internal launcher target shortcut.
- UserHandleCompat user = UserManagerCompat.getInstance(context)
- .getUserForSerialNumber(object.getLong(USER_HANDLE_KEY));
- if (user == null) {
- return null;
- }
-
+ Decoder decoder = new Decoder(encoded, context);
+ if (decoder.optBoolean(APP_SHORTCUT_TYPE_KEY)) {
LauncherActivityInfoCompat info = LauncherAppsCompat.getInstance(context)
- .resolveActivity(launcherIntent, user);
+ .resolveActivity(decoder.launcherIntent, decoder.user);
return info == null ? null : new PendingInstallShortcutInfo(info, context);
+ } else if (decoder.optBoolean(DEEPSHORTCUT_TYPE_KEY)) {
+ DeepShortcutManager sm = DeepShortcutManager.getInstance(context);
+ List<ShortcutInfoCompat> si = sm.queryForFullDetails(
+ decoder.launcherIntent.getPackage(),
+ Arrays.asList(ShortcutInfoCompat.EXTRA_SHORTCUT_ID), decoder.user);
+ if (si.isEmpty()) {
+ return null;
+ } else {
+ return new PendingInstallShortcutInfo(si.get(0), context);
+ }
}
Intent data = new Intent();
- data.putExtra(Intent.EXTRA_SHORTCUT_INTENT, launcherIntent);
- data.putExtra(Intent.EXTRA_SHORTCUT_NAME, object.getString(NAME_KEY));
+ data.putExtra(Intent.EXTRA_SHORTCUT_INTENT, decoder.launcherIntent);
+ data.putExtra(Intent.EXTRA_SHORTCUT_NAME, decoder.getString(NAME_KEY));
- String iconBase64 = object.optString(ICON_KEY);
- String iconResourceName = object.optString(ICON_RESOURCE_NAME_KEY);
- String iconResourcePackageName = object.optString(ICON_RESOURCE_PACKAGE_NAME_KEY);
+ String iconBase64 = decoder.optString(ICON_KEY);
+ String iconResourceName = decoder.optString(ICON_RESOURCE_NAME_KEY);
+ String iconResourcePackageName = decoder.optString(ICON_RESOURCE_PACKAGE_NAME_KEY);
if (iconBase64 != null && !iconBase64.isEmpty()) {
byte[] iconArray = Base64.decode(iconBase64, Base64.DEFAULT);
Bitmap b = BitmapFactory.decodeByteArray(iconArray, 0, iconArray.length);
@@ -389,13 +446,29 @@
data.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
}
- return new PendingInstallShortcutInfo(data, context);
+ return new PendingInstallShortcutInfo(data, decoder.user, context);
} catch (JSONException | URISyntaxException e) {
Log.d(TAG, "Exception reading shortcut to add: " + e);
}
return null;
}
+ private static class Decoder extends JSONObject {
+ public final Intent launcherIntent;
+ public final UserHandleCompat user;
+
+ private Decoder(String encoded, Context context) throws JSONException, URISyntaxException {
+ super(encoded);
+ launcherIntent = Intent.parseUri(getString(LAUNCH_INTENT_KEY), 0);
+ user = has(USER_HANDLE_KEY) ? UserManagerCompat.getInstance(context)
+ .getUserForSerialNumber(getLong(USER_HANDLE_KEY))
+ : UserHandleCompat.myUserHandle();
+ if (user == null) {
+ throw new JSONException("Invalid user");
+ }
+ }
+ }
+
/**
* Tries to create a new PendingInstallShortcutInfo which represents the same target,
* but is an app target and not a shortcut.
@@ -441,7 +514,7 @@
LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext);
for (PendingInstallShortcutInfo pendingInfo : mPendingItems) {
// If the intent specifies a package, make sure the package exists
- String packageName = pendingInfo.getTargetPackage();
+ String packageName = getIntentPackage(pendingInfo.launchIntent);
if (!TextUtils.isEmpty(packageName) && !launcherApps.isPackageEnabledForProfile(
packageName, pendingInfo.user)) {
if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 9160a01..2f7a31f 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1470,9 +1470,7 @@
}
LauncherModel.addItemToDatabase(this, info, container, screenId, cellXY[0], cellXY[1]);
-
- mWorkspace.addInScreen(view, container, screenId, cellXY[0], cellXY[1], 1, 1,
- isWorkspaceLocked());
+ mWorkspace.addInScreen(view, info);
}
/**
@@ -1507,20 +1505,15 @@
hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
}
hostView.setVisibility(View.VISIBLE);
- addAppWidgetToWorkspace(hostView, launcherInfo, appWidgetInfo, isWorkspaceLocked());
+ prepareAppWidget(hostView, launcherInfo);
+ mWorkspace.addInScreen(hostView, launcherInfo);
}
- private void addAppWidgetToWorkspace(
- AppWidgetHostView hostView, LauncherAppWidgetInfo item,
- LauncherAppWidgetProviderInfo appWidgetInfo, boolean insert) {
+ private void prepareAppWidget(AppWidgetHostView hostView, LauncherAppWidgetInfo item) {
hostView.setTag(item);
item.onBindAppWidget(this, hostView);
-
hostView.setFocusable(true);
hostView.setOnFocusChangeListener(mFocusHandler);
-
- mWorkspace.addInScreen(hostView, item.container, item.screenId,
- item.cellX, item.cellY, item.spanX, item.spanY, insert);
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -2105,8 +2098,7 @@
// Create the view
FolderIcon newFolder =
FolderIcon.fromXml(R.layout.folder_icon, this, layout, folderInfo, mIconCache);
- mWorkspace.addInScreen(newFolder, container, screenId, cellX, cellY, 1, 1,
- isWorkspaceLocked());
+ mWorkspace.addInScreen(newFolder, folderInfo);
// Force measure the new folder icon
CellLayout parent = mWorkspace.getParentCellLayoutForView(newFolder);
parent.getShortcutsAndWidgets().measureChild(newFolder);
@@ -3365,8 +3357,7 @@
}
}
}
- workspace.addInScreenFromBind(view, item.container, item.screenId, item.cellX,
- item.cellY, 1, 1);
+ workspace.addInScreenFromBind(view, item);
if (animateIcons) {
// Animate all the applications up now
view.setAlpha(0f);
@@ -3408,15 +3399,6 @@
workspace.requestLayout();
}
- private void bindSafeModeWidget(LauncherAppWidgetInfo item) {
- PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item, true);
- view.updateIcon(mIconCache);
- view.updateAppWidget(null);
- view.setOnClickListener(this);
- addAppWidgetToWorkspace(view, item, null, false);
- mWorkspace.requestLayout();
- }
-
/**
* Add the views for a widget to the workspace.
*
@@ -3433,7 +3415,11 @@
}
if (mIsSafeModeEnabled) {
- bindSafeModeWidget(item);
+ PendingAppWidgetHostView view =
+ new PendingAppWidgetHostView(this, item, mIconCache, true);
+ prepareAppWidget(view, item);
+ mWorkspace.addInScreen(view, item);
+ mWorkspace.requestLayout();
return;
}
@@ -3521,6 +3507,7 @@
}
}
+ final AppWidgetHostView view;
if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
if (DEBUG_WIDGETS) {
Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component "
@@ -3536,16 +3523,12 @@
item.minSpanX = appWidgetInfo.minSpanX;
item.minSpanY = appWidgetInfo.minSpanY;
- addAppWidgetToWorkspace(
- mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo),
- item, appWidgetInfo, false);
+ view = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo);
} else {
- PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item, false);
- view.updateIcon(mIconCache);
- view.updateAppWidget(null);
- view.setOnClickListener(this);
- addAppWidgetToWorkspace(view, item, null, false);
+ view = new PendingAppWidgetHostView(this, item, mIconCache, false);
}
+ prepareAppWidget(view, item);
+ mWorkspace.addInScreen(view, item);
mWorkspace.requestLayout();
if (DEBUG_WIDGETS) {
@@ -4035,24 +4018,6 @@
}
/**
- * Returns a FastBitmapDrawable with the icon, accurately sized.
- */
- public FastBitmapDrawable createIconDrawable(Bitmap icon) {
- FastBitmapDrawable d = new FastBitmapDrawable(icon);
- d.setFilterBitmap(true);
- resizeIconDrawable(d);
- return d;
- }
-
- /**
- * Resizes an icon drawable to the correct icon size.
- */
- public Drawable resizeIconDrawable(Drawable icon) {
- icon.setBounds(0, 0, mDeviceProfile.iconSizePx, mDeviceProfile.iconSizePx);
- return icon;
- }
-
- /**
* Prints out out state for debugging.
*/
public void dumpState() {
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index c7bb188..cc56d43 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1776,9 +1776,12 @@
}
// Unpin shortcuts that don't exist on the workspace.
+ HashSet<ShortcutKey> pendingShortcuts =
+ InstallShortcutReceiver.getPendingShortcuts(context);
for (ShortcutKey key : shortcutKeyToPinnedShortcuts.keySet()) {
MutableInt numTimesPinned = sBgDataModel.pinnedShortcutCounts.get(key);
- if (numTimesPinned == null || numTimesPinned.value == 0) {
+ if ((numTimesPinned == null || numTimesPinned.value == 0)
+ && !pendingShortcuts.contains(key)) {
// Shortcut is pinned but doesn't exist on the workspace; unpin it.
shortcutManager.unpinShortcut(key);
}
diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java
index bf39774..7c92f80 100644
--- a/src/com/android/launcher3/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/PendingAppWidgetHostView.java
@@ -36,6 +36,8 @@
import android.view.View;
import android.view.View.OnClickListener;
+import com.android.launcher3.graphics.DrawableFactory;
+
public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implements OnClickListener {
private static final float SETUP_ICON_SIZE_FACTOR = 2f / 5;
private static final float MIN_SATUNATION = 0.7f;
@@ -63,7 +65,7 @@
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public PendingAppWidgetHostView(Context context, LauncherAppWidgetInfo info,
- boolean disabledForSafeMode) {
+ IconCache cache, boolean disabledForSafeMode) {
super(new ContextThemeWrapper(context, R.style.WidgetContainerTheme));
mLauncher = Launcher.getLauncher(context);
@@ -82,6 +84,10 @@
if (Utilities.ATLEAST_LOLLIPOP) {
setElevation(getResources().getDimension(R.dimen.pending_widget_elevation));
}
+
+ updateIcon(cache);
+ updateAppWidget(null);
+ setOnClickListener(mLauncher);
}
@Override
@@ -117,7 +123,7 @@
mDrawableSizeChanged = true;
}
- public void updateIcon(IconCache cache) {
+ private void updateIcon(IconCache cache) {
Bitmap icon = cache.getIcon(mIconLookupIntent, mInfo.user);
if (mIcon == icon) {
return;
@@ -132,13 +138,14 @@
// 1) App icon in the center
// 2) Preload icon in the center
// 3) Setup icon in the center and app icon in the top right corner.
+ DrawableFactory drawableFactory = DrawableFactory.get(getContext());
if (mDisabledForSafeMode) {
- FastBitmapDrawable disabledIcon = mLauncher.createIconDrawable(mIcon);
+ FastBitmapDrawable disabledIcon = drawableFactory.newIcon(mIcon, mInfo);
disabledIcon.setIsDisabled(true);
mCenterDrawable = disabledIcon;
mSettingIconDrawable = null;
} else if (isReadyForClickSetup()) {
- mCenterDrawable = new FastBitmapDrawable(mIcon);
+ mCenterDrawable = drawableFactory.newIcon(mIcon, mInfo);
mSettingIconDrawable = getResources().getDrawable(R.drawable.ic_setting).mutate();
updateSettingColor();
@@ -148,7 +155,7 @@
sPreloaderTheme.applyStyle(R.style.PreloadIcon, true);
}
- FastBitmapDrawable drawable = mLauncher.createIconDrawable(mIcon);
+ FastBitmapDrawable drawable = drawableFactory.newIcon(mIcon, mInfo);
mCenterDrawable = new PreloadIconDrawable(drawable, sPreloaderTheme);
mCenterDrawable.setCallback(this);
mSettingIconDrawable = null;
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index bd21412..10680b4 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1043,23 +1043,28 @@
}
}
- // See implementation for parameter definition.
- void addInScreen(View child, long container, long screenId,
- int x, int y, int spanX, int spanY) {
- addInScreen(child, container, screenId, x, y, spanX, spanY, false, false);
+ /**
+ * At bind time, we use the rank (screenId) to compute x and y for hotseat items.
+ * See {@link #addInScreen}.
+ */
+ public void addInScreenFromBind(View child, ItemInfo info) {
+ int x = info.cellX;
+ int y = info.cellY;
+ if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ int screenId = (int) info.screenId;
+ x = mLauncher.getHotseat().getCellXFromOrder(screenId);
+ y = mLauncher.getHotseat().getCellYFromOrder(screenId);
+ }
+ addInScreen(child, info.container, info.screenId, x, y, info.spanX, info.spanY);
}
- // At bind time, we use the rank (screenId) to compute x and y for hotseat items.
- // See implementation for parameter definition.
- public void addInScreenFromBind(View child, long container, long screenId, int x, int y,
- int spanX, int spanY) {
- addInScreen(child, container, screenId, x, y, spanX, spanY, false, true);
- }
-
- // See implementation for parameter definition.
- void addInScreen(View child, long container, long screenId, int x, int y, int spanX, int spanY,
- boolean insert) {
- addInScreen(child, container, screenId, x, y, spanX, spanY, insert, false);
+ /**
+ * Adds the specified child in the specified screen based on the {@param info}
+ * See {@link #addInScreen}.
+ */
+ public void addInScreen(View child, ItemInfo info) {
+ addInScreen(child, info.container, info.screenId, info.cellX, info.cellY,
+ info.spanX, info.spanY);
}
/**
@@ -1072,13 +1077,9 @@
* @param y The Y position of the child in the screen's grid.
* @param spanX The number of cells spanned horizontally by the child.
* @param spanY The number of cells spanned vertically by the child.
- * @param insert When true, the child is inserted at the beginning of the children list.
- * @param computeXYFromRank When true, we use the rank (stored in screenId) to compute
- * the x and y position in which to place hotseat items. Otherwise
- * we use the x and y position to compute the rank.
*/
- void addInScreen(View child, long container, long screenId, int x, int y, int spanX, int spanY,
- boolean insert, boolean computeXYFromRank) {
+ private void addInScreen(View child, long container, long screenId, int x, int y,
+ int spanX, int spanY) {
if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
if (getScreenWithId(screenId) == null) {
Log.e(TAG, "Skipping child, screenId " + screenId + " not found");
@@ -1101,13 +1102,6 @@
if (child instanceof FolderIcon) {
((FolderIcon) child).setTextVisible(false);
}
-
- if (computeXYFromRank) {
- x = mLauncher.getHotseat().getCellXFromOrder((int) screenId);
- y = mLauncher.getHotseat().getCellYFromOrder((int) screenId);
- } else {
- screenId = mLauncher.getHotseat().getOrderInHotseat(x, y);
- }
} else {
// Show folder title if not in the hotseat
if (child instanceof FolderIcon) {
@@ -1138,7 +1132,7 @@
int childId = mLauncher.getViewIdForItem(info);
boolean markCellsAsOccupied = !(child instanceof Folder);
- if (!layout.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
+ if (!layout.addViewToCellLayout(child, -1, childId, lp, markCellsAsOccupied)) {
// TODO: This branch occurs when the workspace is adding views
// outside of the defined grid
// maybe we should be deleting these items from the LauncherModel?
@@ -2519,7 +2513,7 @@
if (d.dragSource != this) {
final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1] };
- onDropExternal(touchXY, d.dragInfo, dropTargetLayout, false, d);
+ onDropExternal(touchXY, d.dragInfo, dropTargetLayout, d);
} else if (mDragInfo != null) {
final View cell = mDragInfo.cell;
boolean droppedOnOriginalCellDuringTransition = false;
@@ -3265,7 +3259,7 @@
* to add an item to one of the workspace screens.
*/
private void onDropExternal(final int[] touchXY, final ItemInfo dragInfo,
- final CellLayout cellLayout, boolean insertAtFirst, DragObject d) {
+ final CellLayout cellLayout, DragObject d) {
final Runnable exitSpringLoadedRunnable = new Runnable() {
@Override
public void run() {
@@ -3415,8 +3409,8 @@
LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screenId,
mTargetCell[0], mTargetCell[1]);
- addInScreen(view, container, screenId, mTargetCell[0], mTargetCell[1], info.spanX,
- info.spanY, insertAtFirst);
+ addInScreen(view, container, screenId, mTargetCell[0], mTargetCell[1],
+ info.spanX, info.spanY);
cellLayout.onDropChild(view);
cellLayout.getShortcutsAndWidgets().measureChild(view);
@@ -3467,14 +3461,14 @@
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(layout, loc, true);
resetTransitionTransform(layout);
- float dragViewScaleX;
- float dragViewScaleY;
+ float dragViewScaleX = 1f;
+ float dragViewScaleY = 1f;
if (scale) {
- dragViewScaleX = (1.0f * r.width()) / dragView.getMeasuredWidth();
- dragViewScaleY = (1.0f * r.height()) / dragView.getMeasuredHeight();
- } else {
- dragViewScaleX = 1f;
- dragViewScaleY = 1f;
+ float width = info.spanX * layout.mCellWidth;
+ float height = info.spanY * layout.mCellHeight;
+
+ dragViewScaleX = r.width() / width;
+ dragViewScaleY = r.height() / height;
}
// The animation will scale the dragView about its center, so we need to center about
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index e813bb4..a81b4ca 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -1225,8 +1225,7 @@
// We add the child after removing the folder to prevent both from existing
// at the same time in the CellLayout. We need to add the new item with
// addInScreenFromBind() to ensure that hotseat items are placed correctly.
- mLauncher.getWorkspace().addInScreenFromBind(newIcon, mInfo.container,
- mInfo.screenId, mInfo.cellX, mInfo.cellY, mInfo.spanX, mInfo.spanY);
+ mLauncher.getWorkspace().addInScreenFromBind(newIcon, mInfo);
// Focus the newly created child
newIcon.requestFocus();
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index a29a946..3745323 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -459,10 +459,7 @@
d.setBounds(0, 0, mIntrinsicIconSize, mIntrinsicIconSize);
if (d instanceof FastBitmapDrawable) {
FastBitmapDrawable fd = (FastBitmapDrawable) d;
- float oldBrightness = fd.getBrightness();
- fd.setBrightness(params.overlayAlpha);
- d.draw(canvas);
- fd.setBrightness(oldBrightness);
+ fd.drawWithBrightness(canvas, params.overlayAlpha);
} else {
d.setColorFilter(Color.argb((int) (params.overlayAlpha * 255), 255, 255, 255),
PorterDuff.Mode.SRC_ATOP);
diff --git a/src/com/android/launcher3/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java
index a7d4c63..e205c42 100644
--- a/src/com/android/launcher3/graphics/DragPreviewProvider.java
+++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java
@@ -24,7 +24,9 @@
import android.view.View;
import android.widget.TextView;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppWidgetHostView;
import com.android.launcher3.PreloadIconDrawable;
import com.android.launcher3.Workspace;
import com.android.launcher3.config.ProviderConfig;
@@ -100,20 +102,31 @@
* Responsibility for the bitmap is transferred to the caller.
*/
public Bitmap createDragBitmap(Canvas canvas) {
- Bitmap b;
+ float scale = 1f;
+ int width = mView.getWidth();
+ int height = mView.getHeight();
if (mView instanceof TextView) {
Drawable d = Workspace.getTextViewIcon((TextView) mView);
Rect bounds = getDrawableBounds(d);
- b = Bitmap.createBitmap(bounds.width() + DRAG_BITMAP_PADDING,
- bounds.height() + DRAG_BITMAP_PADDING, Bitmap.Config.ARGB_8888);
- } else {
- b = Bitmap.createBitmap(mView.getWidth() + DRAG_BITMAP_PADDING,
- mView.getHeight() + DRAG_BITMAP_PADDING, Bitmap.Config.ARGB_8888);
+ width = bounds.width();
+ height = bounds.height();
+ } else if (mView instanceof LauncherAppWidgetHostView) {
+ DeviceProfile profile = Launcher.getLauncher(mView.getContext()).getDeviceProfile();
+ scale = Math.min(profile.appWidgetScale.x, profile.appWidgetScale.y);
+ width = (int) (mView.getWidth() * scale);
+ height = (int) (mView.getHeight() * scale);
}
+ Bitmap b = Bitmap.createBitmap(width + DRAG_BITMAP_PADDING, height + DRAG_BITMAP_PADDING,
+ Bitmap.Config.ARGB_8888);
canvas.setBitmap(b);
+
+ canvas.save();
+ canvas.scale(scale, scale);
drawDragView(canvas);
+ canvas.restore();
+
canvas.setBitmap(null);
return b;
@@ -132,12 +145,29 @@
* Responsibility for the bitmap is transferred to the caller.
*/
public Bitmap createDragOutline(Canvas canvas) {
- final Bitmap b = Bitmap.createBitmap(mView.getWidth() + DRAG_BITMAP_PADDING,
- mView.getHeight() + DRAG_BITMAP_PADDING, Bitmap.Config.ALPHA_8);
+ float scale = 1f;
+ int width = mView.getWidth();
+ int height = mView.getHeight();
+
+ if (mView instanceof LauncherAppWidgetHostView) {
+ DeviceProfile profile = Launcher.getLauncher(mView.getContext()).getDeviceProfile();
+ scale = Math.min(profile.appWidgetScale.x, profile.appWidgetScale.y);
+ width = (int) Math.floor(mView.getWidth() * scale);
+ height = (int) Math.floor(mView.getHeight() * scale);
+ }
+
+ Bitmap b = Bitmap.createBitmap(width + DRAG_BITMAP_PADDING, height + DRAG_BITMAP_PADDING,
+ Bitmap.Config.ALPHA_8);
canvas.setBitmap(b);
+
+ canvas.save();
+ canvas.scale(scale, scale);
drawDragView(canvas);
+ canvas.restore();
+
HolographicOutlineHelper.getInstance(mView.getContext())
.applyExpensiveOutlineWithBlur(b, canvas);
+
canvas.setBitmap(null);
return b;
}
@@ -160,8 +190,17 @@
public float getScaleAndPosition(Bitmap preview, int[] outPos) {
float scale = Launcher.getLauncher(mView.getContext())
.getDragLayer().getLocationInDragLayer(mView, outPos);
- outPos[0] = Math.round(outPos[0] - (preview.getWidth() - scale * mView.getWidth()) / 2);
- outPos[1] = Math.round(outPos[1] - (1 - scale) * preview.getHeight() / 2 - previewPadding / 2);
+ DeviceProfile profile = Launcher.getLauncher(mView.getContext()).getDeviceProfile();
+ if (mView instanceof LauncherAppWidgetHostView) {
+ // App widgets are technically scaled, but are drawn at their expected size -- so the
+ // app widget scale should not affect the scale of the preview.
+ scale /= Math.min(profile.appWidgetScale.x, profile.appWidgetScale.y);
+ }
+
+ outPos[0] = Math.round(outPos[0] -
+ (preview.getWidth() - scale * mView.getWidth() * mView.getScaleX()) / 2);
+ outPos[1] = Math.round(outPos[1] - (1 - scale) * preview.getHeight() / 2
+ - previewPadding / 2);
return scale;
}
}
diff --git a/src/com/android/launcher3/graphics/DrawableFactory.java b/src/com/android/launcher3/graphics/DrawableFactory.java
new file mode 100644
index 0000000..2926a29
--- /dev/null
+++ b/src/com/android/launcher3/graphics/DrawableFactory.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 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.graphics;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.text.TextUtils;
+
+import com.android.launcher3.FastBitmapDrawable;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.R;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Factory for creating new drawables.
+ */
+public class DrawableFactory {
+
+ private static DrawableFactory sInstance;
+ private static final Object LOCK = new Object();
+
+ public static DrawableFactory get(Context context) {
+ synchronized (LOCK) {
+ if (sInstance == null) {
+ context = context.getApplicationContext();
+ sInstance = loadByName(context.getString(R.string.drawable_factory_class), context);
+ }
+ return sInstance;
+ }
+ }
+
+ public static DrawableFactory loadByName(String className, Context context) {
+ if (!TextUtils.isEmpty(className)) {
+ try {
+ Class<?> cls = Class.forName(className);
+ return (DrawableFactory)
+ cls.getDeclaredConstructor(Context.class).newInstance(context);
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
+ | ClassCastException | NoSuchMethodException | InvocationTargetException e) {
+ return new DrawableFactory();
+ }
+ }
+ return new DrawableFactory();
+ }
+
+ /**
+ * Returns a FastBitmapDrawable with the icon.
+ */
+ public FastBitmapDrawable newIcon(Bitmap icon, ItemInfo info) {
+ FastBitmapDrawable d = new FastBitmapDrawable(icon);
+ d.setFilterBitmap(true);
+ return d;
+ }
+}
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index 29defdd..3d54637 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -15,10 +15,12 @@
*/
package com.android.launcher3.model;
+import android.content.Context;
import android.util.Log;
import android.util.MutableInt;
import com.android.launcher3.FolderInfo;
+import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetInfo;
@@ -123,9 +125,11 @@
// Decrement pinned shortcut count
ShortcutKey pinnedShortcut = ShortcutKey.fromShortcutInfo((ShortcutInfo) item);
MutableInt count = pinnedShortcutCounts.get(pinnedShortcut);
- if (count == null || --count.value == 0) {
- DeepShortcutManager.getInstance(LauncherAppState.getInstance().getContext())
- .unpinShortcut(pinnedShortcut);
+ Context context = LauncherAppState.getInstance().getContext();
+ if ((count == null || --count.value == 0)
+ && !InstallShortcutReceiver.getPendingShortcuts(context)
+ .contains(pinnedShortcut)) {
+ DeepShortcutManager.getInstance(context).unpinShortcut(pinnedShortcut);
}
// Fall through.
}