From 71b5c0b988a64b3a0613ded5403749bc537ee8a5 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 8 Jan 2015 16:59:04 -0800 Subject: Adding accessibility controls > Adding 'Remove' option to workspace items > Adding 'Add to workspace' to all apps and widget list items, which adds the item to the first available space, giving preference to the current workspace screen > Adding 'App info' and 'Uninstall' options to appropriate items Bug: 18482913 Change-Id: Ifab7423af2d9ba502b5a2771b37bb5436b3df937 --- src/com/android/launcher3/BubbleTextView.java | 36 +- src/com/android/launcher3/CellLayout.java | 8 +- src/com/android/launcher3/DeleteDropTarget.java | 83 +++-- src/com/android/launcher3/FolderIcon.java | 1 + src/com/android/launcher3/InfoDropTarget.java | 30 +- src/com/android/launcher3/Launcher.java | 71 ++-- .../launcher3/LauncherAccessibilityDelegate.java | 109 ++++++ src/com/android/launcher3/LauncherAppState.java | 10 + .../launcher3/LauncherAppWidgetHostView.java | 1 + src/com/android/launcher3/LauncherModel.java | 406 +++++++++++---------- src/com/android/launcher3/PagedViewWidget.java | 2 +- src/com/android/launcher3/PreloadIconDrawable.java | 5 +- src/com/android/launcher3/Workspace.java | 61 +--- 13 files changed, 483 insertions(+), 340 deletions(-) create mode 100644 src/com/android/launcher3/LauncherAccessibilityDelegate.java (limited to 'src') diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 07f3045a5..f9255e6bd 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -49,7 +49,15 @@ public class BubbleTextView extends TextView { private static final int SHADOW_SMALL_COLOUR = 0xCC000000; static final float PADDING_V = 3.0f; - private HolographicOutlineHelper mOutlineHelper; + + private final Drawable mBackground; + private final CheckLongPressHelper mLongPressHelper; + private final HolographicOutlineHelper mOutlineHelper; + + // TODO: Remove custom background handling code, as no instance of BubbleTextView use any + // background. + private boolean mBackgroundSizeChanged; + private Bitmap mPressedBackground; private float mSlop; @@ -58,14 +66,8 @@ public class BubbleTextView extends TextView { private final boolean mCustomShadowsEnabled; private boolean mIsTextVisible; - // TODO: Remove custom background handling code, as no instance of BubbleTextView use any - // background. - private boolean mBackgroundSizeChanged; - private final Drawable mBackground; - private boolean mStayPressed; private boolean mIgnorePressedStateChange; - private CheckLongPressHelper mLongPressHelper; public BubbleTextView(Context context) { this(context, null, 0); @@ -90,7 +92,14 @@ public class BubbleTextView extends TextView { } else { mBackground = null; } - init(); + mLongPressHelper = new CheckLongPressHelper(this); + + mOutlineHelper = HolographicOutlineHelper.obtain(getContext()); + if (mCustomShadowsEnabled) { + setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR); + } + + setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate()); } public void onFinishInflate() { @@ -102,15 +111,6 @@ public class BubbleTextView extends TextView { setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx); } - private void init() { - mLongPressHelper = new CheckLongPressHelper(this); - - mOutlineHelper = HolographicOutlineHelper.obtain(getContext()); - if (mCustomShadowsEnabled) { - setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR); - } - } - public void applyFromShortcutInfo(ShortcutInfo info, IconCache iconCache, boolean setDefaultPadding) { applyFromShortcutInfo(info, iconCache, setDefaultPadding, false); @@ -328,7 +328,7 @@ public class BubbleTextView extends TextView { Drawable top = getCompoundDrawables()[1]; if (top instanceof PreloadIconDrawable) { - ((PreloadIconDrawable) top).applyTheme(getPreloaderTheme()); + ((PreloadIconDrawable) top).applyPreloaderTheme(getPreloaderTheme()); } mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); } diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 7424d61c1..e6865b2e6 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -2981,11 +2981,11 @@ public class CellLayout extends ViewGroup { static boolean findVacantCell(int[] vacant, int spanX, int spanY, int xCount, int yCount, boolean[][] occupied) { - for (int y = 0; y < yCount; y++) { - for (int x = 0; x < xCount; x++) { + for (int y = 0; (y + spanY) <= yCount; y++) { + for (int x = 0; (x + spanX) <= xCount; x++) { boolean available = !occupied[x][y]; -out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) { - for (int j = y; j < y + spanY - 1 && y < yCount; j++) { +out: for (int i = x; i < x + spanX; i++) { + for (int j = y; j < y + spanY; j++) { available = available && !occupied[i][j]; if (!available) break out; } diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java index 5a5c0027e..ebe874f38 100644 --- a/src/com/android/launcher3/DeleteDropTarget.java +++ b/src/com/android/launcher3/DeleteDropTarget.java @@ -19,6 +19,7 @@ package com.android.launcher3; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.annotation.TargetApi; import android.content.ComponentName; import android.content.Context; import android.content.res.ColorStateList; @@ -115,15 +116,6 @@ public class DeleteDropTarget extends ButtonDropTarget { private boolean isDragSourceWorkspaceOrFolder(DragObject d) { return (d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder); } - private boolean isWorkspaceOrFolderApplication(DragObject d) { - return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof ShortcutInfo); - } - private boolean isWorkspaceOrFolderWidget(DragObject d) { - return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof LauncherAppWidgetInfo); - } - private boolean isWorkspaceFolder(DragObject d) { - return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof FolderInfo); - } private void setHoverColor() { if (mCurrentDrawable != null) { @@ -177,6 +169,7 @@ public class DeleteDropTarget extends ButtonDropTarget { return false; } + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) @Override public void onDragStart(DragSource source, Object info, int dragAction) { boolean isVisible = true; @@ -284,7 +277,8 @@ public class DeleteDropTarget extends ButtonDropTarget { } private boolean isUninstallFromWorkspace(DragObject d) { - if (LauncherAppState.isDisableAllApps() && isWorkspaceOrFolderApplication(d)) { + if (LauncherAppState.isDisableAllApps() && isDragSourceWorkspaceOrFolder(d) + && (d.dragInfo instanceof ShortcutInfo)) { ShortcutInfo shortcut = (ShortcutInfo) d.dragInfo; // Only allow manifest shortcuts to initiate an un-install. return !InstallShortcutReceiver.isValidShortcutLaunchIntent(shortcut.intent); @@ -297,10 +291,7 @@ public class DeleteDropTarget extends ButtonDropTarget { boolean wasWaitingForUninstall = mWaitingForUninstall; mWaitingForUninstall = false; if (isAllAppsApplication(d.dragSource, item)) { - // Uninstall the application if it is being dragged from AppsCustomize - AppInfo appInfo = (AppInfo) item; - mLauncher.startApplicationUninstallActivity(appInfo.componentName, appInfo.flags, - appInfo.user); + uninstallApp(mLauncher, (AppInfo) item); } else if (isUninstallFromWorkspace(d)) { ShortcutInfo shortcut = (ShortcutInfo) item; if (shortcut.intent != null && shortcut.intent.getComponent() != null) { @@ -329,40 +320,62 @@ public class DeleteDropTarget extends ButtonDropTarget { mLauncher.addOnResumeCallback(checkIfUninstallWasSuccess); } } - } else if (isWorkspaceOrFolderApplication(d)) { - LauncherModel.deleteItemFromDatabase(mLauncher, item); - } else if (isWorkspaceFolder(d)) { - // Remove the folder from the workspace and delete the contents from launcher model - FolderInfo folderInfo = (FolderInfo) item; - mLauncher.removeFolder(folderInfo); - LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo); - } else if (isWorkspaceOrFolderWidget(d)) { + } else if (isDragSourceWorkspaceOrFolder(d)) { + removeWorkspaceOrFolderItem(mLauncher, item, null); + } + if (wasWaitingForUninstall && !mWaitingForUninstall) { + if (d.dragSource instanceof Folder) { + ((Folder) d.dragSource).onUninstallActivityReturned(false); + } else if (d.dragSource instanceof Workspace) { + ((Workspace) d.dragSource).onUninstallActivityReturned(false); + } + } + } + + public static void uninstallApp(Launcher launcher, AppInfo info) { + launcher.startApplicationUninstallActivity(info.componentName, info.flags, info.user); + } + + /** + * Removes the item from the workspace. If the view is not null, it also removes the view. + * @return true if the item was removed. + */ + public static boolean removeWorkspaceOrFolderItem(Launcher launcher, ItemInfo item, View view) { + if (item instanceof ShortcutInfo) { + LauncherModel.deleteItemFromDatabase(launcher, item); + } else if (item instanceof FolderInfo) { + FolderInfo folder = (FolderInfo) item; + launcher.removeFolder(folder); + LauncherModel.deleteFolderContentsFromDatabase(launcher, folder); + } else if (item instanceof LauncherAppWidgetInfo) { + final LauncherAppWidgetInfo widget = (LauncherAppWidgetInfo) item; + // Remove the widget from the workspace - mLauncher.removeAppWidget((LauncherAppWidgetInfo) item); - LauncherModel.deleteItemFromDatabase(mLauncher, item); + launcher.removeAppWidget(widget); + LauncherModel.deleteItemFromDatabase(launcher, widget); - final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item; - final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost(); + final LauncherAppWidgetHost appWidgetHost = launcher.getAppWidgetHost(); - if (appWidgetHost != null && !launcherAppWidgetInfo.isCustomWidget() - && launcherAppWidgetInfo.isWidgetIdValid()) { + if (appWidgetHost != null && !widget.isCustomWidget() + && widget.isWidgetIdValid()) { // Deleting an app widget ID is a void call but writes to disk before returning // to the caller... new AsyncTask() { public Void doInBackground(Void ... args) { - appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId); + appWidgetHost.deleteAppWidgetId(widget.appWidgetId); return null; } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } + } else { + return false; } - if (wasWaitingForUninstall && !mWaitingForUninstall) { - if (d.dragSource instanceof Folder) { - ((Folder) d.dragSource).onUninstallActivityReturned(false); - } else if (d.dragSource instanceof Workspace) { - ((Workspace) d.dragSource).onUninstallActivityReturned(false); - } + + if (view != null) { + launcher.getWorkspace().removeWorkspaceItem(view); + launcher.getWorkspace().stripEmptyScreens(); } + return true; } public void onDrop(DragObject d) { diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java index a359f1180..a3e82959a 100644 --- a/src/com/android/launcher3/FolderIcon.java +++ b/src/com/android/launcher3/FolderIcon.java @@ -127,6 +127,7 @@ public class FolderIcon extends FrameLayout implements FolderListener { private void init() { mLongPressHelper = new CheckLongPressHelper(this); + setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate()); } public boolean isDropEnabled() { diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java index 7e55af228..3c36361aa 100644 --- a/src/com/android/launcher3/InfoDropTarget.java +++ b/src/com/android/launcher3/InfoDropTarget.java @@ -76,28 +76,32 @@ public class InfoDropTarget extends ButtonDropTarget { // acceptDrop is called just before onDrop. We do the work here, rather than // in onDrop, because it allows us to reject the drop (by returning false) // so that the object being dragged isn't removed from the drag source. + + startDetailsActivityForInfo(d.dragInfo, mLauncher); + // There is no post-drop animation, so clean up the DragView now + d.deferDragViewCleanupPostAnimation = false; + return false; + } + + public static void startDetailsActivityForInfo(Object info, Launcher launcher) { ComponentName componentName = null; - if (d.dragInfo instanceof AppInfo) { - componentName = ((AppInfo) d.dragInfo).componentName; - } else if (d.dragInfo instanceof ShortcutInfo) { - componentName = ((ShortcutInfo) d.dragInfo).intent.getComponent(); - } else if (d.dragInfo instanceof PendingAddItemInfo) { - componentName = ((PendingAddItemInfo) d.dragInfo).componentName; + if (info instanceof AppInfo) { + componentName = ((AppInfo) info).componentName; + } else if (info instanceof ShortcutInfo) { + componentName = ((ShortcutInfo) info).intent.getComponent(); + } else if (info instanceof PendingAddItemInfo) { + componentName = ((PendingAddItemInfo) info).componentName; } final UserHandleCompat user; - if (d.dragInfo instanceof ItemInfo) { - user = ((ItemInfo) d.dragInfo).user; + if (info instanceof ItemInfo) { + user = ((ItemInfo) info).user; } else { user = UserHandleCompat.myUserHandle(); } if (componentName != null) { - mLauncher.startApplicationDetailsActivity(componentName, user); + launcher.startApplicationDetailsActivity(componentName, user); } - - // There is no post-drop animation, so clean up the DragView now - d.deferDragViewCleanupPostAnimation = false; - return false; } @Override diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 0ceb862a7..5d8e136cd 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -162,7 +162,6 @@ public class Launcher extends Activity static final String EXTRA_SHORTCUT_DUPLICATE = "duplicate"; static final int SCREEN_COUNT = 5; - static final int DEFAULT_SCREEN = 2; // To turn on these properties, type // adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS] @@ -232,7 +231,6 @@ public class Launcher extends Activity private static final int ACTIVITY_START_DELAY = 1000; private static final Object sLock = new Object(); - private static int sScreen = DEFAULT_SCREEN; private HashMap mItemIdToViewId = new HashMap(); private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); @@ -675,18 +673,7 @@ public class Launcher extends Activity return !mModel.isLoadingWorkspace(); } - static int getScreen() { - synchronized (sLock) { - return sScreen; - } - } - - static void setScreen(int screen) { - synchronized (sLock) { - sScreen = screen; - } - } - + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static int generateViewId() { if (Build.VERSION.SDK_INT >= 17) { return View.generateViewId(); @@ -1594,7 +1581,6 @@ public class Launcher extends Activity * Add a widget to the workspace. * * @param appWidgetId The app widget id - * @param cellInfo The position on screen where to create the widget. */ private void completeAddAppWidget(int appWidgetId, long container, long screenId, AppWidgetHostView hostView, LauncherAppWidgetProviderInfo appWidgetInfo) { @@ -2294,20 +2280,39 @@ public class Launcher extends Activity closeFolder(); mWorkspace.moveToCustomContentScreen(animate); } + + public void addPendingItem(PendingAddItemInfo info, long container, long screenId, + int[] cell, int spanX, int spanY) { + switch (info.itemType) { + case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET: + case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: + int span[] = new int[2]; + span[0] = spanX; + span[1] = spanY; + addAppWidgetFromDrop((PendingAddWidgetInfo) info, + container, screenId, cell, span); + break; + case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: + processShortcutFromDrop(info.componentName, container, screenId, cell); + break; + default: + throw new IllegalStateException("Unknown item type: " + info.itemType); + } + } + /** * Process a shortcut drop. * * @param componentName The name of the component * @param screenId The ID of the screen where it should be added * @param cell The cell it should be added to, optional - * @param position The location on the screen where it was dropped, optional */ - void processShortcutFromDrop(ComponentName componentName, long container, long screenId, - int[] cell, int[] loc) { + private void processShortcutFromDrop(ComponentName componentName, long container, long screenId, + int[] cell) { resetAddInfo(); mPendingAddInfo.container = container; mPendingAddInfo.screenId = screenId; - mPendingAddInfo.dropPos = loc; + mPendingAddInfo.dropPos = null; if (cell != null) { mPendingAddInfo.cellX = cell[0]; @@ -2325,14 +2330,13 @@ public class Launcher extends Activity * @param info The PendingAppWidgetInfo of the widget being added. * @param screenId The ID of the screen where it should be added * @param cell The cell it should be added to, optional - * @param position The location on the screen where it was dropped, optional */ - void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container, long screenId, - int[] cell, int[] span, int[] loc) { + private void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container, long screenId, + int[] cell, int[] span) { resetAddInfo(); mPendingAddInfo.container = info.container = container; mPendingAddInfo.screenId = info.screenId = screenId; - mPendingAddInfo.dropPos = loc; + mPendingAddInfo.dropPos = null; mPendingAddInfo.minSpanX = info.minSpanX; mPendingAddInfo.minSpanY = info.minSpanY; @@ -3291,6 +3295,7 @@ public class Launcher extends Activity showAppsCustomizeHelper(animated, springLoaded, contentType); } + @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void showAppsCustomizeHelper(final boolean animated, final boolean springLoaded, final AppsCustomizePagedView.ContentType contentType) { if (mStateAnimation != null) { @@ -3303,13 +3308,10 @@ public class Launcher extends Activity final Resources res = getResources(); - final int duration = res.getInteger(R.integer.config_appsCustomizeZoomInTime); - final int fadeDuration = res.getInteger(R.integer.config_appsCustomizeFadeInTime); final int revealDuration = res.getInteger(R.integer.config_appsCustomizeRevealTime); final int itemsAlphaStagger = res.getInteger(R.integer.config_appsCustomizeItemsAlphaStagger); - final float scale = (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor); final View fromView = mWorkspace; final AppsCustomizeTabHost toView = mAppsCustomizeTabHost; @@ -3536,14 +3538,10 @@ public class Launcher extends Activity boolean material = Utilities.isLmpOrAbove(); Resources res = getResources(); - final int duration = res.getInteger(R.integer.config_appsCustomizeZoomOutTime); - final int fadeOutDuration = res.getInteger(R.integer.config_appsCustomizeFadeOutTime); final int revealDuration = res.getInteger(R.integer.config_appsCustomizeConcealTime); final int itemsAlphaStagger = res.getInteger(R.integer.config_appsCustomizeItemsAlphaStagger); - final float scaleFactor = (float) - res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor); final View fromView = mAppsCustomizeTabHost; final View toView = mWorkspace; Animator workspaceAnim = null; @@ -4139,6 +4137,19 @@ public class Launcher extends Activity } } + @Override + public void bindAddPendingItem(final PendingAddItemInfo info, final long container, + final long screenId, final int[] cell, final int spanX, final int spanY) { + showWorkspace(true, new Runnable() { + + @Override + public void run() { + mWorkspace.snapToPage(mWorkspace.getPageIndexForScreenId(screenId)); + addPendingItem(info, container, screenId, cell, spanX, spanY); + } + }); + } + private boolean shouldShowWeightWatcher() { String spKey = LauncherAppState.getSharedPreferencesKey(); SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_PRIVATE); diff --git a/src/com/android/launcher3/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/LauncherAccessibilityDelegate.java new file mode 100644 index 000000000..c9e277e4c --- /dev/null +++ b/src/com/android/launcher3/LauncherAccessibilityDelegate.java @@ -0,0 +1,109 @@ +package com.android.launcher3; + +import android.annotation.TargetApi; +import android.os.Build; +import android.os.Bundle; +import android.util.SparseArray; +import android.view.View; +import android.view.View.AccessibilityDelegate; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; + +import com.android.launcher3.LauncherModel.ScreenPosProvider; + +import java.util.ArrayList; + +@TargetApi(Build.VERSION_CODES.LOLLIPOP) +public class LauncherAccessibilityDelegate extends AccessibilityDelegate { + + public static final int REMOVE = R.id.action_remove; + public static final int INFO = R.id.action_info; + public static final int UNINSTALL = R.id.action_uninstall; + public static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace; + + private final SparseArray mActions = + new SparseArray(); + private final Launcher mLauncher; + + public LauncherAccessibilityDelegate(Launcher launcher) { + mLauncher = launcher; + + mActions.put(REMOVE, new AccessibilityAction(REMOVE, + launcher.getText(R.string.delete_target_label))); + mActions.put(INFO, new AccessibilityAction(INFO, + launcher.getText(R.string.info_target_label))); + mActions.put(UNINSTALL, new AccessibilityAction(UNINSTALL, + launcher.getText(R.string.delete_target_uninstall_label))); + mActions.put(ADD_TO_WORKSPACE, new AccessibilityAction(ADD_TO_WORKSPACE, + launcher.getText(R.string.action_add_to_workspace))); + } + + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + if (!(host.getTag() instanceof ItemInfo)) return; + ItemInfo item = (ItemInfo) host.getTag(); + + if ((item instanceof ShortcutInfo) + || (item instanceof LauncherAppWidgetInfo) + || (item instanceof FolderInfo)) { + // Workspace shortcut / widget + info.addAction(mActions.get(REMOVE)); + } else if ((item instanceof AppInfo) || (item instanceof PendingAddItemInfo)) { + // App or Widget from customization tray + if (item instanceof AppInfo) { + info.addAction(mActions.get(UNINSTALL)); + } + info.addAction(mActions.get(INFO)); + info.addAction(mActions.get(ADD_TO_WORKSPACE)); + } + } + + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if ((host.getTag() instanceof ItemInfo) + && performAction(host, (ItemInfo) host.getTag(), action)) { + return true; + } + return super.performAccessibilityAction(host, action, args); + } + + public boolean performAction(View host, ItemInfo item, int action) { + if (action == REMOVE) { + return DeleteDropTarget.removeWorkspaceOrFolderItem(mLauncher, item, host); + } else if (action == INFO) { + InfoDropTarget.startDetailsActivityForInfo(item, mLauncher); + return true; + } else if (action == UNINSTALL) { + DeleteDropTarget.uninstallApp(mLauncher, (AppInfo) item); + return true; + } else if (action == ADD_TO_WORKSPACE) { + final int preferredPage = mLauncher.getWorkspace().getCurrentPage(); + final ScreenPosProvider screenProvider = new ScreenPosProvider() { + + @Override + public int getScreenIndex(ArrayList screenIDs) { + return preferredPage; + } + }; + if (item instanceof AppInfo) { + final ArrayList addShortcuts = new ArrayList(); + addShortcuts.add(((AppInfo) item).makeShortcut()); + mLauncher.showWorkspace(true, new Runnable() { + + @Override + public void run() { + mLauncher.getModel().addAndBindAddedWorkspaceApps( + mLauncher, addShortcuts, screenProvider, 0, true); + } + }); + return true; + } else if (item instanceof PendingAddItemInfo) { + mLauncher.getModel().addAndBindPendingItem( + mLauncher, (PendingAddItemInfo) item, screenProvider, 0); + return true; + } + } + return false; + } +} diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index b7c45a340..87e9aae15 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -32,10 +32,13 @@ import android.os.Handler; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; +import android.view.View.AccessibilityDelegate; import android.view.WindowManager; + import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.PackageInstallerCompat; import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; + import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -62,6 +65,7 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks { private static LauncherAppState INSTANCE; private DynamicGrid mDynamicGrid; + private AccessibilityDelegate mAccessibilityDelegate; public static LauncherAppState getInstance() { if (INSTANCE == null) { @@ -162,9 +166,15 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks { LauncherModel setLauncher(Launcher launcher) { mModel.initialize(launcher); + mAccessibilityDelegate = ((launcher != null) && Utilities.isLmpOrAbove()) ? + new LauncherAccessibilityDelegate(launcher) : null; return mModel; } + AccessibilityDelegate getAccessibilityDelegate() { + return mAccessibilityDelegate; + } + public IconCache getIconCache() { return mIconCache; } diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java index ebe55ab78..2d04df2de 100644 --- a/src/com/android/launcher3/LauncherAppWidgetHostView.java +++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java @@ -48,6 +48,7 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc mLongPressHelper = new CheckLongPressHelper(this); mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mDragLayer = ((Launcher) context).getDragLayer(); + setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate()); } @Override diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 95ebaec87..7b5f8466a 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -29,7 +29,6 @@ import android.content.Intent; import android.content.Intent.ShortcutIconResource; import android.content.IntentFilter; import android.content.SharedPreferences; -import android.content.pm.LauncherApps.Callback; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; @@ -38,6 +37,7 @@ import android.content.res.Resources; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Rect; import android.net.Uri; import android.os.Environment; import android.os.Handler; @@ -49,6 +49,7 @@ import android.os.SystemClock; import android.provider.BaseColumns; import android.text.TextUtils; import android.util.Log; +import android.util.LongSparseArray; import android.util.Pair; import com.android.launcher3.compat.AppWidgetManagerCompat; @@ -108,7 +109,6 @@ public class LauncherModel extends BroadcastReceiver private DeferredHandler mHandler = new DeferredHandler(); private LoaderTask mLoaderTask; private boolean mIsLoaderTaskRunning; - private volatile boolean mFlushingWorkerThread; /** * Maintain a set of packages per user, for which we added a shortcut on the workspace. @@ -219,12 +219,18 @@ public class LauncherModel extends BroadcastReceiver public boolean isAllAppsButtonRank(int rank); public void onPageBoundSynchronously(int page); public void dumpLogsToLocalData(); + public void bindAddPendingItem(PendingAddItemInfo info, long container, long screenId, + int[] cell, int spanX, int spanY); } public interface ItemInfoFilter { public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn); } + public interface ScreenPosProvider { + int getScreenIndex(ArrayList screenIDs); + } + LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) { Context context = app.getContext(); @@ -287,67 +293,6 @@ public class LauncherModel extends BroadcastReceiver return mOldContentProviderExists && !launcher.isLauncherPreinstalled() ; } - static boolean findNextAvailableIconSpaceInScreen(ArrayList items, int[] xy, - long screen) { - LauncherAppState app = LauncherAppState.getInstance(); - DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); - final int xCount = (int) grid.numColumns; - final int yCount = (int) grid.numRows; - boolean[][] occupied = new boolean[xCount][yCount]; - - int cellX, cellY, spanX, spanY; - for (int i = 0; i < items.size(); ++i) { - final ItemInfo item = items.get(i); - if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { - if (item.screenId == screen) { - cellX = item.cellX; - cellY = item.cellY; - spanX = item.spanX; - spanY = item.spanY; - for (int x = cellX; 0 <= x && x < cellX + spanX && x < xCount; x++) { - for (int y = cellY; 0 <= y && y < cellY + spanY && y < yCount; y++) { - occupied[x][y] = true; - } - } - } - } - } - - return CellLayout.findVacantCell(xy, 1, 1, xCount, yCount, occupied); - } - static Pair findNextAvailableIconSpace(Context context, String name, - Intent launchIntent, - int firstScreenIndex, - ArrayList workspaceScreens) { - // Lock on the app so that we don't try and get the items while apps are being added - LauncherAppState app = LauncherAppState.getInstance(); - LauncherModel model = app.getModel(); - boolean found = false; - synchronized (app) { - if (sWorkerThread.getThreadId() != Process.myTid()) { - // Flush the LauncherModel worker thread, so that if we just did another - // processInstallShortcut, we give it time for its shortcut to get added to the - // database (getItemsInLocalCoordinates reads the database) - model.flushWorkerThread(); - } - final ArrayList items = LauncherModel.getItemsInLocalCoordinates(context); - - // Try adding to the workspace screens incrementally, starting at the default or center - // screen and alternating between +1, -1, +2, -2, etc. (using ~ ceil(i/2f)*(-1)^(i-1)) - firstScreenIndex = Math.min(firstScreenIndex, workspaceScreens.size()); - int count = workspaceScreens.size(); - for (int screen = firstScreenIndex; screen < count && !found; screen++) { - int[] tmpCoordinates = new int[2]; - if (findNextAvailableIconSpaceInScreen(items, tmpCoordinates, - workspaceScreens.get(screen))) { - // Update the Launcher db - return new Pair(workspaceScreens.get(screen), tmpCoordinates); - } - } - } - return null; - } - public void setPackageState(final ArrayList installInfo) { // Process the updated package state Runnable r = new Runnable() { @@ -402,11 +347,196 @@ public class LauncherModel extends BroadcastReceiver public void addAndBindAddedWorkspaceApps(final Context context, final ArrayList workspaceApps) { - final Callbacks callbacks = getCallback(); + addAndBindAddedWorkspaceApps(context, workspaceApps, + new ScreenPosProvider() { + + @Override + public int getScreenIndex(ArrayList screenIDs) { + return screenIDs.isEmpty() ? 0 : 1; + } + }, 1, false); + } - if (workspaceApps == null) { - throw new RuntimeException("workspaceApps and allAppsApps must not be null"); + private static boolean findNextAvailableIconSpaceInScreen(ArrayList occupiedPos, + int[] xy, int spanX, int spanY) { + LauncherAppState app = LauncherAppState.getInstance(); + DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); + final int xCount = (int) grid.numColumns; + final int yCount = (int) grid.numRows; + boolean[][] occupied = new boolean[xCount][yCount]; + if (occupiedPos != null) { + for (Rect r : occupiedPos) { + for (int x = r.left; 0 <= x && x < r.right && x < xCount; x++) { + for (int y = r.top; 0 <= y && y < r.bottom && y < yCount; y++) { + occupied[x][y] = true; + } + } + } + } + return CellLayout.findVacantCell(xy, spanX, spanY, xCount, yCount, occupied); + } + + /** + * Find a position on the screen for the given size or adds a new screen. + * @return screenId and the coordinates for the item. + */ + private static Pair findSpaceForItem( + Context context, + ScreenPosProvider preferredScreen, + int fallbackStartScreen, + ArrayList workspaceScreens, + ArrayList addedWorkspaceScreensFinal, + int spanX, int spanY) { + // Load position of items which are on the desktop. We can't use sBgItemsIdMap because + // loadWorkspace() may not have been called. + final ContentResolver cr = context.getContentResolver(); + Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, + new String[] { + LauncherSettings.Favorites.SCREEN, + LauncherSettings.Favorites.CELLX, + LauncherSettings.Favorites.CELLY, + LauncherSettings.Favorites.SPANX, + LauncherSettings.Favorites.SPANY, + LauncherSettings.Favorites.CONTAINER + }, + "container=?", + new String[] { Integer.toString(LauncherSettings.Favorites.CONTAINER_DESKTOP) }, + null); + + final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN); + final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX); + final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY); + final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX); + final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY); + LongSparseArray> screenItems = new LongSparseArray>(); + try { + while (c.moveToNext()) { + Rect rect = new Rect(); + rect.left = c.getInt(cellXIndex); + rect.top = c.getInt(cellYIndex); + rect.right = rect.left + Math.max(1, c.getInt(spanXIndex)); + rect.bottom = rect.top + Math.max(1, c.getInt(spanYIndex)); + + long screenId = c.getInt(screenIndex); + ArrayList items = screenItems.get(screenId); + if (items == null) { + items = new ArrayList(); + screenItems.put(screenId, items); + } + items.add(rect); + } + } catch (Exception e) { + screenItems.clear(); + } finally { + c.close(); + } + + // Find appropriate space for the item. + long screenId = 0; + int[] cordinates = new int[2]; + boolean found = false; + + int screenCount = workspaceScreens.size(); + // First check the preferred screen. + int preferredScreenIndex = preferredScreen.getScreenIndex(workspaceScreens); + if (preferredScreenIndex < screenCount) { + screenId = workspaceScreens.get(preferredScreenIndex); + found = findNextAvailableIconSpaceInScreen( + screenItems.get(screenId), cordinates, spanX, spanY); + } + + if (!found) { + // Search on any of the screens. + for (int screen = fallbackStartScreen; screen < screenCount; screen++) { + screenId = workspaceScreens.get(screen); + if (findNextAvailableIconSpaceInScreen( + screenItems.get(screenId), cordinates, spanX, spanY)) { + // We found a space for it + found = true; + break; + } + } } + + if (!found) { + // Still no position found. Add a new screen to the end. + screenId = LauncherAppState.getLauncherProvider().generateNewScreenId(); + + // Save the screen id for binding in the workspace + workspaceScreens.add(screenId); + addedWorkspaceScreensFinal.add(screenId); + + // If we still can't find an empty space, then God help us all!!! + if (!findNextAvailableIconSpaceInScreen( + screenItems.get(screenId), cordinates, spanX, spanY)) { + throw new RuntimeException("Can't find space to add the item"); + } + } + return Pair.create(screenId, cordinates); + } + + /** + * Adds the provided items to the workspace. + * @param preferredScreen the screen where we should try to add the app first + * @param fallbackStartScreen the screen to start search for empty space if + * preferredScreen is not available. + */ + public void addAndBindPendingItem( + final Context context, + final PendingAddItemInfo addInfo, + final ScreenPosProvider preferredScreen, + final int fallbackStartScreen) { + final Callbacks callbacks = getCallback(); + // Process the newly added applications and add them to the database first + Runnable r = new Runnable() { + public void run() { + final ArrayList addedWorkspaceScreensFinal = new ArrayList(); + + ArrayList workspaceScreens = new ArrayList(); + TreeMap orderedScreens = loadWorkspaceScreensDb(context); + for (Integer i : orderedScreens.keySet()) { + long screenId = orderedScreens.get(i); + workspaceScreens.add(screenId); + } + + // Find appropriate space for the item. + Pair coords = findSpaceForItem(context, preferredScreen, + fallbackStartScreen, workspaceScreens, addedWorkspaceScreensFinal, + addInfo.spanX, + addInfo.spanY); + final long screenId = coords.first; + final int[] cordinates = coords.second; + + // Update the workspace screens + updateWorkspaceScreenOrder(context, workspaceScreens); + runOnMainThread(new Runnable() { + public void run() { + Callbacks cb = getCallback(); + if (callbacks == cb && cb != null) { + cb.bindAddScreens(addedWorkspaceScreensFinal); + cb.bindAddPendingItem(addInfo, + LauncherSettings.Favorites.CONTAINER_DESKTOP, + screenId, cordinates, addInfo.spanX, addInfo.spanY); + } + } + }); + } + }; + runOnWorkerThread(r); + } + + /** + * Adds the provided items to the workspace. + * @param preferredScreen the screen where we should try to add the app first + * @param fallbackStartScreen the screen to start search for empty space if + * preferredScreen is not available. + */ + public void addAndBindAddedWorkspaceApps(final Context context, + final ArrayList workspaceApps, + final ScreenPosProvider preferredScreen, + final int fallbackStartScreen, + final boolean allowDuplicate) { + final Callbacks callbacks = getCallback(); if (workspaceApps.isEmpty()) { return; } @@ -427,53 +557,27 @@ public class LauncherModel extends BroadcastReceiver } synchronized(sBgLock) { - Iterator iter = workspaceApps.iterator(); - while (iter.hasNext()) { - ItemInfo a = iter.next(); - final String name = a.title.toString(); - final Intent launchIntent = a.getIntent(); - - // Short-circuit this logic if the icon exists somewhere on the workspace - if (shortcutExists(context, name, launchIntent, a.user)) { - continue; - } - - // Add this icon to the db, creating a new page if necessary. If there - // is only the empty page then we just add items to the first page. - // Otherwise, we add them to the next pages. - int startSearchPageIndex = workspaceScreens.isEmpty() ? 0 : 1; - Pair coords = LauncherModel.findNextAvailableIconSpace(context, - name, launchIntent, startSearchPageIndex, workspaceScreens); - if (coords == null) { - LauncherProvider lp = LauncherAppState.getLauncherProvider(); - - // If we can't find a valid position, then just add a new screen. - // This takes time so we need to re-queue the add until the new - // page is added. Create as many screens as necessary to satisfy - // the startSearchPageIndex. - int numPagesToAdd = Math.max(1, startSearchPageIndex + 1 - - workspaceScreens.size()); - while (numPagesToAdd > 0) { - long screenId = lp.generateNewScreenId(); - // Save the screen id for binding in the workspace - workspaceScreens.add(screenId); - addedWorkspaceScreensFinal.add(screenId); - numPagesToAdd--; + for (ItemInfo item : workspaceApps) { + if (!allowDuplicate) { + // Short-circuit this logic if the icon exists somewhere on the workspace + if (shortcutExists(context, item.title.toString(), + item.getIntent(), item.user)) { + continue; } - - // Find the coordinate again - coords = LauncherModel.findNextAvailableIconSpace(context, - name, launchIntent, startSearchPageIndex, workspaceScreens); - } - if (coords == null) { - throw new RuntimeException("Coordinates should not be null"); } + // Find appropriate space for the item. + Pair coords = findSpaceForItem(context, preferredScreen, + fallbackStartScreen, workspaceScreens, addedWorkspaceScreensFinal, + 1, 1); + long screenId = coords.first; + int[] cordinates = coords.second; + ShortcutInfo shortcutInfo; - if (a instanceof ShortcutInfo) { - shortcutInfo = (ShortcutInfo) a; - } else if (a instanceof AppInfo) { - shortcutInfo = ((AppInfo) a).makeShortcut(); + if (item instanceof ShortcutInfo) { + shortcutInfo = (ShortcutInfo) item; + } else if (item instanceof AppInfo) { + shortcutInfo = ((AppInfo) item).makeShortcut(); } else { throw new RuntimeException("Unexpected info type"); } @@ -481,7 +585,7 @@ public class LauncherModel extends BroadcastReceiver // Add the shortcut to the db addItemToDatabase(context, shortcutInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP, - coords.first, coords.second[0], coords.second[1], false); + screenId, cordinates[0], cordinates[1], false); // Save the ShortcutInfo for binding in the workspace addedShortcutsFinal.add(shortcutInfo); } @@ -717,35 +821,6 @@ public class LauncherModel extends BroadcastReceiver } } - public void flushWorkerThread() { - mFlushingWorkerThread = true; - Runnable waiter = new Runnable() { - public void run() { - synchronized (this) { - notifyAll(); - mFlushingWorkerThread = false; - } - } - }; - - synchronized(waiter) { - runOnWorkerThread(waiter); - if (mLoaderTask != null) { - synchronized(mLoaderTask) { - mLoaderTask.notify(); - } - } - boolean success = false; - while (!success) { - try { - waiter.wait(); - success = true; - } catch (InterruptedException e) { - } - } - } - } - /** * Move an item in the DB to a new */ @@ -889,57 +964,6 @@ public class LauncherModel extends BroadcastReceiver } } - /** - * Returns an ItemInfo array containing all the items in the LauncherModel. - * The ItemInfo.id is not set through this function. - */ - static ArrayList getItemsInLocalCoordinates(Context context) { - ArrayList items = new ArrayList(); - final ContentResolver cr = context.getContentResolver(); - Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, new String[] { - LauncherSettings.Favorites.ITEM_TYPE, LauncherSettings.Favorites.CONTAINER, - LauncherSettings.Favorites.SCREEN, - LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY, - LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY, - LauncherSettings.Favorites.PROFILE_ID }, null, null, null); - - final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE); - final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER); - final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN); - final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX); - final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY); - final int rankIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.RANK); - final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX); - final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY); - final int profileIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE_ID); - UserManagerCompat userManager = UserManagerCompat.getInstance(context); - try { - while (c.moveToNext()) { - ItemInfo item = new ItemInfo(); - item.cellX = c.getInt(cellXIndex); - item.cellY = c.getInt(cellYIndex); - item.rank = c.getInt(rankIndex); - item.spanX = Math.max(1, c.getInt(spanXIndex)); - item.spanY = Math.max(1, c.getInt(spanYIndex)); - item.container = c.getInt(containerIndex); - item.itemType = c.getInt(itemTypeIndex); - item.screenId = c.getInt(screenIndex); - long serialNumber = c.getInt(profileIdIndex); - item.user = userManager.getUserForSerialNumber(serialNumber); - // Skip if user has been deleted. - if (item.user != null) { - items.add(item); - } - } - } catch (Exception e) { - items.clear(); - } finally { - c.close(); - } - - return items; - } - /** * Find a folder in the db, creating the FolderInfo if necessary, and adding it to folderList. */ @@ -1543,7 +1567,7 @@ public class LauncherModel extends BroadcastReceiver } }); - while (!mStopped && !mLoadAndBindStepFinished && !mFlushingWorkerThread) { + while (!mStopped && !mLoadAndBindStepFinished) { try { // Just in case mFlushingWorkerThread changes but we aren't woken up, // wait no longer than 1sec at a time diff --git a/src/com/android/launcher3/PagedViewWidget.java b/src/com/android/launcher3/PagedViewWidget.java index 41270e3be..107069b78 100644 --- a/src/com/android/launcher3/PagedViewWidget.java +++ b/src/com/android/launcher3/PagedViewWidget.java @@ -16,7 +16,6 @@ package com.android.launcher3; -import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; @@ -67,6 +66,7 @@ public class PagedViewWidget extends LinearLayout { setWillNotDraw(false); setClipToPadding(false); + setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate()); } @Override diff --git a/src/com/android/launcher3/PreloadIconDrawable.java b/src/com/android/launcher3/PreloadIconDrawable.java index 2972c4f9b..bcb59c448 100644 --- a/src/com/android/launcher3/PreloadIconDrawable.java +++ b/src/com/android/launcher3/PreloadIconDrawable.java @@ -54,12 +54,11 @@ class PreloadIconDrawable extends Drawable { mPaint.setStrokeCap(Paint.Cap.ROUND); setBounds(icon.getBounds()); - applyTheme(theme); + applyPreloaderTheme(theme); onLevelChange(0); } - @Override - public void applyTheme(Theme t) { + public void applyPreloaderTheme(Theme t) { TypedArray ta = t.obtainStyledAttributes(R.styleable.PreloadIconDrawable); mBgDrawable = ta.getDrawable(R.styleable.PreloadIconDrawable_background); mBgDrawable.setFilterBitmap(true); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index b6e85f304..44d77571b 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -31,10 +31,7 @@ import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; @@ -77,8 +74,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.Map; -import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; /** @@ -92,9 +87,6 @@ public class Workspace extends SmoothPagedView Insettable { private static final String TAG = "Launcher.Workspace"; - // Y rotation to apply to the workspace screens - private static final float WORKSPACE_OVERSCROLL_ROTATION = 24f; - private static final int CHILDREN_OUTLINE_FADE_OUT_DELAY = 0; private static final int CHILDREN_OUTLINE_FADE_OUT_DURATION = 375; private static final int CHILDREN_OUTLINE_FADE_IN_DURATION = 100; @@ -228,7 +220,6 @@ public class Workspace extends SmoothPagedView private Runnable mDelayedResizeRunnable; private Runnable mDelayedSnapToPageRunnable; private Point mDisplaySize = new Point(); - private int mCameraDistance; // Variables relating to the creation of user folders by hovering shortcuts over shortcuts private static final int FOLDER_CREATION_TIMEOUT = 0; @@ -346,7 +337,6 @@ public class Workspace extends SmoothPagedView mSpringLoadedShrinkFactor = res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f; mOverviewModeShrinkFactor = grid.getOverviewModeScale(); - mCameraDistance = res.getInteger(R.integer.config_cameraDistance); mOriginalDefaultPage = mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1); a.recycle(); @@ -450,7 +440,6 @@ public class Workspace extends SmoothPagedView */ protected void initWorkspace() { mCurrentPage = mDefaultPage; - Launcher.setScreen(mCurrentPage); LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); mIconCache = app.getIconCache(); @@ -1323,7 +1312,6 @@ public class Workspace extends SmoothPagedView @Override protected void notifyPageSwitchListener() { super.notifyPageSwitchListener(); - Launcher.setScreen(getNextPage()); if (hasCustomContent() && getNextPage() == 0 && !mCustomContentShowing) { mCustomContentShowing = true; @@ -3952,23 +3940,8 @@ public class Workspace extends SmoothPagedView // When dragging and dropping from customization tray, we deal with creating // widgets/shortcuts/folders in a slightly different way - switch (pendingInfo.itemType) { - case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET: - case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: - int span[] = new int[2]; - span[0] = item.spanX; - span[1] = item.spanY; - mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) pendingInfo, - container, screenId, mTargetCell, span, null); - break; - case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: - mLauncher.processShortcutFromDrop(pendingInfo.componentName, - container, screenId, mTargetCell, null); - break; - default: - throw new IllegalStateException("Unknown item type: " + - pendingInfo.itemType); - } + mLauncher.addPendingItem(pendingInfo, container, screenId, mTargetCell, + item.spanX, item.spanY); } }; boolean isWidget = pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET @@ -3998,7 +3971,7 @@ public class Workspace extends SmoothPagedView case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: if (info.container == NO_ID && info instanceof AppInfo) { // Came from all apps -- make a copy - info = new ShortcutInfo((AppInfo) info); + info = ((AppInfo) info).makeShortcut(); } view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info); @@ -4250,15 +4223,7 @@ public class Workspace extends SmoothPagedView if (success && !(beingCalledAfterUninstall && !mUninstallSuccessful)) { if (target != this && mDragInfo != null) { - CellLayout parentCell = getParentCellLayoutForView(mDragInfo.cell); - if (parentCell != null) { - parentCell.removeView(mDragInfo.cell); - } else if (LauncherAppState.isDogfoodBuild()) { - throw new NullPointerException("mDragInfo.cell has null parent"); - } - if (mDragInfo.cell instanceof DropTarget) { - mDragController.removeDropTarget((DropTarget) mDragInfo.cell); - } + removeWorkspaceItem(mDragInfo.cell); } } else if (mDragInfo != null) { CellLayout cellLayout; @@ -4283,6 +4248,18 @@ public class Workspace extends SmoothPagedView mDragInfo = null; } + public void removeWorkspaceItem(View v) { + CellLayout parentCell = getParentCellLayoutForView(v); + if (parentCell != null) { + parentCell.removeView(v); + } else if (LauncherAppState.isDogfoodBuild()) { + throw new NullPointerException("mDragInfo.cell has null parent"); + } + if (v instanceof DropTarget) { + mDragController.removeDropTarget((DropTarget) v); + } + } + public void deferCompleteDropAfterUninstallActivity() { mDeferDropAfterUninstall = true; } @@ -4477,12 +4454,6 @@ public class Workspace extends SmoothPagedView return true; } - @Override - protected void onRestoreInstanceState(Parcelable state) { - super.onRestoreInstanceState(state); - Launcher.setScreen(mCurrentPage); - } - @Override protected void dispatchRestoreInstanceState(SparseArray container) { // We don't dispatch restoreInstanceState to our children using this code path. -- cgit v1.2.3