Merge "Use notification icon views' tags to store NotificationInfo." into ub-launcher3-master
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
index 95a558a..0e8c313 100644
--- a/res/values-ml-rIN/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -33,7 +33,7 @@
<string name="long_accessible_way_to_add" msgid="4289502106628154155">"വിജറ്റ് തിരഞ്ഞെടുക്കാനോ ഇഷ്ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കാനോ രണ്ടുതവണ ടാപ്പുചെയ്ത് പിടിക്കുക."</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d വീതിയും %2$d ഉയരവും"</string>
- <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ആപ്പ്സ് തിരയുക"</string>
+ <string name="all_apps_search_bar_hint" msgid="7084713969757597256">"ആപ്പുകളെ തിരയുക"</string>
<string name="all_apps_loading_message" msgid="7557140873644765180">"ആപ്പ്സ് ലോഡുചെയ്യുന്നു..."</string>
<string name="all_apps_no_search_results" msgid="6332185285860416787">"\"<xliff:g id="QUERY">%1$s</xliff:g>\" എന്നതുമായി പൊരുത്തപ്പെടുന്ന ആപ്പ്സൊന്നും കണ്ടെത്തിയില്ല"</string>
<string name="all_apps_search_market_message" msgid="1366263386197059176">"കൂടുതൽ ആപ്പുകൾക്ക് തിരയുക"</string>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 809fc6d..19bf51a 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -50,4 +50,7 @@
<!-- Used as a fallback since colorSecondary doesn't exist pre-API 25 -->
<color name="fallback_secondary_color">#FF37474F</color>
+
+ <color name="notification_icon_default_color">#757575</color> <!-- Gray 600 -->
+ <color name="legacy_icon_background">#FFE0E0E0</color>
</resources>
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 85b08d1..8d69fe3 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -229,7 +229,7 @@
}
};
dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
- mLauncher.getDragController().isExternalDrag() ? 1 : DRAG_VIEW_DROP_DURATION,
+ DRAG_VIEW_DROP_DURATION,
new DecelerateInterpolator(2),
new LinearInterpolator(), onAnimationEndRunnable,
DragLayer.ANIMATION_END_DISAPPEAR, null);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index a1aafb8..11db9a0 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -101,7 +101,6 @@
import com.android.launcher3.dynamicui.ExtractedColors;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.keyboard.CustomActionsPopup;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.logging.FileLog;
@@ -111,7 +110,6 @@
import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.shortcuts.DeepShortcutManager;
-import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -836,7 +834,7 @@
}
@Override
- public void onActivityResult(
+ protected void onActivityResult(
final int requestCode, final int resultCode, final Intent data) {
handleActivityResult(requestCode, resultCode, data);
if (mLauncherCallbacks != null) {
@@ -1459,21 +1457,8 @@
ShortcutInfo info = null;
if (Utilities.isAtLeastO()) {
- PinItemRequestCompat request = PinItemRequestCompat.getPinItemRequest(data);
- // request.accept will initiate a shortcutChanged callback. To ensure that the model is
- // consistent, that callback must be processed by the model, after the ShortcutInfo is
- // added to the model. This is guaranteed here the callback comes on the UI thread, and
- // we will add the shortcut on the UI thread as well.
- if (request != null &&
- request.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT &&
- request.isValid() && request.accept()) {
- ShortcutInfoCompat compat = new ShortcutInfoCompat(request.getShortcutInfo());
- info = new ShortcutInfo(compat, this);
- // Apply the unbadged icon and fetch the actual icon asynchronously.
- info.iconBitmap = LauncherIcons
- .createShortcutIcon(compat, this, false /* badged */);
- getModel().updateAndBindShortcutInfo(info, compat);
- }
+ info = LauncherAppsCompat.createShortcutInfoFromPinItemRequest(
+ this, PinItemRequestCompat.getPinItemRequest(data));
}
if (info == null) {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index cd1d8d9..72dff66 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -2523,7 +2523,7 @@
if (d.dragSource != this) {
final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1] };
- onDropExternal(touchXY, d.dragInfo, dropTargetLayout, d);
+ onDropExternal(touchXY, dropTargetLayout, d);
} else if (mDragInfo != null) {
final View cell = mDragInfo.cell;
boolean droppedOnOriginalCellDuringTransition = false;
@@ -3226,8 +3226,7 @@
* NOTE: This can also be called when we are outside of a drag event, when we want
* to add an item to one of the workspace screens.
*/
- private void onDropExternal(final int[] touchXY, final ItemInfo dragInfo,
- final CellLayout cellLayout, DragObject d) {
+ private void onDropExternal(final int[] touchXY, final CellLayout cellLayout, DragObject d) {
final Runnable exitSpringLoadedRunnable = new Runnable() {
@Override
public void run() {
@@ -3236,7 +3235,15 @@
}
};
- ItemInfo info = dragInfo;
+ if (d.dragInfo instanceof PendingAddShortcutInfo) {
+ ShortcutInfo si = ((PendingAddShortcutInfo) d.dragInfo)
+ .activityInfo.createShortcutInfo();
+ if (si != null) {
+ d.dragInfo = si;
+ }
+ }
+
+ ItemInfo info = d.dragInfo;
int spanX = info.spanX;
int spanY = info.spanY;
if (mDragInfo != null) {
@@ -3255,7 +3262,7 @@
}
if (info instanceof PendingAddItemInfo) {
- final PendingAddItemInfo pendingInfo = (PendingAddItemInfo) dragInfo;
+ final PendingAddItemInfo pendingInfo = (PendingAddItemInfo) info;
boolean findNearestVacantCell = true;
if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
@@ -3318,7 +3325,7 @@
int animationStyle = ANIMATE_INTO_POSITION_AND_DISAPPEAR;
if (isWidget && ((PendingAddWidgetInfo) pendingInfo).info != null &&
- ((PendingAddWidgetInfo) pendingInfo).info.configure != null) {
+ ((PendingAddWidgetInfo) pendingInfo).getHandler().needsConfigure()) {
animationStyle = ANIMATE_INTO_POSITION_AND_REMAIN;
}
animateWidgetDrop(info, cellLayout, d.dragView, onAnimationCompleteRunnable,
@@ -3433,21 +3440,32 @@
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(layout, loc, true);
resetTransitionTransform(layout);
- float dragViewScaleX = 1f;
- float dragViewScaleY = 1f;
if (scale) {
- dragViewScaleX = (1.0f * r.width()) / dragView.getMeasuredWidth();
- dragViewScaleY = (1.0f * r.height()) / dragView.getMeasuredHeight();
+ float dragViewScaleX = (1.0f * r.width()) / dragView.getMeasuredWidth();
+ float dragViewScaleY = (1.0f * r.height()) / dragView.getMeasuredHeight();
+
+ // The animation will scale the dragView about its center, so we need to center about
+ // the final location.
+ loc[0] -= (dragView.getMeasuredWidth() - cellLayoutScale * r.width()) / 2
+ - Math.ceil(layout.getUnusedHorizontalSpace() / 2f);
+ loc[1] -= (dragView.getMeasuredHeight() - cellLayoutScale * r.height()) / 2;
+ scaleXY[0] = dragViewScaleX * cellLayoutScale;
+ scaleXY[1] = dragViewScaleY * cellLayoutScale;
+ } else {
+ // Since we are not cross-fading the dragView, align the drag view to the
+ // final cell position.
+ float dragScale = dragView.getInitialScale() * cellLayoutScale;
+ loc[0] += (dragScale - 1) * dragView.getWidth() / 2;
+ loc[1] += (dragScale - 1) * dragView.getHeight() / 2;
+ scaleXY[0] = scaleXY[1] = dragScale;
+
+ // If a dragRegion was provided, offset the final position accordingly.
+ Rect dragRegion = dragView.getDragRegion();
+ if (dragRegion != null) {
+ loc[0] += cellLayoutScale * dragRegion.left;
+ loc[1] += cellLayoutScale * dragRegion.top;
+ }
}
-
- // The animation will scale the dragView about its center, so we need to center about
- // the final location.
- loc[0] -= (dragView.getMeasuredWidth() - cellLayoutScale * r.width()) / 2
- - Math.ceil(layout.getUnusedHorizontalSpace() / 2f);
- loc[1] -= (dragView.getMeasuredHeight() - cellLayoutScale * r.height()) / 2;
-
- scaleXY[0] = dragViewScaleX * cellLayoutScale;
- scaleXY[1] = dragViewScaleY * cellLayoutScale;
}
public void animateWidgetDrop(ItemInfo info, CellLayout cellLayout, final DragView dragView,
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index 281069a..b9142ed 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -23,8 +23,12 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.os.UserHandle;
+import android.support.annotation.Nullable;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
+import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import java.util.List;
@@ -75,4 +79,38 @@
public abstract boolean isActivityEnabledForProfile(ComponentName component,
UserHandle user);
public abstract List<ShortcutConfigActivityInfo> getCustomShortcutActivityList();
+
+ /**
+ * request.accept() will initiate the following flow:
+ * -> go-to-system-process for actual processing (a)
+ * -> callback-to-launcher on UI thread (b)
+ * -> post callback on the worker thread (c)
+ * -> Update model and unpin (in system) any shortcut not in out model. (d)
+ *
+ * Note that (b) will take at-least one frame as it involves posting callback from binder
+ * thread to UI thread.
+ * If (d) happens before we add this shortcut to our model, we will end up unpinning
+ * the shortcut in the system.
+ * Here its the caller's responsibility to add the newly created ShortcutInfo immediately
+ * to the model (which may involves a single post-to-worker-thread). That will guarantee
+ * that (d) happens after model is updated.
+ */
+ @Nullable
+ public static ShortcutInfo createShortcutInfoFromPinItemRequest(
+ Context context, PinItemRequestCompat request) {
+ if (request != null &&
+ request.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT &&
+ request.isValid() && request.accept()) {
+ ShortcutInfoCompat compat = new ShortcutInfoCompat(request.getShortcutInfo());
+ ShortcutInfo info = new ShortcutInfo(compat, context);
+ // Apply the unbadged icon and fetch the actual icon asynchronously.
+ info.iconBitmap = LauncherIcons
+ .createShortcutIcon(compat, context, false /* badged */);
+ LauncherAppState.getInstance(context).getModel()
+ .updateAndBindShortcutInfo(info, compat);
+ return info;
+ } else {
+ return null;
+ }
+ }
}
diff --git a/src/com/android/launcher3/compat/PinItemRequestCompat.java b/src/com/android/launcher3/compat/PinItemRequestCompat.java
index 481310a..f76b776 100644
--- a/src/com/android/launcher3/compat/PinItemRequestCompat.java
+++ b/src/com/android/launcher3/compat/PinItemRequestCompat.java
@@ -94,10 +94,6 @@
parcel.writeParcelable(mObject, i);
}
- public Intent toIntent() {
- return new Intent().putExtra(EXTRA_PIN_ITEM_REQUEST, mObject);
- }
-
public static final Parcelable.Creator<PinItemRequestCompat> CREATOR =
new Parcelable.Creator<PinItemRequestCompat>() {
public PinItemRequestCompat createFromParcel(Parcel source) {
diff --git a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
index 1cfbd20..ebe95d6 100644
--- a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
@@ -26,18 +26,15 @@
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
-import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
import android.util.Log;
import android.widget.Toast;
import com.android.launcher3.IconCache;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
+import com.android.launcher3.ShortcutInfo;
import java.lang.reflect.Method;
@@ -68,7 +65,15 @@
public abstract Drawable getFullResIcon(IconCache cache);
- public boolean startConfigActivity(Launcher activity, int requestCode) {
+ /**
+ * Return a shortcut info, if it can be created directly on drop, without requiring any
+ * {@link #startConfigActivity(Activity, int)}.
+ */
+ public ShortcutInfo createShortcutInfo() {
+ return null;
+ }
+
+ public boolean startConfigActivity(Activity activity, int requestCode) {
Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT)
.setComponent(getComponent());
try {
@@ -137,7 +142,7 @@
}
@Override
- public boolean startConfigActivity(Launcher activity, int requestCode) {
+ public boolean startConfigActivity(Activity activity, int requestCode) {
if (getUser().equals(Process.myUserHandle())) {
return super.startConfigActivity(activity, requestCode);
}
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index 423fdab..b80baf3 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -117,11 +117,19 @@
public boolean onLongClick(View view) {
// Find the position of the preview relative to the touch location.
WidgetImageView img = mWidgetCell.getWidgetView();
+
+ // If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
+ // we abort the drag.
+ if (img.getBitmap() == null) {
+ return false;
+ }
+
Rect bounds = img.getBitmapBounds();
bounds.offset(img.getLeft() - (int) mLastTouchPos.x, img.getTop() - (int) mLastTouchPos.y);
// Start home and pass the draw request params
- PinItemDragListener listener = new PinItemDragListener(mRequest, bounds);
+ PinItemDragListener listener = new PinItemDragListener(mRequest, bounds,
+ img.getBitmap().getWidth(), img.getWidth());
Intent homeIntent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME)
.setPackage(getPackageName())
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 5a5e7d0..e31c8ff 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -121,28 +121,6 @@
/**
* Starts a drag.
*
- * @param v The view that is being dragged
- * @param bmp The bitmap that represents the view being dragged
- * @param source An object representing where the drag originated
- * @param dragInfo The data associated with the object that is being dragged
- * @param viewImageBounds the position of the image inside the view
- */
- public void startDrag(View v, Bitmap bmp, DragSource source, ItemInfo dragInfo,
- Rect viewImageBounds, float initialDragViewScale, DragOptions options) {
- int[] loc = mCoordinatesTemp;
- mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
- int dragLayerX = loc[0] + viewImageBounds.left
- + (int) ((initialDragViewScale * bmp.getWidth() - bmp.getWidth()) / 2);
- int dragLayerY = loc[1] + viewImageBounds.top
- + (int) ((initialDragViewScale * bmp.getHeight() - bmp.getHeight()) / 2);
-
- startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, null,
- null, initialDragViewScale, options);
- }
-
- /**
- * Starts a drag.
- *
* @param b The bitmap to display as the drag image. It will be re-scaled to the
* enlarged size.
* @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.
@@ -259,10 +237,6 @@
return mDragDriver != null || (mOptions != null && mOptions.isAccessibleDrag);
}
- public boolean isExternalDrag() {
- return (mOptions != null && mOptions.systemDndStartPoint != null);
- }
-
/**
* Stop dragging without dropping.
*/
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index de416e3..1be40f7 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -673,15 +673,11 @@
// If duration < 0, this is a cue to compute the duration based on the distance
if (duration < 0) {
- if (mDragController != null && mDragController.isExternalDrag()) {
- duration = 1;
- } else {
- duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
- if (dist < maxDist) {
- duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist);
- }
- duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
+ duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
+ if (dist < maxDist) {
+ duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist);
}
+ duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
}
// Fall back to cubic ease out interpolator for the animation if none is specified
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index c946235..3a98ae7 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -392,4 +392,8 @@
public int getBlurSizeOutline() {
return mBlurSizeOutline;
}
+
+ public float getInitialScale() {
+ return mInitialScale;
+ }
}
diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
index 9770d40..6e5318f 100644
--- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -17,9 +17,6 @@
package com.android.launcher3.dragndrop;
import android.content.ClipDescription;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
@@ -32,30 +29,25 @@
import android.view.View;
import com.android.launcher3.DeleteDropTarget;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.R;
import com.android.launcher3.compat.PinItemRequestCompat;
import com.android.launcher3.folder.Folder;
-import com.android.launcher3.graphics.LauncherIcons;
-import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
-import com.android.launcher3.widget.PendingItemPreviewProvider;
+import com.android.launcher3.widget.PendingItemDragHelper;
import com.android.launcher3.widget.WidgetAddFlowHandler;
-import com.android.launcher3.widget.WidgetHostViewLoader;
import java.util.UUID;
/**
- * {@link DragSource} for handling drop from from a different window. This object is initialized
+ * {@link DragSource} for handling drop from a different window. This object is initialized
* in the source window and is passed on to the Launcher activity as an Intent extra.
*/
public class PinItemDragListener
@@ -71,6 +63,9 @@
// Position of preview relative to the touch location
private final Rect mPreviewRect;
+ private final int mPreviewBitmapWidth;
+ private final int mPreviewViewWidth;
+
// Randomly generated id used to verify the drag event.
private final String mId;
@@ -78,15 +73,20 @@
private DragController mDragController;
private long mDragStartTime;
- public PinItemDragListener(PinItemRequestCompat request, Rect previewRect) {
+ public PinItemDragListener(PinItemRequestCompat request, Rect previewRect,
+ int previewBitmapWidth, int previewViewWidth) {
mRequest = request;
mPreviewRect = previewRect;
+ mPreviewBitmapWidth = previewBitmapWidth;
+ mPreviewViewWidth = previewViewWidth;
mId = UUID.randomUUID().toString();
}
private PinItemDragListener(Parcel parcel) {
mRequest = PinItemRequestCompat.CREATOR.createFromParcel(parcel);
mPreviewRect = Rect.CREATOR.createFromParcel(parcel);
+ mPreviewBitmapWidth = parcel.readInt();
+ mPreviewViewWidth = parcel.readInt();
mId = parcel.readString();
}
@@ -103,6 +103,8 @@
public void writeToParcel(Parcel parcel, int i) {
mRequest.writeToParcel(parcel, i);
mPreviewRect.writeToParcel(parcel, i);
+ parcel.writeInt(mPreviewBitmapWidth);
+ parcel.writeInt(mPreviewViewWidth);
parcel.writeString(mId);
}
@@ -139,26 +141,9 @@
}
final PendingAddItemInfo item;
- final Bitmap preview;
- final View view = new View(mLauncher);
-
- Point dragShift = new Point(mPreviewRect.left, mPreviewRect.top);
if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT) {
item = new PendingAddShortcutInfo(
new PinShortcutRequestActivityInfo(mRequest, mLauncher));
-
- ShortcutInfoCompat compat = new ShortcutInfoCompat(mRequest.getShortcutInfo());
- Bitmap icon = LauncherIcons.createShortcutIcon(compat, mLauncher, false /* badged */);
-
- // Create a preview same as the workspace cell size and draw the icon at the
- // appropriate position.
- int[] size = mLauncher.getWorkspace().estimateItemSize(item, true, false);
- preview = Bitmap.createBitmap(size[0], size[1], Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(preview);
- DeviceProfile dp = mLauncher.getDeviceProfile();
- c.drawBitmap(icon, (size[0] - icon.getWidth()) / 2,
- (size[1] - icon.getHeight() - dp.iconTextSizePx - dp.iconDrawablePaddingPx) / 2,
- new Paint(Paint.FILTER_BITMAP_FLAG));
} else {
// mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_APPWIDGET
LauncherAppWidgetProviderInfo providerInfo =
@@ -166,46 +151,28 @@
mLauncher, mRequest.getAppWidgetProviderInfo(mLauncher));
final PinWidgetFlowHandler flowHandler =
new PinWidgetFlowHandler(providerInfo, mRequest);
- PendingAddWidgetInfo info = new PendingAddWidgetInfo(providerInfo) {
+ item = new PendingAddWidgetInfo(providerInfo) {
@Override
public WidgetAddFlowHandler getHandler() {
return flowHandler;
}
};
- int[] size = mLauncher.getWorkspace().estimateItemSize(info, true, false);
-
- float minScale = 1.25f;
- int maxWidth = Math.min((int) (mPreviewRect.width() * minScale), size[0]);
- int[] previewSizeBeforeScale = new int[1];
- preview = LauncherAppState.getInstance(mLauncher).getWidgetCache()
- .generateWidgetPreview(mLauncher, info.info, maxWidth, null,
- previewSizeBeforeScale);
-
- dragShift.offset(
- (mPreviewRect.width() - preview.getWidth()) / 2,
- (mPreviewRect.height() - preview.getHeight()) / 2);
- item = info;
-
- view.setTag(info);
- mDragController.addDragListener(new WidgetHostViewLoader(mLauncher, view));
}
-
- PendingItemPreviewProvider previewProvider =
- new PendingItemPreviewProvider(view, item, preview);
-
- // Since we are not going through the workspace for starting the drag, set drag related
- // information on the workspace before starting the drag.
- mLauncher.getWorkspace().prepareDragWithProvider(previewProvider);
+ View view = new View(mLauncher);
+ view.setTag(item);
Point downPos = new Point((int) event.getX(), (int) event.getY());
DragOptions options = new DragOptions();
options.systemDndStartPoint = downPos;
options.preDragCondition = this;
- int x = downPos.x + dragShift.x;
- int y = downPos.y + dragShift.y;
- mDragController.startDrag(
- preview, x, y, this, item, null, null, 1f, options);
+ // We use drag event position as the screenPos for the preview image. Since mPreviewRect
+ // already includes the view position relative to the drag event on the source window,
+ // and the absolute position (position relative to the screen) of drag event is same
+ // across windows, using drag position here give a good estimate for relative position
+ // to source window.
+ new PendingItemDragHelper(view).startDrag(new Rect(mPreviewRect),
+ mPreviewBitmapWidth, mPreviewViewWidth, downPos, this, options);
mDragStartTime = SystemClock.uptimeMillis();
return true;
}
diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
index 2121b43..6a8c19f 100644
--- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
+++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
@@ -26,8 +26,8 @@
import android.os.Build;
import com.android.launcher3.IconCache;
-import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PinItemRequestCompat;
import com.android.launcher3.compat.ShortcutConfigActivityInfo;
@@ -66,9 +66,13 @@
}
@Override
- public boolean startConfigActivity(Launcher activity, int requestCode) {
- activity.onActivityResult(requestCode, Activity.RESULT_OK, mRequest.toIntent());
- return true;
+ public com.android.launcher3.ShortcutInfo createShortcutInfo() {
+ return LauncherAppsCompat.createShortcutInfoFromPinItemRequest(mContext, mRequest);
+ }
+
+ @Override
+ public boolean startConfigActivity(Activity activity, int requestCode) {
+ return false;
}
@Override
diff --git a/src/com/android/launcher3/graphics/IconPalette.java b/src/com/android/launcher3/graphics/IconPalette.java
index 58ad449..27aeaba 100644
--- a/src/com/android/launcher3/graphics/IconPalette.java
+++ b/src/com/android/launcher3/graphics/IconPalette.java
@@ -16,14 +16,22 @@
package com.android.launcher3.graphics;
+import android.app.Notification;
+import android.content.Context;
import android.graphics.Color;
import android.support.v4.graphics.ColorUtils;
+import android.util.Log;
+
+import com.android.launcher3.R;
/**
* Contains colors based on the dominant color of an icon.
*/
public class IconPalette {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "IconPalette";
+
public int backgroundColor;
public int textColor;
public int secondaryColor;
@@ -36,6 +44,100 @@
return palette;
}
+ /**
+ * Resolves a color such that it has enough contrast to be used as the
+ * color of an icon or text on the given background color.
+ *
+ * @return a color of the same hue with enough contrast against the background.
+ *
+ * This was copied from com.android.internal.util.NotificationColorUtil.
+ */
+ public static int resolveContrastColor(Context context, int color, int background) {
+ final int resolvedColor = resolveColor(context, color);
+
+ int contrastingColor = ensureTextContrast(resolvedColor, background);
+
+ if (contrastingColor != resolvedColor) {
+ if (DEBUG){
+ Log.w(TAG, String.format(
+ "Enhanced contrast of notification for %s " +
+ "%s (over background) by changing #%s to %s",
+ context.getPackageName(),
+ contrastChange(resolvedColor, contrastingColor, background),
+ Integer.toHexString(resolvedColor), Integer.toHexString(contrastingColor)));
+ }
+ }
+ return contrastingColor;
+ }
+
+ /**
+ * Resolves {@param color} to an actual color if it is {@link Notification#COLOR_DEFAULT}
+ *
+ * This was copied from com.android.internal.util.NotificationColorUtil.
+ */
+ private static int resolveColor(Context context, int color) {
+ if (color == Notification.COLOR_DEFAULT) {
+ return context.getColor(R.color.notification_icon_default_color);
+ }
+ return color;
+ }
+
+ /** For debugging. This was copied from com.android.internal.util.NotificationColorUtil. */
+ private static String contrastChange(int colorOld, int colorNew, int bg) {
+ return String.format("from %.2f:1 to %.2f:1",
+ ColorUtils.calculateContrast(colorOld, bg),
+ ColorUtils.calculateContrast(colorNew, bg));
+ }
+
+ /**
+ * Finds a text color with sufficient contrast over bg that has the same hue as the original
+ * color.
+ *
+ * This was copied from com.android.internal.util.NotificationColorUtil.
+ */
+ private static int ensureTextContrast(int color, int bg) {
+ return findContrastColor(color, bg, true, 4.5);
+ }
+ /**
+ * Finds a suitable color such that there's enough contrast.
+ *
+ * @param color the color to start searching from.
+ * @param other the color to ensure contrast against. Assumed to be lighter than {@param color}
+ * @param findFg if true, we assume {@param color} is a foreground, otherwise a background.
+ * @param minRatio the minimum contrast ratio required.
+ * @return a color with the same hue as {@param color}, potentially darkened to meet the
+ * contrast ratio.
+ *
+ * This was copied from com.android.internal.util.NotificationColorUtil.
+ */
+ private static int findContrastColor(int color, int other, boolean findFg, double minRatio) {
+ int fg = findFg ? color : other;
+ int bg = findFg ? other : color;
+ if (ColorUtils.calculateContrast(fg, bg) >= minRatio) {
+ return color;
+ }
+
+ double[] lab = new double[3];
+ ColorUtils.colorToLAB(findFg ? fg : bg, lab);
+
+ double low = 0, high = lab[0];
+ final double a = lab[1], b = lab[2];
+ for (int i = 0; i < 15 && high - low > 0.00001; i++) {
+ final double l = (low + high) / 2;
+ if (findFg) {
+ fg = ColorUtils.LABToColor(l, a, b);
+ } else {
+ bg = ColorUtils.LABToColor(l, a, b);
+ }
+ if (ColorUtils.calculateContrast(fg, bg) > minRatio) {
+ low = l;
+ } else {
+ high = l;
+ }
+ }
+ return ColorUtils.LABToColor(low, a, b);
+ }
+
private static int getMutedColor(int color) {
int alpha = (int) (255 * 0.15f);
return ColorUtils.compositeColors(ColorUtils.setAlphaComponent(color, alpha), Color.WHITE);
diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java
index 2ae7a4a..472b913 100644
--- a/src/com/android/launcher3/graphics/LauncherIcons.java
+++ b/src/com/android/launcher3/graphics/LauncherIcons.java
@@ -29,10 +29,13 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
+import android.graphics.drawable.ScaleDrawable;
import android.os.Process;
import android.os.UserHandle;
+import android.view.Gravity;
import com.android.launcher3.AppInfo;
import com.android.launcher3.IconCache;
@@ -45,12 +48,12 @@
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
-import java.lang.reflect.Method;
-
/**
* Helper methods for generating various launcher icons
*/
public class LauncherIcons {
+ // TODO b/33553066 use the constant defined in MaskableIconDrawable
+ private static final float LEGACY_ICON_SCALE = .7f * .6667f;
private static final Rect sOldBounds = new Rect();
private static final Canvas sCanvas = new Canvas();
@@ -168,7 +171,7 @@
* @param scale the scale to apply before drawing {@param icon} on the canvas
*/
public static Bitmap createIconBitmap(Drawable icon, Context context, float scale) {
- icon = castToMaskableIconDrawable(icon);
+ icon = wrapToMaskableIconDrawable(context, icon);
synchronized (sCanvas) {
final int iconBitmapSize = LauncherAppState.getIDP(context).iconBitmapSize;
@@ -224,17 +227,31 @@
}
}
- static Drawable castToMaskableIconDrawable(Drawable drawable) {
+ /**
+ * If the platform is running O but the app is not providing MaskableIconDrawable, then
+ * shrink the legacy icon and set it as foreground. Use color drawable as background to
+ * create MaskableIconDrawable.
+ */
+ static Drawable wrapToMaskableIconDrawable(Context context, Drawable drawable) {
if (!(ProviderConfig.IS_DOGFOOD_BUILD && Utilities.isAtLeastO())) {
return drawable;
}
+ int color = context.getResources().getColor(R.color.legacy_icon_background);
+ ColorDrawable colorDrawable = new ColorDrawable(color);
+ ScaleDrawable scaleDrawable = new ScaleDrawable(drawable,
+ Gravity.CENTER, LEGACY_ICON_SCALE, LEGACY_ICON_SCALE);
+ scaleDrawable.setLevel(1);
try {
Class clazz = Class.forName("android.graphics.drawable.MaskableIconDrawable");
- Method method = clazz.getDeclaredMethod("wrap", Drawable.class);
- return (Drawable) method.invoke(null, drawable);
+ if (!clazz.isAssignableFrom(drawable.getClass())){
+
+ return (Drawable) clazz.getConstructor(Drawable.class, Drawable.class)
+ .newInstance(colorDrawable, scaleDrawable);
+ }
} catch (Exception e) {
return drawable;
}
+ return drawable;
}
public static Bitmap createShortcutIcon(ShortcutInfoCompat shortcutInfo, Context context) {
diff --git a/src/com/android/launcher3/notification/NotificationFooterLayout.java b/src/com/android/launcher3/notification/NotificationFooterLayout.java
index f84ddb1..58789f6 100644
--- a/src/com/android/launcher3/notification/NotificationFooterLayout.java
+++ b/src/com/android/launcher3/notification/NotificationFooterLayout.java
@@ -58,6 +58,7 @@
LinearLayout.LayoutParams mIconLayoutParams;
private LinearLayout mIconRow;
+ private int mBackgroundColor;
private int mTextColor;
public NotificationFooterLayout(Context context) {
@@ -87,7 +88,8 @@
}
public void applyColors(IconPalette iconPalette) {
- setBackgroundTintList(ColorStateList.valueOf(iconPalette.backgroundColor));
+ mBackgroundColor = iconPalette.backgroundColor;
+ setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor));
findViewById(R.id.divider).setBackgroundColor(iconPalette.secondaryColor);
mTextColor = iconPalette.textColor;
}
@@ -126,7 +128,7 @@
private void addNotificationIconForInfo(NotificationInfo info, boolean fromOverflow) {
View icon = new View(getContext());
- icon.setBackground(info.iconDrawable);
+ icon.setBackground(info.getIconForBackground(getContext(), mBackgroundColor));
icon.setOnClickListener(info);
int addIndex = mIconRow.getChildCount();
if (fromOverflow) {
diff --git a/src/com/android/launcher3/notification/NotificationInfo.java b/src/com/android/launcher3/notification/NotificationInfo.java
index bf57b2a..af5e817 100644
--- a/src/com/android/launcher3/notification/NotificationInfo.java
+++ b/src/com/android/launcher3/notification/NotificationInfo.java
@@ -25,6 +25,7 @@
import android.view.View;
import com.android.launcher3.Launcher;
+import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.util.PackageUserKey;
@@ -41,11 +42,14 @@
public final String notificationKey;
public final CharSequence title;
public final CharSequence text;
- public final Drawable iconDrawable;
public final PendingIntent intent;
public final boolean autoCancel;
public final boolean dismissable;
+ private final Drawable mIconDrawable;
+ private boolean mShouldTintIcon;
+ private int mIconColor;
+
/**
* Extracts the data that we need from the StatusBarNotification.
*/
@@ -60,10 +64,12 @@
Icon icon = notification.getLargeIcon();
if (icon == null) {
icon = notification.getSmallIcon();
- iconDrawable = icon.loadDrawable(context);
- iconDrawable.setTint(statusBarNotification.getNotification().color);
+ mIconDrawable = icon.loadDrawable(context);
+ mIconColor = statusBarNotification.getNotification().color;
+ mShouldTintIcon = true;
} else {
- iconDrawable = icon.loadDrawable(context);
+ mIconDrawable = icon.loadDrawable(context);
+ mShouldTintIcon = false;
}
intent = notification.contentIntent;
autoCancel = (notification.flags & Notification.FLAG_AUTO_CANCEL) != 0;
@@ -83,4 +89,18 @@
}
PopupContainerWithArrow.getOpen(launcher).close(true);
}
+
+ public Drawable getIconForBackground(Context context, int background) {
+ if (!mShouldTintIcon) {
+ return mIconDrawable;
+ }
+ mIconColor = IconPalette.resolveContrastColor(context, mIconColor, background);
+ Drawable icon = mIconDrawable.mutate();
+ // DrawableContainer ignores the color filter if it's already set, so clear it first to
+ // get it set and invalidated properly.
+ icon.setTintList(null);
+ icon.setTint(mIconColor);
+ mShouldTintIcon = false;
+ return icon;
+ }
}
diff --git a/src/com/android/launcher3/notification/NotificationItemView.java b/src/com/android/launcher3/notification/NotificationItemView.java
index b74cd4e..422722d 100644
--- a/src/com/android/launcher3/notification/NotificationItemView.java
+++ b/src/com/android/launcher3/notification/NotificationItemView.java
@@ -35,7 +35,9 @@
import com.android.launcher3.popup.PopupItemView;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import static com.android.launcher3.LauncherAnimUtils.animateViewHeight;
@@ -117,7 +119,7 @@
mHeader.setBackgroundTintList(ColorStateList.valueOf(iconPalette.backgroundColor));
mHeader.setTextColor(ColorStateList.valueOf(iconPalette.textColor));
mDivider.setBackgroundColor(iconPalette.secondaryColor);
- mMainView.setBackgroundColor(iconPalette.backgroundColor);
+ mMainView.applyColors(iconPalette);
mFooter.applyColors(iconPalette);
}
@@ -135,7 +137,7 @@
@Override
public void onIconAnimationEnd(NotificationInfo newMainNotification) {
if (newMainNotification != null) {
- mMainView.applyNotificationInfo(newMainNotification, mIconView, mIconPalette);
+ mMainView.applyNotificationInfo(newMainNotification, mIconView, true);
// Remove the animated notification from the footer by calling trim
// TODO: Remove the notification in NotificationFooterLayout directly
// instead of relying on this hack.
diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java
index 2997d40..76a84b7 100644
--- a/src/com/android/launcher3/notification/NotificationMainView.java
+++ b/src/com/android/launcher3/notification/NotificationMainView.java
@@ -41,6 +41,7 @@
private NotificationInfo mNotificationInfo;
private TextView mTitleView;
private TextView mTextView;
+ private IconPalette mIconPalette;
public NotificationMainView(Context context) {
this(context, null, 0);
@@ -62,35 +63,38 @@
mTextView = (TextView) findViewById(R.id.text);
}
+ public void applyColors(IconPalette iconPalette) {
+ setBackgroundColor(iconPalette.backgroundColor);
+ mIconPalette = iconPalette;
+ }
+
public void applyNotificationInfo(NotificationInfo mainNotification, View iconView) {
- applyNotificationInfo(mainNotification, iconView, null);
+ applyNotificationInfo(mainNotification, iconView, false);
}
/**
- * @param iconPalette if not null, indicates that the new info should be animated in,
- * and that part of this animation includes animating the background
- * from iconPalette.secondaryColor to iconPalette.backgroundColor.
+ * Sets the content of this view, animating it after a new icon shifts up if necessary.
*/
public void applyNotificationInfo(NotificationInfo mainNotification, View iconView,
- @Nullable IconPalette iconPalette) {
- boolean animate = iconPalette != null;
+ boolean animate) {
if (animate) {
mTitleView.setAlpha(0);
mTextView.setAlpha(0);
- setBackgroundColor(iconPalette.secondaryColor);
+ setBackgroundColor(mIconPalette.secondaryColor);
}
mNotificationInfo = mainNotification;
mTitleView.setText(mNotificationInfo.title);
mTextView.setText(mNotificationInfo.text);
- iconView.setBackground(mNotificationInfo.iconDrawable);
+ iconView.setBackground(mNotificationInfo.getIconForBackground(
+ getContext(), mIconPalette.backgroundColor));
setOnClickListener(mNotificationInfo);
setTranslationX(0);
if (animate) {
AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
Animator textFade = new LauncherViewPropertyAnimator(mTextView).alpha(1);
Animator titleFade = new LauncherViewPropertyAnimator(mTitleView).alpha(1);
- ValueAnimator colorChange = ValueAnimator.ofArgb(iconPalette.secondaryColor,
- iconPalette.backgroundColor);
+ ValueAnimator colorChange = ValueAnimator.ofArgb(mIconPalette.secondaryColor,
+ mIconPalette.backgroundColor);
colorChange.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
diff --git a/src/com/android/launcher3/util/SQLiteCacheHelper.java b/src/com/android/launcher3/util/SQLiteCacheHelper.java
index d1cfe42..9aabfeb 100644
--- a/src/com/android/launcher3/util/SQLiteCacheHelper.java
+++ b/src/com/android/launcher3/util/SQLiteCacheHelper.java
@@ -9,6 +9,9 @@
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.config.ProviderConfig;
+
/**
* An extension of {@link SQLiteOpenHelper} with utility methods for a single table cache DB.
* Any exception during write operations are ignored, and any version change causes a DB reset.
@@ -16,12 +19,18 @@
public abstract class SQLiteCacheHelper {
private static final String TAG = "SQLiteCacheHelper";
+ private static final boolean NO_ICON_CACHE = ProviderConfig.IS_DOGFOOD_BUILD &&
+ Utilities.isPropertyEnabled("MEMORY_ONLY_ICON_CACHE");
+
private final String mTableName;
private final MySQLiteOpenHelper mOpenHelper;
private boolean mIgnoreWrites;
public SQLiteCacheHelper(Context context, String name, int version, String tableName) {
+ if (NO_ICON_CACHE) {
+ name = null;
+ }
mTableName = tableName;
mOpenHelper = new MySQLiteOpenHelper(context, name, version);
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
new file mode 100644
index 0000000..a4698c2
--- /dev/null
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -0,0 +1,191 @@
+/*
+ * 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.widget;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DragSource;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.PendingAddItemInfo;
+import com.android.launcher3.Workspace;
+import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.graphics.DragPreviewProvider;
+import com.android.launcher3.graphics.HolographicOutlineHelper;
+import com.android.launcher3.graphics.LauncherIcons;
+
+/**
+ * Extension of {@link DragPreviewProvider} with logic specific to pending widgets/shortcuts
+ * dragged from the widget tray.
+ */
+public class PendingItemDragHelper extends DragPreviewProvider {
+
+ private static final float MAX_WIDGET_SCALE = 1.25f;
+
+ private final PendingAddItemInfo mAddInfo;
+
+ private Bitmap mPreviewBitmap;
+
+ public PendingItemDragHelper(View view) {
+ super(view);
+ mAddInfo = (PendingAddItemInfo) view.getTag();
+ }
+
+ /**
+ * Starts the drag for the pending item associated with the view.
+ *
+ * @param previewBounds The bounds where the image was displayed,
+ * {@link WidgetImageView#getBitmapBounds()}
+ * @param previewBitmapWidth The actual width of the bitmap displayed in the view.
+ * @param previewViewWidth The width of {@link WidgetImageView} displaying the preview
+ * @param screenPos Position of {@link WidgetImageView} on the screen
+ */
+ public void startDrag(Rect previewBounds, int previewBitmapWidth, int previewViewWidth,
+ Point screenPos, DragSource source, DragOptions options) {
+ final Launcher launcher = Launcher.getLauncher(mView.getContext());
+ LauncherAppState app = LauncherAppState.getInstance(launcher);
+
+ final Bitmap preview;
+ final float scale;
+ final Point dragOffset;
+ final Rect dragRegion;
+
+
+ if (mAddInfo instanceof PendingAddWidgetInfo) {
+ PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) mAddInfo;
+ int[] size = launcher.getWorkspace().estimateItemSize(createWidgetInfo, true, false);
+
+ int maxWidth = Math.min((int) (previewBitmapWidth * MAX_WIDGET_SCALE), size[0]);
+
+ int[] previewSizeBeforeScale = new int[1];
+ preview = app.getWidgetCache() .generateWidgetPreview(
+ launcher, createWidgetInfo.info, maxWidth, null, previewSizeBeforeScale);
+
+ if (previewSizeBeforeScale[0] < previewBitmapWidth) {
+ // The icon has extra padding around it.
+ int padding = (previewBitmapWidth - previewSizeBeforeScale[0]) / 2;
+ if (previewBitmapWidth > previewViewWidth) {
+ padding = padding * previewViewWidth / previewBitmapWidth;
+ }
+
+ previewBounds.left += padding;
+ previewBounds.right -= padding;
+ }
+ scale = previewBounds.width() / (float) preview.getWidth();
+ launcher.getDragController().addDragListener(new WidgetHostViewLoader(launcher, mView));
+
+ dragOffset = null;
+ dragRegion = null;
+ } else {
+ PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) mAddInfo;
+ Drawable icon = createShortcutInfo.activityInfo.getFullResIcon(app.getIconCache());
+ preview = LauncherIcons.createScaledBitmapWithoutShadow(icon, launcher);
+ mAddInfo.spanX = mAddInfo.spanY = 1;
+ scale = ((float) launcher.getDeviceProfile().iconSizePx) / preview.getWidth();
+
+ dragOffset = new Point(previewPadding / 2, previewPadding / 2);
+
+ // Create a preview same as the workspace cell size and draw the icon at the
+ // appropriate position.
+ int[] size = launcher.getWorkspace().estimateItemSize(mAddInfo, false, true);
+ DeviceProfile dp = launcher.getDeviceProfile();
+ int iconSize = dp.iconSizePx;
+
+ dragRegion = new Rect();
+ dragRegion.left = (size[0] - iconSize) / 2;
+ dragRegion.right = dragRegion.left + iconSize;
+ dragRegion.top = (size[1] - iconSize - dp.iconTextSizePx - dp.iconDrawablePaddingPx) / 2;
+ dragRegion.bottom = dragRegion.top + iconSize;
+ }
+
+ // Since we are not going through the workspace for starting the drag, set drag related
+ // information on the workspace before starting the drag.
+ launcher.getWorkspace().prepareDragWithProvider(this);
+
+ int dragLayerX = screenPos.x + previewBounds.left
+ + (int) ((scale * preview.getWidth() - preview.getWidth()) / 2);
+ int dragLayerY = screenPos.y + previewBounds.top
+ + (int) ((scale * preview.getHeight() - preview.getHeight()) / 2);
+
+ mPreviewBitmap = preview;
+ // Start the drag
+ launcher.getDragController().startDrag(preview, dragLayerX, dragLayerY, source, mAddInfo,
+ dragOffset, dragRegion, scale, options);
+ }
+
+
+ @Override
+ public Bitmap createDragOutline(Canvas canvas) {
+ if (mAddInfo instanceof PendingAddShortcutInfo) {
+ int width = mPreviewBitmap.getWidth();
+ int height = mPreviewBitmap.getHeight();
+ Bitmap b = Bitmap.createBitmap(width + blurSizeOutline, height + blurSizeOutline,
+ Bitmap.Config.ALPHA_8);
+ canvas.setBitmap(b);
+
+ Launcher launcher = Launcher.getLauncher(mView.getContext());
+ int size = launcher.getDeviceProfile().iconSizePx;
+
+ Rect src = new Rect(0, 0, mPreviewBitmap.getWidth(), mPreviewBitmap.getHeight());
+ Rect dst = new Rect(0, 0, size, size);
+ dst.offset(blurSizeOutline / 2, blurSizeOutline / 2);
+ canvas.drawBitmap(mPreviewBitmap, src, dst, new Paint(Paint.FILTER_BITMAP_FLAG));
+
+ HolographicOutlineHelper.getInstance(mView.getContext())
+ .applyExpensiveOutlineWithBlur(b, canvas);
+
+ canvas.setBitmap(null);
+ return b;
+ }
+
+ Workspace workspace = Launcher.getLauncher(mView.getContext()).getWorkspace();
+ int[] size = workspace.estimateItemSize(mAddInfo, false, false);
+
+ int w = size[0];
+ int h = size[1];
+ final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ALPHA_8);
+ canvas.setBitmap(b);
+
+ Rect src = new Rect(0, 0, mPreviewBitmap.getWidth(), mPreviewBitmap.getHeight());
+ float scaleFactor = Math.min((w - blurSizeOutline) / (float) mPreviewBitmap.getWidth(),
+ (h - blurSizeOutline) / (float) mPreviewBitmap.getHeight());
+ int scaledWidth = (int) (scaleFactor * mPreviewBitmap.getWidth());
+ int scaledHeight = (int) (scaleFactor * mPreviewBitmap.getHeight());
+ Rect dst = new Rect(0, 0, scaledWidth, scaledHeight);
+
+ // center the image
+ dst.offset((w - scaledWidth) / 2, (h - scaledHeight) / 2);
+
+ canvas.drawBitmap(mPreviewBitmap, src, dst, null);
+
+ // Don't clip alpha values for the drag outline if we're using the default widget preview
+ boolean clipAlpha = !(mAddInfo instanceof PendingAddWidgetInfo &&
+ (((PendingAddWidgetInfo) mAddInfo).previewImage == 0));
+ HolographicOutlineHelper.getInstance(mView.getContext())
+ .applyExpensiveOutlineWithBlur(b, canvas, clipAlpha);
+ canvas.setBitmap(null);
+
+ return b;
+ }
+}
diff --git a/src/com/android/launcher3/widget/PendingItemPreviewProvider.java b/src/com/android/launcher3/widget/PendingItemPreviewProvider.java
deleted file mode 100644
index 3a49a6c..0000000
--- a/src/com/android/launcher3/widget/PendingItemPreviewProvider.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.widget;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.view.View;
-
-import com.android.launcher3.graphics.HolographicOutlineHelper;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.PendingAddItemInfo;
-import com.android.launcher3.Workspace;
-import com.android.launcher3.graphics.DragPreviewProvider;
-
-/**
- * Extension of {@link DragPreviewProvider} with logic specific to pending widgets/shortcuts
- * dragged from the widget tray.
- */
-public class PendingItemPreviewProvider extends DragPreviewProvider {
-
- private final PendingAddItemInfo mAddInfo;
- private final Bitmap mPreviewBitmap;
-
- public PendingItemPreviewProvider(View view, PendingAddItemInfo addInfo, Bitmap preview) {
- super(view);
- mAddInfo = addInfo;
- mPreviewBitmap = preview;
- }
-
- @Override
- public Bitmap createDragOutline(Canvas canvas) {
- Workspace workspace = Launcher.getLauncher(mView.getContext()).getWorkspace();
- int[] size = workspace.estimateItemSize(mAddInfo, false, false);
-
- int w = size[0];
- int h = size[1];
- final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ALPHA_8);
- canvas.setBitmap(b);
-
- Rect src = new Rect(0, 0, mPreviewBitmap.getWidth(), mPreviewBitmap.getHeight());
- float scaleFactor = Math.min((w - blurSizeOutline) / (float) mPreviewBitmap.getWidth(),
- (h - blurSizeOutline) / (float) mPreviewBitmap.getHeight());
- int scaledWidth = (int) (scaleFactor * mPreviewBitmap.getWidth());
- int scaledHeight = (int) (scaleFactor * mPreviewBitmap.getHeight());
- Rect dst = new Rect(0, 0, scaledWidth, scaledHeight);
-
- // center the image
- dst.offset((w - scaledWidth) / 2, (h - scaledHeight) / 2);
-
- canvas.drawBitmap(mPreviewBitmap, src, dst, null);
-
- // Don't clip alpha values for the drag outline if we're using the default widget preview
- boolean clipAlpha = !(mAddInfo instanceof PendingAddWidgetInfo &&
- (((PendingAddWidgetInfo) mAddInfo).previewImage == 0));
- HolographicOutlineHelper.getInstance(mView.getContext())
- .applyExpensiveOutlineWithBlur(b, canvas, clipAlpha);
- canvas.setBitmap(null);
-
- return b;
- }
-}
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
index d1421e0..b2321a7 100644
--- a/src/com/android/launcher3/widget/WidgetsContainerView.java
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -17,9 +17,7 @@
package com.android.launcher3.widget;
import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
+import android.graphics.Point;
import android.support.v7.widget.LinearLayoutManager;
import android.util.AttributeSet;
import android.util.Log;
@@ -35,17 +33,13 @@
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.WidgetPreviewLoader;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.folder.Folder;
-import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.model.WidgetItem;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.MultiHashMap;
@@ -71,9 +65,6 @@
/* Touch handling related member variables. */
private Toast mWidgetInstructionToast;
- /* Rendering related. */
- private WidgetPreviewLoader mWidgetPreviewLoader;
-
public WidgetsContainerView(Context context) {
this(context, null);
}
@@ -174,7 +165,6 @@
private boolean beginDraggingWidget(WidgetCell v) {
// Get the widget preview as the drag representation
WidgetImageView image = (WidgetImageView) v.findViewById(R.id.widget_preview);
- PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
// If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
// we abort the drag.
@@ -182,55 +172,12 @@
return false;
}
- // Compose the drag image
- Bitmap preview;
- final float scale;
- final Rect bounds = image.getBitmapBounds();
+ int[] loc = new int[2];
+ mLauncher.getDragLayer().getLocationInDragLayer(image, loc);
- if (createItemInfo instanceof PendingAddWidgetInfo) {
- // This can happen in some weird cases involving multi-touch. We can't start dragging
- // the widget if this is null, so we break out.
-
- PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) createItemInfo;
- int[] size = mLauncher.getWorkspace().estimateItemSize(createWidgetInfo, true, false);
-
- Bitmap icon = image.getBitmap();
- float minScale = 1.25f;
- int maxWidth = Math.min((int) (icon.getWidth() * minScale), size[0]);
-
- int[] previewSizeBeforeScale = new int[1];
- preview = getWidgetPreviewLoader().generateWidgetPreview(mLauncher,
- createWidgetInfo.info, maxWidth, null, previewSizeBeforeScale);
-
- if (previewSizeBeforeScale[0] < icon.getWidth()) {
- // The icon has extra padding around it.
- int padding = (icon.getWidth() - previewSizeBeforeScale[0]) / 2;
- if (icon.getWidth() > image.getWidth()) {
- padding = padding * image.getWidth() / icon.getWidth();
- }
-
- bounds.left += padding;
- bounds.right -= padding;
- }
- scale = bounds.width() / (float) preview.getWidth();
-
- mLauncher.getDragController().addDragListener(new WidgetHostViewLoader(mLauncher, v));
- } else {
- PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag();
- Drawable icon = createShortcutInfo.activityInfo.getFullResIcon(mIconCache);
- preview = LauncherIcons.createIconBitmap(icon, mLauncher);
- createItemInfo.spanX = createItemInfo.spanY = 1;
- scale = ((float) mLauncher.getDeviceProfile().iconSizePx) / preview.getWidth();
- }
-
- // Since we are not going through the workspace for starting the drag, set drag related
- // information on the workspace before starting the drag.
- mLauncher.getWorkspace().prepareDragWithProvider(
- new PendingItemPreviewProvider(v, createItemInfo, preview));
-
- // Start the drag
- mDragController.startDrag(image, preview, this, createItemInfo,
- bounds, scale, new DragOptions());
+ new PendingItemDragHelper(v).startDrag(
+ image.getBitmapBounds(), image.getBitmap().getWidth(), image.getWidth(),
+ new Point(loc[0], loc[1]), this, new DragOptions());
return true;
}
@@ -294,13 +241,6 @@
return mAdapter.getItemCount() == 0;
}
- private WidgetPreviewLoader getWidgetPreviewLoader() {
- if (mWidgetPreviewLoader == null) {
- mWidgetPreviewLoader = LauncherAppState.getInstance(getContext()).getWidgetCache();
- }
- return mWidgetPreviewLoader;
- }
-
@Override
public void fillInLogContainerData(View v, ItemInfo info, Target target, Target targetParent) {
targetParent.containerType = ContainerType.WIDGETS;