diff options
Diffstat (limited to 'src')
23 files changed, 446 insertions, 214 deletions
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java index 02958d060..fcb04ea08 100644 --- a/src/com/android/launcher3/AppWidgetResizeFrame.java +++ b/src/com/android/launcher3/AppWidgetResizeFrame.java @@ -95,13 +95,13 @@ public class AppWidgetResizeFrame extends FrameLayout { mLeftHandle = new ImageView(context); mLeftHandle.setImageResource(R.drawable.widget_resize_handle_left); lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, - Gravity.START | Gravity.CENTER_VERTICAL); + Gravity.LEFT | Gravity.CENTER_VERTICAL); addView(mLeftHandle, lp); mRightHandle = new ImageView(context); mRightHandle.setImageResource(R.drawable.widget_resize_handle_right); lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, - Gravity.END | Gravity.CENTER_VERTICAL); + Gravity.RIGHT | Gravity.CENTER_VERTICAL); addView(mRightHandle, lp); mTopHandle = new ImageView(context); diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java index dd870e402..4e9d68b50 100644 --- a/src/com/android/launcher3/AppsCustomizePagedView.java +++ b/src/com/android/launcher3/AppsCustomizePagedView.java @@ -500,6 +500,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen mPressedIcon.lockDrawableState(); } mLauncher.startActivitySafely(v, appInfo.intent, appInfo); + mLauncher.getStats().recordLaunch(appInfo.intent); } else if (v instanceof PagedViewWidget) { // Let the user know that they have to long press to add a widget if (mWidgetInstructionToast != null) { diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 22492ac31..a114ec383 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -927,6 +927,8 @@ public class CellLayout extends ViewGroup { return r; } + /** Return a rect that has the cellWidth/cellHeight (left, top), and + * widthGap/heightGap (right, bottom) */ static void getMetrics(Rect metrics, int paddedMeasureWidth, int paddedMeasureHeight, int countX, int countY) { LauncherAppState app = LauncherAppState.getInstance(); diff --git a/src/com/android/launcher3/Cling.java b/src/com/android/launcher3/Cling.java index 7ca699030..2656ad6a8 100644 --- a/src/com/android/launcher3/Cling.java +++ b/src/com/android/launcher3/Cling.java @@ -70,6 +70,9 @@ public class Cling extends FrameLayout implements Insettable, View.OnLongClickLi private Paint mBubblePaint; private Paint mDotPaint; + private View mScrimView; + private int mBackgroundColor; + private final Rect mInsets = new Rect(); public Cling(Context context) { @@ -91,9 +94,11 @@ public class Cling extends FrameLayout implements Insettable, View.OnLongClickLi } - void init(Launcher l, int[] positionData) { + void init(Launcher l, View scrim) { if (!mIsInitialized) { mLauncher = l; + mScrimView = scrim; + mBackgroundColor = 0xdd000000; setOnLongClickListener(this); mErasePaint = new Paint(); @@ -128,10 +133,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnLongClickLi content.animate() .alpha(1f) .setDuration(duration) - .setListener(new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { - }; - }) + .setListener(null) .start(); setAlpha(1f); } else { @@ -142,11 +144,24 @@ public class Cling extends FrameLayout implements Insettable, View.OnLongClickLi .alpha(1f) .setInterpolator(new AccelerateInterpolator()) .setDuration(duration) + .setListener(null) .start(); } else { setAlpha(1f); } } + + // Show the scrim if necessary + if (mScrimView != null) { + mScrimView.setVisibility(View.VISIBLE); + mScrimView.setAlpha(0f); + mScrimView.animate() + .alpha(1f) + .setDuration(duration) + .setListener(null) + .start(); + } + setFocusableInTouchMode(true); post(new Runnable() { public void run() { @@ -160,26 +175,42 @@ public class Cling extends FrameLayout implements Insettable, View.OnLongClickLi if (mDrawIdentifier.equals(FIRST_RUN_PORTRAIT) || mDrawIdentifier.equals(FIRST_RUN_LANDSCAPE)) { View content = getContent(); - ObjectAnimator anim = LauncherAnimUtils.ofFloat(content, "alpha", 0f); - anim.setDuration(duration); - anim.addListener(new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { - // We are about to trigger the workspace cling, so don't do anything else - setVisibility(View.GONE); - postCb.run(); - }; - }); - anim.start(); + content.animate() + .alpha(0f) + .setDuration(duration) + .setListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + // We are about to trigger the workspace cling, so don't do anything else + setVisibility(View.GONE); + postCb.run(); + }; + }) + .start(); } else { - ObjectAnimator anim = LauncherAnimUtils.ofFloat(this, "alpha", 0f); - anim.setDuration(duration); - anim.addListener(new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { - setVisibility(View.GONE); - postCb.run(); - }; - }); - anim.start(); + animate() + .alpha(0f) + .setDuration(duration) + .setListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + // We are about to trigger the workspace cling, so don't do anything else + setVisibility(View.GONE); + postCb.run(); + }; + }) + .start(); + } + + // Show the scrim if necessary + if (mScrimView != null) { + mScrimView.animate() + .alpha(0f) + .setDuration(duration) + .setListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + mScrimView.setVisibility(View.GONE); + }; + }) + .start(); } } @@ -188,6 +219,12 @@ public class Cling extends FrameLayout implements Insettable, View.OnLongClickLi mIsInitialized = false; } + void bringScrimToFront() { + if (mScrimView != null) { + mScrimView.bringToFront(); + } + } + @Override public void setInsets(Rect insets) { mInsets.set(insets); @@ -262,13 +299,12 @@ public class Cling extends FrameLayout implements Insettable, View.OnLongClickLi // Draw the background Bitmap eraseBg = null; Canvas eraseCanvas = null; - if (mBackground != null) { + if (mScrimView != null) { + // Skip drawing the background + mScrimView.setBackgroundColor(mBackgroundColor); + } else if (mBackground != null) { mBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); mBackground.draw(canvas); - } else if (mDrawIdentifier.equals(FOLDER_PORTRAIT) || - mDrawIdentifier.equals(FOLDER_LANDSCAPE) || - mDrawIdentifier.equals(FOLDER_LARGE)) { - canvas.drawColor(0xcc000000); } else if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) || mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) || mDrawIdentifier.equals(WORKSPACE_LARGE)) { @@ -276,9 +312,9 @@ public class Cling extends FrameLayout implements Insettable, View.OnLongClickLi eraseBg = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); eraseCanvas = new Canvas(eraseBg); - eraseCanvas.drawColor(0xdd000000); + eraseCanvas.drawColor(mBackgroundColor); } else { - canvas.drawColor(0xdd000000); + canvas.drawColor(mBackgroundColor); } // Draw everything else diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java index 56f595c74..da6f2f79b 100644 --- a/src/com/android/launcher3/DeleteDropTarget.java +++ b/src/com/android/launcher3/DeleteDropTarget.java @@ -175,16 +175,10 @@ public class DeleteDropTarget extends ButtonDropTarget { boolean isVisible = true; boolean isUninstall = false; - // If we are dragging a widget from AppsCustomize, hide the delete target - if (isAllAppsWidget(source, info)) { - isVisible = false; - } - // If we are dragging an application from AppsCustomize, only show the control if we can - // delete the app (it was downloaded), and rename the string to "uninstall" in such a case - if (willAcceptDrop(info)) { - isVisible = true; - } else { + // delete the app (it was downloaded), and rename the string to "uninstall" in such a case. + // Hide the delete target if it is a widget from AppsCustomize. + if (!willAcceptDrop(info) || isAllAppsWidget(source, info)) { isVisible = false; } diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java index 4c4f399a9..5b5c35c5a 100644 --- a/src/com/android/launcher3/DragController.java +++ b/src/com/android/launcher3/DragController.java @@ -24,8 +24,8 @@ import android.graphics.PointF; import android.graphics.Rect; import android.os.Handler; import android.os.IBinder; -import android.os.Vibrator; import android.util.Log; +import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.VelocityTracker; @@ -50,8 +50,7 @@ public class DragController { public static int DRAG_ACTION_COPY = 1; private static final int SCROLL_DELAY = 500; - private static final int RESCROLL_DELAY = 750; - private static final int VIBRATE_DURATION = 15; + private static final int RESCROLL_DELAY = PagedView.PAGE_SNAP_ANIMATION_DURATION + 150; private static final boolean PROFILE_DRAWING_DURING_DRAG = false; @@ -66,7 +65,6 @@ public class DragController { private Launcher mLauncher; private Handler mHandler; - private final Vibrator mVibrator; // temporaries to avoid gc thrash private Rect mRectTemp = new Rect(); @@ -150,7 +148,6 @@ public class DragController { mHandler = new Handler(); mScrollZone = r.getDimensionPixelSize(R.dimen.scroll_zone); mVelocityTracker = VelocityTracker.obtain(); - mVibrator = (Vibrator) launcher.getSystemService(Context.VIBRATOR_SERVICE); float density = r.getDisplayMetrics().density; mFlingToDeleteThresholdVelocity = @@ -240,8 +237,6 @@ public class DragController { mDragObject.dragSource = source; mDragObject.dragInfo = dragInfo; - mVibrator.vibrate(VIBRATE_DURATION); - final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX, registrationY, 0, 0, b.getWidth(), b.getHeight(), initialDragViewScale); @@ -252,6 +247,7 @@ public class DragController { dragView.setDragRegion(new Rect(dragRegion)); } + mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); dragView.show(mMotionDownX, mMotionDownY); handleMoveEvent(mMotionDownX, mMotionDownY); } @@ -506,6 +502,8 @@ public class DragController { public void forceTouchMove() { int[] dummyCoordinates = mCoordinatesTemp; DropTarget dropTarget = findDropTarget(mLastTouch[0], mLastTouch[1], dummyCoordinates); + mDragObject.x = dummyCoordinates[0]; + mDragObject.y = dummyCoordinates[1]; checkTouchMove(dropTarget); } diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java index 9c649edda..3c955cbe3 100644 --- a/src/com/android/launcher3/DragLayer.java +++ b/src/com/android/launcher3/DragLayer.java @@ -107,7 +107,7 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams(); if (child instanceof Insettable) { ((Insettable)child).setInsets(insets); - } else { + } else { flp.topMargin += (insets.top - mInsets.top); flp.leftMargin += (insets.left - mInsets.left); flp.rightMargin += (insets.right - mInsets.right); diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java index 495e930f9..33eb595ef 100644 --- a/src/com/android/launcher3/DynamicGrid.java +++ b/src/com/android/launcher3/DynamicGrid.java @@ -290,7 +290,8 @@ class DeviceProfile { Rect getWorkspacePadding(int orientation) { Rect padding = new Rect(); - if (isVerticalBarLayout()) { + if (orientation == CellLayout.LANDSCAPE && + transposeLayoutWithOrientation) { // Pad the left and right of the workspace with search/hotseat bar sizes padding.set(searchBarSpaceHeightPx, edgeMarginPx, hotseatBarHeightPx, edgeMarginPx); @@ -358,14 +359,14 @@ class DeviceProfile { boolean hasVerticalBarLayout = isVerticalBarLayout(); // Layout the search bar space - View searchBarSpace = launcher.findViewById(R.id.qsb_bar); - lp = (FrameLayout.LayoutParams) searchBarSpace.getLayoutParams(); + View searchBar = launcher.getSearchBar(); + lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams(); if (hasVerticalBarLayout) { // Vertical search bar lp.gravity = Gravity.TOP | Gravity.LEFT; lp.width = searchBarSpaceHeightPx; lp.height = LayoutParams.MATCH_PARENT; - searchBarSpace.setPadding( + searchBar.setPadding( 0, 2 * edgeMarginPx, 0, 2 * edgeMarginPx); } else { @@ -373,19 +374,19 @@ class DeviceProfile { lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; lp.width = searchBarSpaceWidthPx; lp.height = searchBarSpaceHeightPx; - searchBarSpace.setPadding( + searchBar.setPadding( 2 * edgeMarginPx, 2 * edgeMarginPx, 2 * edgeMarginPx, 0); } - searchBarSpace.setLayoutParams(lp); + searchBar.setLayoutParams(lp); // Layout the search bar - View searchBar = launcher.getQsbBar(); - lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams(); - lp.width = LayoutParams.MATCH_PARENT; - lp.height = LayoutParams.MATCH_PARENT; - searchBar.setLayoutParams(lp); + View qsbBar = launcher.getQsbBar(); + LayoutParams vglp = qsbBar.getLayoutParams(); + vglp.width = LayoutParams.MATCH_PARENT; + vglp.height = LayoutParams.MATCH_PARENT; + qsbBar.setLayoutParams(vglp); // Layout the voice proxy View voiceButtonProxy = launcher.findViewById(R.id.voice_button_proxy); diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index a71d9b2c0..a4cb11734 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -453,8 +453,9 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList setLayerType(LAYER_TYPE_NONE, null); Cling cling = mLauncher.showFirstRunFoldersCling(); if (cling != null) { - cling.bringToFront(); + cling.bringScrimToFront(); bringToFront(); + cling.bringToFront(); } setFocusOnFirstChild(); } diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java index b31f45d57..821c15f52 100644 --- a/src/com/android/launcher3/InstallShortcutReceiver.java +++ b/src/com/android/launcher3/InstallShortcutReceiver.java @@ -37,7 +37,7 @@ import org.json.*; public class InstallShortcutReceiver extends BroadcastReceiver { public static final String ACTION_INSTALL_SHORTCUT = - "com.android.launcher3.action.INSTALL_SHORTCUT"; + "com.android.launcher.action.INSTALL_SHORTCUT"; public static final String DATA_INTENT_KEY = "intent.data"; public static final String LAUNCH_INTENT_KEY = "intent.launch"; @@ -102,6 +102,35 @@ public class InstallShortcutReceiver extends BroadcastReceiver { } } + public static void removeFromInstallQueue(SharedPreferences sharedPrefs, + ArrayList<String> packageNames) { + synchronized(sLock) { + Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null); + if (strings != null) { + Set<String> newStrings = new HashSet<String>(strings); + for (String json : newStrings) { + try { + JSONObject object = (JSONObject) new JSONTokener(json).nextValue(); + Intent launchIntent = Intent.parseUri(object.getString(LAUNCH_INTENT_KEY), 0); + String pn = launchIntent.getPackage(); + if (pn == null) { + pn = launchIntent.getComponent().getPackageName(); + } + if (packageNames.contains(pn)) { + newStrings.remove(json); + } + } catch (org.json.JSONException e) { + Log.d("InstallShortcutReceiver", "Exception reading shortcut to remove: " + e); + } catch (java.net.URISyntaxException e) { + Log.d("InstallShortcutReceiver", "Exception reading shortcut to remove: " + e); + } + } + sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, + new HashSet<String>(newStrings)).commit(); + } + } + } + private static ArrayList<PendingInstallShortcutInfo> getAndClearInstallQueue( SharedPreferences sharedPrefs) { synchronized(sLock) { @@ -115,7 +144,8 @@ public class InstallShortcutReceiver extends BroadcastReceiver { try { JSONObject object = (JSONObject) new JSONTokener(json).nextValue(); Intent data = Intent.parseUri(object.getString(DATA_INTENT_KEY), 0); - Intent launchIntent = Intent.parseUri(object.getString(LAUNCH_INTENT_KEY), 0); + Intent launchIntent = + Intent.parseUri(object.getString(LAUNCH_INTENT_KEY), 0); String name = object.getString(NAME_KEY); String iconBase64 = object.optString(ICON_KEY); String iconResourceName = object.optString(ICON_RESOURCE_NAME_KEY); @@ -137,9 +167,11 @@ public class InstallShortcutReceiver extends BroadcastReceiver { new PendingInstallShortcutInfo(data, name, launchIntent); infos.add(info); } catch (org.json.JSONException e) { - Log.d("InstallShortcutReceiver", "Exception reading shortcut to add: " + e); + Log.d("InstallShortcutReceiver", + "Exception reading shortcut to add: " + e); } catch (java.net.URISyntaxException e) { - Log.d("InstallShortcutReceiver", "Exception reading shortcut to add: " + e); + Log.d("InstallShortcutReceiver", + "Exception reading shortcut to add: " + e); } } sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, new HashSet<String>()).commit(); @@ -192,6 +224,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver { data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE); // Queue the item up for adding if launcher has not loaded properly yet + LauncherAppState.setApplicationContext(context.getApplicationContext()); LauncherAppState app = LauncherAppState.getInstance(); boolean launcherNotLoaded = (app.getDynamicGrid() == null); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 84d5a09f7..ba34c136c 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -209,7 +209,8 @@ public class Launcher extends Activity private static int sScreen = DEFAULT_SCREEN; // How long to wait before the new-shortcut animation automatically pans the workspace - private static int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 10; + private static int NEW_APPS_PAGE_MOVE_DELAY = 500; + private static int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 5; private static int NEW_APPS_ANIMATION_DELAY = 500; private final BroadcastReceiver mCloseSystemDialogsReceiver @@ -273,7 +274,7 @@ public class Launcher extends Activity private boolean mUserPresent = true; private boolean mVisible = false; private boolean mAttached = false; - private static final boolean DISABLE_CLINGS = true; + private static final boolean DISABLE_CLINGS = false; private static final boolean DISABLE_CUSTOM_CLINGS = true; private static LocaleConfiguration sLocaleConfiguration = null; @@ -633,6 +634,10 @@ public class Launcher extends Activity } } + public Stats getStats() { + return mStats; + } + public LayoutInflater getInflater() { return mInflater; } @@ -829,9 +834,6 @@ public class Launcher extends Activity // Background was set to gradient in onPause(), restore to black if in all apps. setWorkspaceBackground(mState == State.WORKSPACE); - // Process any items that were added while Launcher was away - InstallShortcutReceiver.disableAndFlushInstallQueue(this); - mPaused = false; sPausedFromUserAction = false; if (mRestoring || mOnResumeNeedsLoad) { @@ -880,12 +882,19 @@ public class Launcher extends Activity // Resets the previous all apps icon press state mAppsCustomizeContent.resetDrawableState(); } + // Reset AllApps to its initial state + if (mAppsCustomizeTabHost != null) { + mAppsCustomizeTabHost.reset(); + } // It is possible that widgets can receive updates while launcher is not in the foreground. // Consequently, the widgets will be inflated in the orientation of the foreground activity // (framework issue). On resuming, we ensure that any widgets are inflated for the current // orientation. getWorkspace().reinflateWidgetsIfNecessary(); + // Process any items that were added while Launcher was away. + InstallShortcutReceiver.disableAndFlushInstallQueue(this); + // Again, as with the above scenario, it's possible that one or more of the global icons // were updated in the wrong orientation. updateGlobalIcons(); @@ -906,7 +915,7 @@ public class Launcher extends Activity } protected void onFinishBindingItems() { - if (hasCustomContentToLeft() && mWorkspace.hasCustomContent()) { + if (mWorkspace != null && hasCustomContentToLeft() && mWorkspace.hasCustomContent()) { addCustomContentToLeft(); } } @@ -1913,6 +1922,8 @@ public class Launcher extends Activity } protected void moveToCustomContentScreen(boolean animate) { + // Close any folders that may be open. + closeFolder(); mWorkspace.moveToCustomContentScreen(animate); } /** @@ -2552,11 +2563,14 @@ public class Launcher extends Activity if (v instanceof Workspace) { if (!mWorkspace.isInOverviewMode()) { - mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, - HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); - mWorkspace.enterOverviewMode(); + if (mWorkspace.enterOverviewMode()) { + mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, + HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + return true; + } else { + return false; + } } - return true; } if (!(v instanceof CellLayout)) { @@ -3251,7 +3265,8 @@ public class Launcher extends Activity public View getQsbBar() { if (mQsbBar == null) { - mQsbBar = mInflater.inflate(R.layout.qsb_bar, mSearchDropTargetBar); + mQsbBar = mInflater.inflate(R.layout.search_bar, mSearchDropTargetBar, false); + mSearchDropTargetBar.addView(mQsbBar); } return mQsbBar; } @@ -3694,20 +3709,23 @@ public class Launcher extends Activity // Animate to the correct page if (newShortcutsScreenId > -1) { long currentScreenId = mWorkspace.getScreenIdForPageIndex(mWorkspace.getNextPage()); - int newScreenIndex = mWorkspace.getPageIndexForScreenId(newShortcutsScreenId); + final int newScreenIndex = mWorkspace.getPageIndexForScreenId(newShortcutsScreenId); if (newShortcutsScreenId != currentScreenId) { - mWorkspace.snapToPage(newScreenIndex); + // We post the animation slightly delayed to prevent slowdowns + // when we are loading right after we return to launcher. + mWorkspace.postDelayed(new Runnable() { + public void run() { + mWorkspace.snapToPage(newScreenIndex); + mWorkspace.postDelayed(new Runnable() { + public void run() { + anim.playTogether(bounceAnims); + anim.start(); + } + }, NEW_APPS_ANIMATION_DELAY); + } + }, NEW_APPS_PAGE_MOVE_DELAY); } } - - // We post the animation slightly delayed to prevent slowdowns when we are loading - // right after we return to launcher. - mWorkspace.postDelayed(new Runnable() { - public void run() { - anim.playTogether(bounceAnims); - anim.start(); - } - }, NEW_APPS_ANIMATION_DELAY); } workspace.requestLayout(); } @@ -4049,11 +4067,15 @@ public class Launcher extends Activity return true; } - private Cling initCling(int clingId, int[] positionData, boolean animate, + private Cling initCling(int clingId, int scrimId, boolean animate, boolean dimNavBarVisibilty) { - final Cling cling = (Cling) findViewById(clingId); + Cling cling = (Cling) findViewById(clingId); + View scrim = null; + if (scrimId > 0) { + scrim = findViewById(R.id.cling_scrim); + } if (cling != null) { - cling.init(this, positionData); + cling.init(this, scrim); cling.show(animate, SHOW_CLING_DURATION); if (dimNavBarVisibilty) { @@ -4072,7 +4094,6 @@ public class Launcher extends Activity final Runnable cleanUpClingCb = new Runnable() { public void run() { cling.cleanup(); - /* // We should update the shared preferences on a background thread new Thread("dismissClingThread") { public void run() { @@ -4081,7 +4102,6 @@ public class Launcher extends Activity editor.commit(); } }.start(); - */ if (postAnimationCb != null) { postAnimationCb.run(); } @@ -4162,7 +4182,7 @@ public class Launcher extends Activity ccHint.setVisibility(View.VISIBLE); } } - initCling(R.id.first_run_cling, null, false, true); + initCling(R.id.first_run_cling, 0, false, true); } else { removeCling(R.id.first_run_cling); } @@ -4179,7 +4199,7 @@ public class Launcher extends Activity // Enable the clings only if they have not been dismissed before if (isClingsEnabled() && !mSharedPrefs.getBoolean(Cling.WORKSPACE_CLING_DISMISSED_KEY, false)) { - initCling(R.id.workspace_cling, null, false, true); + initCling(R.id.workspace_cling, 0, false, true); } else { removeCling(R.id.workspace_cling); } @@ -4188,7 +4208,8 @@ public class Launcher extends Activity // Enable the clings only if they have not been dismissed before if (isClingsEnabled() && !mSharedPrefs.getBoolean(Cling.FOLDER_CLING_DISMISSED_KEY, false)) { - Cling cling = initCling(R.id.folder_cling, null, true, true); + Cling cling = initCling(R.id.folder_cling, R.id.cling_scrim, + true, true); return cling; } else { removeCling(R.id.folder_cling); diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 1d264aa55..f8644b1ec 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -281,14 +281,14 @@ public class LauncherModel extends BroadcastReceiver { return null; } - public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> added, - final ArrayList<AppInfo> addedApps) { + public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps, + final ArrayList<AppInfo> allAppsApps) { Callbacks cb = mCallbacks != null ? mCallbacks.get() : null; - addAndBindAddedApps(context, added, cb, addedApps); + addAndBindAddedApps(context, workspaceApps, cb, allAppsApps); } - public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> added, - final Callbacks callbacks, final ArrayList<AppInfo> addedApps) { - if (added.isEmpty()) { + public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps, + final Callbacks callbacks, final ArrayList<AppInfo> allAppsApps) { + if (workspaceApps.isEmpty() && allAppsApps.isEmpty()) { return; } // Process the newly added applications and add them to the database first @@ -308,7 +308,7 @@ public class LauncherModel extends BroadcastReceiver { } synchronized(sBgLock) { - Iterator<ItemInfo> iter = added.iterator(); + Iterator<ItemInfo> iter = workspaceApps.iterator(); while (iter.hasNext()) { ItemInfo a = iter.next(); final String name = a.title.toString(); @@ -356,6 +356,7 @@ public class LauncherModel extends BroadcastReceiver { } else { throw new RuntimeException("Unexpected info type"); } + // Add the shortcut to the db addItemToDatabase(context, shortcutInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP, @@ -368,24 +369,26 @@ public class LauncherModel extends BroadcastReceiver { // Update the workspace screens updateWorkspaceScreenOrder(context, workspaceScreens); - if (!addedShortcutsFinal.isEmpty()) { + if (!addedShortcutsFinal.isEmpty() || !allAppsApps.isEmpty()) { runOnMainThread(new Runnable() { public void run() { Callbacks cb = mCallbacks != null ? mCallbacks.get() : null; if (callbacks == cb && cb != null) { - ItemInfo info = addedShortcutsFinal.get(addedShortcutsFinal.size() - 1); - long lastScreenId = info.screenId; final ArrayList<ItemInfo> addAnimated = new ArrayList<ItemInfo>(); final ArrayList<ItemInfo> addNotAnimated = new ArrayList<ItemInfo>(); - for (ItemInfo i : addedShortcutsFinal) { - if (i.screenId == lastScreenId) { - addAnimated.add(i); - } else { - addNotAnimated.add(i); + if (!addedShortcutsFinal.isEmpty()) { + ItemInfo info = addedShortcutsFinal.get(addedShortcutsFinal.size() - 1); + long lastScreenId = info.screenId; + for (ItemInfo i : addedShortcutsFinal) { + if (i.screenId == lastScreenId) { + addAnimated.add(i); + } else { + addNotAnimated.add(i); + } } } callbacks.bindAppsAdded(addedWorkspaceScreensFinal, - addNotAnimated, addAnimated, addedApps); + addNotAnimated, addAnimated, allAppsApps); } } }); @@ -2474,7 +2477,7 @@ public class LauncherModel extends BroadcastReceiver { for (int i=0; i<N; i++) { if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]); mBgAllAppsList.updatePackage(context, packages[i]); - WidgetPreviewLoader.removeFromDb( + WidgetPreviewLoader.removePackageFromDb( mApp.getWidgetPreviewCacheDb(), packages[i]); } break; @@ -2483,7 +2486,7 @@ public class LauncherModel extends BroadcastReceiver { for (int i=0; i<N; i++) { if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]); mBgAllAppsList.removePackage(packages[i]); - WidgetPreviewLoader.removeFromDb( + WidgetPreviewLoader.removePackageFromDb( mApp.getWidgetPreviewCacheDb(), packages[i]); } break; @@ -2514,9 +2517,13 @@ public class LauncherModel extends BroadcastReceiver { if (added != null) { // Ensure that we add all the workspace applications to the db - final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added); Callbacks cb = mCallbacks != null ? mCallbacks.get() : null; - addAndBindAddedApps(context, addedInfos, cb, added); + if (!AppsCustomizePagedView.DISABLE_ALL_APPS) { + addAndBindAddedApps(context, new ArrayList<ItemInfo>(), cb, added); + } else { + final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added); + addAndBindAddedApps(context, addedInfos, cb, added); + } } if (modified != null) { final ArrayList<AppInfo> modifiedFinal = modified; @@ -2558,6 +2565,12 @@ public class LauncherModel extends BroadcastReceiver { deleteItemFromDatabase(context, i); } } + + // Remove any queued items from the install queue + String spKey = LauncherAppState.getSharedPreferencesKey(); + SharedPreferences sp = + context.getSharedPreferences(spKey, Context.MODE_PRIVATE); + InstallShortcutReceiver.removeFromInstallQueue(sp, removedPackageNames); } else { for (AppInfo a : removedApps) { ArrayList<ItemInfo> infos = @@ -3055,7 +3068,8 @@ public class LauncherModel extends BroadcastReceiver { final Collator collator = Collator.getInstance(); return new Comparator<AppInfo>() { public final int compare(AppInfo a, AppInfo b) { - int result = collator.compare(a.title.toString(), b.title.toString()); + int result = collator.compare(a.title.toString().trim(), + b.title.toString().trim()); if (result == 0) { result = a.componentName.compareTo(b.componentName); } @@ -3075,7 +3089,7 @@ public class LauncherModel extends BroadcastReceiver { final Collator collator = Collator.getInstance(); return new Comparator<AppWidgetProviderInfo>() { public final int compare(AppWidgetProviderInfo a, AppWidgetProviderInfo b) { - return collator.compare(a.label.toString(), b.label.toString()); + return collator.compare(a.label.toString().trim(), b.label.toString().trim()); } }; } @@ -3107,14 +3121,14 @@ public class LauncherModel extends BroadcastReceiver { if (mLabelCache.containsKey(keyA)) { labelA = mLabelCache.get(keyA); } else { - labelA = a.loadLabel(mPackageManager).toString(); + labelA = a.loadLabel(mPackageManager).toString().trim(); mLabelCache.put(keyA, labelA); } if (mLabelCache.containsKey(keyB)) { labelB = mLabelCache.get(keyB); } else { - labelB = b.loadLabel(mPackageManager).toString(); + labelB = b.loadLabel(mPackageManager).toString().trim(); mLabelCache.put(keyB, labelB); } @@ -3137,7 +3151,7 @@ public class LauncherModel extends BroadcastReceiver { } else { labelA = (a instanceof AppWidgetProviderInfo) ? ((AppWidgetProviderInfo) a).label : - ((ResolveInfo) a).loadLabel(mPackageManager).toString(); + ((ResolveInfo) a).loadLabel(mPackageManager).toString().trim(); mLabelCache.put(a, labelA); } if (mLabelCache.containsKey(b)) { @@ -3145,7 +3159,7 @@ public class LauncherModel extends BroadcastReceiver { } else { labelB = (b instanceof AppWidgetProviderInfo) ? ((AppWidgetProviderInfo) b).label : - ((ResolveInfo) b).loadLabel(mPackageManager).toString(); + ((ResolveInfo) b).loadLabel(mPackageManager).toString().trim(); mLabelCache.put(b, labelB); } return mCollator.compare(labelA, labelB); diff --git a/src/com/android/launcher3/LiveWallpaperListAdapter.java b/src/com/android/launcher3/LiveWallpaperListAdapter.java index 9d0f48bf0..e9e5e79a8 100644 --- a/src/com/android/launcher3/LiveWallpaperListAdapter.java +++ b/src/com/android/launcher3/LiveWallpaperListAdapter.java @@ -116,6 +116,7 @@ public class LiveWallpaperListAdapter extends BaseAdapter implements ListAdapter mThumbnail = thumbnail; mInfo = info; } + @Override public void onClick(WallpaperPickerActivity a) { Intent preview = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER); preview.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, diff --git a/src/com/android/launcher3/PackageChangedReceiver.java b/src/com/android/launcher3/PackageChangedReceiver.java index 75a1e095c..e59f6d81d 100644 --- a/src/com/android/launcher3/PackageChangedReceiver.java +++ b/src/com/android/launcher3/PackageChangedReceiver.java @@ -16,6 +16,6 @@ public class PackageChangedReceiver extends BroadcastReceiver { // in rare cases the receiver races with the application to set up LauncherAppState LauncherAppState.setApplicationContext(context.getApplicationContext()); LauncherAppState app = LauncherAppState.getInstance(); - WidgetPreviewLoader.removeFromDb(app.getWidgetPreviewCacheDb(), packageName); + WidgetPreviewLoader.removePackageFromDb(app.getWidgetPreviewCacheDb(), packageName); } } diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 1ae2943f6..41687d383 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -1316,13 +1316,13 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc */ if (mActivePointerId != INVALID_POINTER) { determineScrollingStart(ev); - break; } // if mActivePointerId is INVALID_POINTER, then we must have missed an ACTION_DOWN // event. in that case, treat the first occurence of a move event as a ACTION_DOWN // i.e. fall through to the next case (don't break) // (We sometimes miss ACTION_DOWN events in Workspace because it ignores all events // while it's small- this was causing a crash before we checked for INVALID_POINTER) + break; } case MotionEvent.ACTION_DOWN: { @@ -2147,19 +2147,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } public void scrollLeft() { - if (mScroller.isFinished()) { - if (mCurrentPage > 0) snapToPage(mCurrentPage - 1); - } else { - if (mNextPage > 0) snapToPage(mNextPage - 1); - } + if (getNextPage() > 0) snapToPage(getNextPage() - 1); } public void scrollRight() { - if (mScroller.isFinished()) { - if (mCurrentPage < getChildCount() -1) snapToPage(mCurrentPage + 1); - } else { - if (mNextPage < getChildCount() -1) snapToPage(mNextPage + 1); - } + if (getNextPage() < getChildCount() -1) snapToPage(getNextPage() + 1); } public int getPageForView(View v) { @@ -2326,6 +2318,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc loadAssociatedPages(mCurrentPage, immediateAndOnly); requestLayout(); } + if (isPageMoving()) { + // If the page is moving, then snap it to the final position to ensure we don't get + // stuck between pages + snapToDestination(); + } } // Animate the drag view back to the original position @@ -2373,7 +2370,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } public boolean startReordering(View v) { - int dragViewIndex = indexOfChild(v);//getPageNearestToCenterOfScreen(); + int dragViewIndex = indexOfChild(v); + + if (mTouchState != TOUCH_STATE_REST) return false; + mTempVisiblePagesRange[0] = 0; mTempVisiblePagesRange[1] = getPageCount() - 1; getOverviewModePages(mTempVisiblePagesRange); diff --git a/src/com/android/launcher3/SavedWallpaperImages.java b/src/com/android/launcher3/SavedWallpaperImages.java index f00f62ff6..531672a04 100644 --- a/src/com/android/launcher3/SavedWallpaperImages.java +++ b/src/com/android/launcher3/SavedWallpaperImages.java @@ -36,7 +36,6 @@ import android.widget.ListAdapter; import com.android.photos.BitmapRegionTileSource; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -57,6 +56,7 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter { mDbId = dbId; mThumb = thumb; } + @Override public void onClick(WallpaperPickerActivity a) { String imageFilename = a.getSavedImages().getImageFilename(mDbId); File file = new File(a.getFilesDir(), imageFilename); @@ -65,14 +65,17 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter { v.moveToLeft(); v.setTouchEnabled(false); } + @Override public void onSave(WallpaperPickerActivity a) { boolean finishActivityWhenDone = true; String imageFilename = a.getSavedImages().getImageFilename(mDbId); a.setWallpaper(imageFilename, finishActivityWhenDone); } + @Override public void onDelete(WallpaperPickerActivity a) { a.getSavedImages().deleteImage(mDbId); } + @Override public boolean isSelectable() { return true; } @@ -100,6 +103,7 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter { while (result.moveToNext()) { String filename = result.getString(1); File file = new File(mContext.getFilesDir(), filename); + Bitmap thumb = BitmapFactory.decodeFile(file.getAbsolutePath()); if (thumb != null) { mImages.add(new SavedWallpaperTile(result.getInt(0), new BitmapDrawable(thumb))); @@ -181,12 +185,11 @@ public class SavedWallpaperImages extends BaseAdapter implements ListAdapter { imageFileStream.write(imageBytes); imageFileStream.close(); - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - thumbnail.compress(Bitmap.CompressFormat.JPEG, 95, stream); File thumbFile = File.createTempFile("wallpaperthumb", "", mContext.getFilesDir()); FileOutputStream thumbFileStream = mContext.openFileOutput(thumbFile.getName(), Context.MODE_PRIVATE); - thumbFileStream.write(stream.toByteArray()); + thumbnail.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream); + thumbFileStream.close(); SQLiteDatabase db = mDb.getWritableDatabase(); ContentValues values = new ContentValues(); diff --git a/src/com/android/launcher3/ScrimView.java b/src/com/android/launcher3/ScrimView.java new file mode 100644 index 000000000..6831fe3d4 --- /dev/null +++ b/src/com/android/launcher3/ScrimView.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; + +public class ScrimView extends FrameLayout implements Insettable { + + public ScrimView(Context context) { + this(context, null, 0); + } + + public ScrimView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ScrimView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void setInsets(Rect insets) { + // Do nothing + } +} diff --git a/src/com/android/launcher3/Stats.java b/src/com/android/launcher3/Stats.java index ca088f71a..882fb04a3 100644 --- a/src/com/android/launcher3/Stats.java +++ b/src/com/android/launcher3/Stats.java @@ -103,20 +103,24 @@ public class Stats { } } + public void recordLaunch(Intent intent) { + recordLaunch(intent, null); + } + public void recordLaunch(Intent intent, ShortcutInfo shortcut) { intent = new Intent(intent); intent.setSourceBounds(null); final String flat = intent.toUri(0); - mLauncher.sendBroadcast( - new Intent(ACTION_LAUNCH) - .putExtra(EXTRA_INTENT, flat) - .putExtra(EXTRA_CONTAINER, shortcut.container) - .putExtra(EXTRA_SCREEN, shortcut.screenId) - .putExtra(EXTRA_CELLX, shortcut.cellX) - .putExtra(EXTRA_CELLY, shortcut.cellY), - PERM_LAUNCH); + Intent broadcastIntent = new Intent(ACTION_LAUNCH).putExtra(EXTRA_INTENT, flat); + if (shortcut != null) { + broadcastIntent.putExtra(EXTRA_CONTAINER, shortcut.container) + .putExtra(EXTRA_SCREEN, shortcut.screenId) + .putExtra(EXTRA_CELLX, shortcut.cellX) + .putExtra(EXTRA_CELLY, shortcut.cellY); + } + mLauncher.sendBroadcast(broadcastIntent, PERM_LAUNCH); incrementLaunch(flat); @@ -128,10 +132,17 @@ public class Stats { try { mLog.writeInt(LOG_TAG_LAUNCH); mLog.writeLong(System.currentTimeMillis()); - mLog.writeShort((short) shortcut.container); - mLog.writeShort((short) shortcut.screenId); - mLog.writeShort((short) shortcut.cellX); - mLog.writeShort((short) shortcut.cellY); + if (shortcut == null) { + mLog.writeShort(0); + mLog.writeShort(0); + mLog.writeShort(0); + mLog.writeShort(0); + } else { + mLog.writeShort((short) shortcut.container); + mLog.writeShort((short) shortcut.screenId); + mLog.writeShort((short) shortcut.cellX); + mLog.writeShort((short) shortcut.cellY); + } mLog.writeUTF(flat); if (FLUSH_IMMEDIATELY) { mLog.flush(); // TODO: delayed writes diff --git a/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java b/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java index ab2f5d72a..7ed1c1bfb 100644 --- a/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java +++ b/src/com/android/launcher3/ThirdPartyWallpaperPickerListAdapter.java @@ -46,6 +46,7 @@ public class ThirdPartyWallpaperPickerListAdapter extends BaseAdapter implements public ThirdPartyWallpaperTile(ResolveInfo resolveInfo) { mResolveInfo = resolveInfo; } + @Override public void onClick(WallpaperPickerActivity a) { final ComponentName itemComponentName = new ComponentName( mResolveInfo.activityInfo.packageName, mResolveInfo.activityInfo.name); diff --git a/src/com/android/launcher3/UninstallShortcutReceiver.java b/src/com/android/launcher3/UninstallShortcutReceiver.java index d92963abe..ccea4ec0c 100644 --- a/src/com/android/launcher3/UninstallShortcutReceiver.java +++ b/src/com/android/launcher3/UninstallShortcutReceiver.java @@ -30,7 +30,7 @@ import java.util.Iterator; public class UninstallShortcutReceiver extends BroadcastReceiver { private static final String ACTION_UNINSTALL_SHORTCUT = - "com.android.launcher3.action.UNINSTALL_SHORTCUT"; + "com.android.launcher.action.UNINSTALL_SHORTCUT"; // The set of shortcuts that are pending uninstall private static ArrayList<PendingUninstallShortcutInfo> mUninstallQueue = @@ -78,6 +78,7 @@ public class UninstallShortcutReceiver extends BroadcastReceiver { PendingUninstallShortcutInfo pendingInfo) { final Intent data = pendingInfo.data; + LauncherAppState.setApplicationContext(context.getApplicationContext()); LauncherAppState app = LauncherAppState.getInstance(); synchronized (app) { // TODO: make removeShortcut internally threadsafe removeShortcut(context, data); diff --git a/src/com/android/launcher3/WallpaperPickerActivity.java b/src/com/android/launcher3/WallpaperPickerActivity.java index 5f35cde21..ef94fe86e 100644 --- a/src/com/android/launcher3/WallpaperPickerActivity.java +++ b/src/com/android/launcher3/WallpaperPickerActivity.java @@ -29,11 +29,12 @@ import android.content.res.Resources; import android.database.Cursor; import android.database.DataSetObserver; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.RectF; -import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LevelListDrawable; import android.net.Uri; @@ -58,6 +59,8 @@ import android.widget.ListAdapter; import com.android.photos.BitmapRegionTileSource; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; @@ -87,11 +90,12 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { public static abstract class WallpaperTileInfo { public void onClick(WallpaperPickerActivity a) {} public void onSave(WallpaperPickerActivity a) {} - public void onDelete() {} + public void onDelete(WallpaperPickerActivity a) {} public boolean isSelectable() { return false; } } public static class PickImageInfo extends WallpaperTileInfo { + @Override public void onClick(WallpaperPickerActivity a) { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); @@ -104,13 +108,14 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { public UriWallpaperInfo(Uri uri) { mUri = uri; } + @Override public void onClick(WallpaperPickerActivity a) { CropView v = a.getCropView(); v.setTileSource(new BitmapRegionTileSource( a, mUri, 1024, 0), null); v.setTouchEnabled(true); } - + @Override public void onSave(final WallpaperPickerActivity a) { boolean finishActivityWhenDone = true; OnBitmapCroppedHandler h = new OnBitmapCroppedHandler() { @@ -123,6 +128,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { }; a.cropImageAndSetWallpaper(mUri, h, finishActivityWhenDone); } + @Override public boolean isSelectable() { return true; } @@ -138,6 +144,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { mResId = resId; mThumb = thumb; } + @Override public void onClick(WallpaperPickerActivity a) { BitmapRegionTileSource source = new BitmapRegionTileSource( mResources, a, mResId, 1024, 0); @@ -151,10 +158,12 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { v.setScale(wallpaperSize.x / crop.width()); v.setTouchEnabled(false); } + @Override public void onSave(WallpaperPickerActivity a) { boolean finishActivityWhenDone = true; a.cropImageAndSetWallpaper(mResources, mResId, finishActivityWhenDone); } + @Override public boolean isSelectable() { return true; } @@ -211,11 +220,11 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { return; } WallpaperTileInfo info = (WallpaperTileInfo) v.getTag(); - if (mSelectedThumb != null) { - mSelectedThumb.setSelected(false); - mSelectedThumb = null; - } if (info.isSelectable()) { + if (mSelectedThumb != null) { + mSelectedThumb.setSelected(false); + mSelectedThumb = null; + } mSelectedThumb = v; v.setSelected(true); } @@ -307,8 +316,10 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { new View.OnClickListener() { @Override public void onClick(View v) { - WallpaperTileInfo info = (WallpaperTileInfo) mSelectedThumb.getTag(); - info.onSave(WallpaperPickerActivity.this); + if (mSelectedThumb != null) { + WallpaperTileInfo info = (WallpaperTileInfo) mSelectedThumb.getTag(); + info.onSave(WallpaperPickerActivity.this); + } } }); @@ -361,7 +372,8 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { CheckableFrameLayout c = (CheckableFrameLayout) mWallpapersView.getChildAt(i); if (c.isChecked()) { - ((WallpaperTileInfo) c.getTag()).onDelete(); + WallpaperTileInfo info = (WallpaperTileInfo) c.getTag(); + info.onDelete(WallpaperPickerActivity.this); viewsToRemove.add(c); } } @@ -462,7 +474,7 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { new BitmapCropTask(context, res, resId, null, width, height, false, true, null); } Point bounds = cropTask.getImageBounds(); - if (bounds == null) { + if (bounds == null || bounds.x == 0 || bounds.y == 0) { return null; } @@ -546,14 +558,48 @@ public class WallpaperPickerActivity extends WallpaperCropActivity { } catch (PackageManager.NameNotFoundException e) { } } - //TODO: add default wallpaper - //Resources sysRes = Resources.getSystem(); - //int resId = sysRes.getIdentifier("default_wallpaper", "drawable", "android"); - //bundledWallpapers.add( - // new ResourceWallpaperInfo(sysRes, resId, new ColorDrawable(0xFFFF0000))); + + // Add an entry for the default wallpaper (stored in system resources) + ResourceWallpaperInfo defaultWallpaperInfo = getDefaultWallpaperInfo(); + if (defaultWallpaperInfo != null) { + bundledWallpapers.add(0, defaultWallpaperInfo); + } return bundledWallpapers; } + private ResourceWallpaperInfo getDefaultWallpaperInfo() { + Resources sysRes = Resources.getSystem(); + int resId = sysRes.getIdentifier("default_wallpaper", "drawable", "android"); + + File defaultThumbFile = new File(getFilesDir(), "default_thumb.jpg"); + Bitmap thumb = null; + boolean defaultWallpaperExists = false; + if (defaultThumbFile.exists()) { + thumb = BitmapFactory.decodeFile(defaultThumbFile.getAbsolutePath()); + defaultWallpaperExists = true; + } else { + Point defaultThumbSize = getDefaultThumbnailSize(getResources()); + thumb = createThumbnail(defaultThumbSize, this, null, null, sysRes, resId, false); + if (thumb != null) { + try { + defaultThumbFile.createNewFile(); + FileOutputStream thumbFileStream = + openFileOutput(defaultThumbFile.getName(), Context.MODE_PRIVATE); + thumb.compress(Bitmap.CompressFormat.JPEG, 95, thumbFileStream); + thumbFileStream.close(); + defaultWallpaperExists = true; + } catch (IOException e) { + Log.e(TAG, "Error while writing default wallpaper thumbnail to file " + e); + defaultThumbFile.delete(); + } + } + } + if (defaultWallpaperExists) { + return new ResourceWallpaperInfo(sysRes, resId, new BitmapDrawable(thumb)); + } + return null; + } + public Pair<ApplicationInfo, Integer> getWallpaperArrayResourceId() { // Context.getPackageName() may return the "original" package name, // com.android.launcher3; Resources needs the real package name, diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java index 11c12f875..1910ab74a 100644 --- a/src/com/android/launcher3/WidgetPreviewLoader.java +++ b/src/com/android/launcher3/WidgetPreviewLoader.java @@ -159,11 +159,12 @@ public class WidgetPreviewLoader { } public Bitmap getPreview(final Object o) { - String name = getObjectName(o); + final String name = getObjectName(o); + final String packageName = getObjectPackage(o); // check if the package is valid boolean packageValid = true; synchronized(sInvalidPackages) { - packageValid = !sInvalidPackages.contains(getObjectPackage(o)); + packageValid = !sInvalidPackages.contains(packageName); } if (!packageValid) { return null; @@ -334,7 +335,7 @@ public class WidgetPreviewLoader { db.insert(CacheDb.TABLE_NAME, null, values); } - public static void removeFromDb(final CacheDb cacheDb, final String packageName) { + public static void removePackageFromDb(final CacheDb cacheDb, final String packageName) { synchronized(sInvalidPackages) { sInvalidPackages.add(packageName); } @@ -356,6 +357,18 @@ public class WidgetPreviewLoader { }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } + public static void removeItemFromDb(final CacheDb cacheDb, final String objectName) { + new AsyncTask<Void, Void, Void>() { + public Void doInBackground(Void ... args) { + SQLiteDatabase db = cacheDb.getWritableDatabase(); + db.delete(CacheDb.TABLE_NAME, + CacheDb.COLUMN_NAME + " = ? ", // SELECT query + new String[] { objectName }); // args to SELECT query + return null; + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); + } + private Bitmap readFromDb(String name, Bitmap b) { if (mCachedSelectQuery == null) { mCachedSelectQuery = CacheDb.COLUMN_NAME + " = ? AND " + @@ -377,8 +390,12 @@ public class WidgetPreviewLoader { final BitmapFactory.Options opts = mCachedBitmapFactoryOptions.get(); opts.inBitmap = b; opts.inSampleSize = 1; - Bitmap out = BitmapFactory.decodeByteArray(blob, 0, blob.length, opts); - return out; + try { + return BitmapFactory.decodeByteArray(blob, 0, blob.length, opts); + } catch (IllegalArgumentException e) { + removeItemFromDb(mDb, name); + return null; + } } else { result.close(); return null; diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 87840a7bd..132f42d5f 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -194,6 +194,7 @@ public class Workspace extends SmoothPagedView private final int[] mTempXY = new int[2]; private int[] mTempVisiblePagesRange = new int[2]; private boolean mOverscrollTransformsSet; + private float mLastOverscrollPivotX; public static final int DRAG_BITMAP_PADDING = 2; private boolean mWorkspaceFadeInAdjacentScreens; @@ -1035,12 +1036,14 @@ public class Workspace extends SmoothPagedView if (mCustomContentCallbacks != null) { mCustomContentCallbacks.onShow(); mCustomContentShowTime = System.currentTimeMillis(); + mLauncher.setVoiceButtonProxyVisible(false); } } else if (hasCustomContent() && getNextPage() != 0 && mCustomContentShowing) { mCustomContentShowing = false; if (mCustomContentCallbacks != null) { mCustomContentCallbacks.onHide(); mLauncher.resetQSBScroll(); + mLauncher.setVoiceButtonProxyVisible(true); } } }; @@ -1413,22 +1416,20 @@ public class Workspace extends SmoothPagedView final float rightBiasedPivot = 0.75f; final int lowerIndex = 0; final int upperIndex = getChildCount() - 1; - if (isRtl) { - index = mOverScrollX < 0 ? upperIndex : lowerIndex; - pivotX = (index == 0 ? leftBiasedPivot : rightBiasedPivot); - } else { - index = mOverScrollX < 0 ? lowerIndex : upperIndex; - pivotX = (index == 0 ? rightBiasedPivot : leftBiasedPivot); - } + + final boolean isLeftPage = mOverScrollX < 0; + index = (!isRtl && isLeftPage) || (isRtl && !isLeftPage) ? lowerIndex : upperIndex; + pivotX = isLeftPage ? rightBiasedPivot : leftBiasedPivot; CellLayout cl = (CellLayout) getChildAt(index); float scrollProgress = getScrollProgress(screenCenter, cl, index); - final boolean isLeftPage = (isRtl ? index > 0 : index == 0); cl.setOverScrollAmount(Math.abs(scrollProgress), isLeftPage); float rotation = -WORKSPACE_OVERSCROLL_ROTATION * scrollProgress; cl.setRotationY(rotation); - if (!mOverscrollTransformsSet) { + + if (!mOverscrollTransformsSet || Float.compare(mLastOverscrollPivotX, pivotX) != 0) { mOverscrollTransformsSet = true; + mLastOverscrollPivotX = pivotX; cl.setCameraDistance(mDensity * mCameraDistance); cl.setPivotX(cl.getMeasuredWidth() * pivotX); cl.setPivotY(cl.getMeasuredHeight() * 0.5f); @@ -1747,25 +1748,17 @@ public class Workspace extends SmoothPagedView protected void onStartReordering() { super.onStartReordering(); - int count = getChildCount(); - for (int i = 0; i < count; i++) { - ((CellLayout) getChildAt(i)).setUseActiveGlowBackground(true); - } showOutlines(); - // Reordering handles its own animations, disable the automatic ones. setLayoutTransition(null); } protected void onEndReordering() { super.onEndReordering(); - int count = getChildCount(); - for (int i = 0; i < count; i++) { - ((CellLayout) getChildAt(i)).setUseActiveGlowBackground(false); - } - hideOutlines(); + hideOutlines(); mScreenOrder.clear(); + int count = getChildCount(); for (int i = 0; i < count; i++) { CellLayout cl = ((CellLayout) getChildAt(i)); mScreenOrder.add(getIdForScreen(cl)); @@ -1781,9 +1774,13 @@ public class Workspace extends SmoothPagedView return mState == State.OVERVIEW; } - public void enterOverviewMode() { + public boolean enterOverviewMode() { + if (mTouchState != TOUCH_STATE_REST) { + return false; + } mLauncher.onInteractionBegin(); enableOverviewMode(true, -1, true); + return true; } public void exitOverviewMode(boolean animated) { @@ -2644,8 +2641,8 @@ public class Workspace extends SmoothPagedView } } - LauncherModel.moveItemInDatabase(mLauncher, info, container, screenId, lp.cellX, - lp.cellY); + LauncherModel.modifyItemInDatabase(mLauncher, info, container, screenId, lp.cellX, + lp.cellY, item.spanX, item.spanY); } else { // If we can't find a drop location, we return the item to its original position CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams(); @@ -2744,6 +2741,8 @@ public class Workspace extends SmoothPagedView } } + /** Return a rect that has the cellWidth/cellHeight (left, top), and + * widthGap/heightGap (right, bottom) */ static Rect getCellLayoutMetrics(Launcher launcher, int orientation) { LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); @@ -2755,24 +2754,28 @@ public class Workspace extends SmoothPagedView display.getCurrentSizeRange(smallestSize, largestSize); int countX = (int) grid.numColumns; int countY = (int) grid.numRows; + int constrainedLongEdge = largestSize.y; + int constrainedShortEdge = smallestSize.y; if (orientation == CellLayout.LANDSCAPE) { if (mLandscapeCellLayoutMetrics == null) { Rect padding = grid.getWorkspacePadding(CellLayout.LANDSCAPE); - int width = largestSize.x - padding.left - padding.right; - int height = smallestSize.y - padding.top - padding.bottom; + int width = constrainedLongEdge - padding.left - padding.right; + int height = constrainedShortEdge - padding.top - padding.bottom; mLandscapeCellLayoutMetrics = new Rect(); - CellLayout.getMetrics(mLandscapeCellLayoutMetrics, width, height, - countX, countY); + mLandscapeCellLayoutMetrics.set( + grid.calculateCellWidth(width, countX), + grid.calculateCellHeight(height, countY), 0, 0); } return mLandscapeCellLayoutMetrics; } else if (orientation == CellLayout.PORTRAIT) { if (mPortraitCellLayoutMetrics == null) { Rect padding = grid.getWorkspacePadding(CellLayout.PORTRAIT); - int width = smallestSize.x - padding.left - padding.right; - int height = largestSize.y - padding.top - padding.bottom; + int width = constrainedShortEdge - padding.left - padding.right; + int height = constrainedLongEdge - padding.top - padding.bottom; mPortraitCellLayoutMetrics = new Rect(); - CellLayout.getMetrics(mPortraitCellLayoutMetrics, width, height, - countX, countY); + mPortraitCellLayoutMetrics.set( + grid.calculateCellWidth(width, countX), + grid.calculateCellHeight(height, countY), 0, 0); } return mPortraitCellLayoutMetrics; } @@ -3114,9 +3117,18 @@ public class Workspace extends SmoothPagedView ItemInfo info = (ItemInfo) d.dragInfo; + int minSpanX = item.spanX; + int minSpanY = item.spanY; + if (item.minSpanX > 0 && item.minSpanY > 0) { + minSpanX = item.minSpanX; + minSpanY = item.minSpanY; + } + mTargetCell = findNearestArea((int) mDragViewVisualCenter[0], - (int) mDragViewVisualCenter[1], item.spanX, item.spanY, + (int) mDragViewVisualCenter[1], minSpanX, minSpanY, mDragTargetLayout, mTargetCell); + int reorderX = mTargetCell[0]; + int reorderY = mTargetCell[1]; setCurrentDropOverCell(mTargetCell[0], mTargetCell[1]); @@ -3129,13 +3141,6 @@ public class Workspace extends SmoothPagedView manageFolderFeedback(info, mDragTargetLayout, mTargetCell, targetCellDistance, dragOverView); - int minSpanX = item.spanX; - int minSpanY = item.spanY; - if (item.minSpanX > 0 && item.minSpanY > 0) { - minSpanX = item.minSpanX; - minSpanY = item.minSpanY; - } - boolean nearestDropOccupied = mDragTargetLayout.isNearestDropLocationOccupied((int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX, item.spanY, child, mTargetCell); @@ -3146,8 +3151,8 @@ public class Workspace extends SmoothPagedView mTargetCell[0], mTargetCell[1], item.spanX, item.spanY, false, d.dragView.getDragVisualizeOffset(), d.dragView.getDragRegion()); } else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER) - && !mReorderAlarm.alarmPending() && (mLastReorderX != mTargetCell[0] || - mLastReorderY != mTargetCell[1])) { + && !mReorderAlarm.alarmPending() && (mLastReorderX != reorderX || + mLastReorderY != reorderY)) { // Otherwise, if we aren't adding to or creating a folder and there's no pending // reorder, then we schedule a reorder @@ -3246,7 +3251,8 @@ public class Workspace extends SmoothPagedView public void onAlarm(Alarm alarm) { int[] resultSpan = new int[2]; mTargetCell = findNearestArea((int) mDragViewVisualCenter[0], - (int) mDragViewVisualCenter[1], spanX, spanY, mDragTargetLayout, mTargetCell); + (int) mDragViewVisualCenter[1], minSpanX, minSpanY, mDragTargetLayout, + mTargetCell); mLastReorderX = mTargetCell[0]; mLastReorderY = mTargetCell[1]; |