summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/layout/search_drop_target_bar.xml2
-rw-r--r--res/values-sw600dp/config.xml4
-rw-r--r--res/values-sw720dp/config.xml3
-rw-r--r--res/values/config.xml14
-rw-r--r--res/values/strings.xml7
-rw-r--r--src/com/android/launcher3/BubbleTextView.java36
-rw-r--r--src/com/android/launcher3/CellLayout.java8
-rw-r--r--src/com/android/launcher3/DeleteDropTarget.java83
-rw-r--r--src/com/android/launcher3/FolderIcon.java1
-rw-r--r--src/com/android/launcher3/InfoDropTarget.java30
-rw-r--r--src/com/android/launcher3/Launcher.java71
-rw-r--r--src/com/android/launcher3/LauncherAccessibilityDelegate.java109
-rw-r--r--src/com/android/launcher3/LauncherAppState.java10
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetHostView.java1
-rw-r--r--src/com/android/launcher3/LauncherModel.java406
-rw-r--r--src/com/android/launcher3/PagedViewWidget.java2
-rw-r--r--src/com/android/launcher3/PreloadIconDrawable.java5
-rw-r--r--src/com/android/launcher3/Workspace.java61
18 files changed, 494 insertions, 359 deletions
diff --git a/res/layout/search_drop_target_bar.xml b/res/layout/search_drop_target_bar.xml
index af2d01634..0d7167e5b 100644
--- a/res/layout/search_drop_target_bar.xml
+++ b/res/layout/search_drop_target_bar.xml
@@ -38,7 +38,7 @@
android:id="@+id/delete_target_text"
style="@style/DropTargetButton"
android:drawableStart="@drawable/remove_target_selector"
- android:text="@string/delete_zone_label_workspace" />
+ android:text="@string/delete_target_label" />
</FrameLayout>
<FrameLayout
diff --git a/res/values-sw600dp/config.xml b/res/values-sw600dp/config.xml
index 15d5725d1..a7345a705 100644
--- a/res/values-sw600dp/config.xml
+++ b/res/values-sw600dp/config.xml
@@ -4,8 +4,4 @@
<!-- DragController -->
<integer name="config_flingToDeleteMinVelocity">-1000</integer>
-
- <!-- Camera distance for the overscroll effect. We use a higher value here because the
- workspace screens run nearly flush to the edge of the screen-->
- <integer name="config_cameraDistance">14000</integer>
</resources>
diff --git a/res/values-sw720dp/config.xml b/res/values-sw720dp/config.xml
index c00b5943f..3d2ca8318 100644
--- a/res/values-sw720dp/config.xml
+++ b/res/values-sw720dp/config.xml
@@ -10,9 +10,6 @@
<!-- Whether or not the drop targets drop down as opposed to fade in -->
<bool name="config_useDropTargetDownTransition">false</bool>
- <!-- Camera distance for the overscroll effect -->
- <integer name="config_cameraDistance">18000</integer>
-
<!-- Hotseat -->
<bool name="hotseat_transpose_layout_with_orientation">false</bool>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 96bd13bbb..cbec51216 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -36,11 +36,6 @@
<!-- Fade/zoom in/out duration & scale in the AllApps transition.
Note: This should be less than the workspaceShrinkTime as they happen together. -->
<integer name="config_appsCustomizeRevealTime">220</integer>
- <integer name="config_appsCustomizeZoomInTime">350</integer>
- <integer name="config_appsCustomizeZoomOutTime">600</integer>
- <integer name="config_appsCustomizeZoomScaleFactor">7</integer>
- <integer name="config_appsCustomizeFadeInTime">250</integer>
- <integer name="config_appsCustomizeFadeOutTime">200</integer>
<integer name="config_appsCustomizeWorkspaceShrinkTime">300</integer>
<integer name="config_appsCustomizeConcealTime">250</integer>
@@ -90,9 +85,6 @@
<integer name="config_dragFadeOutAlpha">80</integer>
<integer name="config_dragFadeOutDuration">250</integer>
- <!-- Camera distance for the overscroll effect -->
- <integer name="config_cameraDistance">8000</integer>
-
<!-- Hotseat -->
<bool name="hotseat_transpose_layout_with_orientation">true</bool>
@@ -106,4 +98,10 @@
<!-- Name of a subclass of com.android.launcher3.BuildInfo used to
get build information. Can be empty. -->
<string name="build_info_class" translatable="false"></string>
+
+<!-- Accessibility actions -->
+ <item type="id" name="action_remove" />
+ <item type="id" name="action_uninstall" />
+ <item type="id" name="action_info" />
+ <item type="id" name="action_add_to_workspace" />
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4af1f7347..8b7e6c199 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -118,9 +118,6 @@ s -->
<!-- Label for button in all applications label to go back home (to the workspace / desktop)
for accessibilty (spoken when the button gets focus). -->
<string name="all_apps_home_button_label">Home</string>
- <!-- Label for trash icon on workspace. Meant to communicate the idea of removing the
- icon/widget from the home screen, but not permanently. [CHAR_LIMIT=30] -->
- <string name="delete_zone_label_workspace">Remove</string>
<!-- Label for trash icon in All Apps. The icon/widget will become completely unavailable on the
device. [CHAR_LIMIT=30]-->
<string name="delete_zone_label_all_apps">Uninstall</string>
@@ -304,4 +301,8 @@ s -->
<string name="abandoned_promise_explanation">The app for this icon isn\'t installed.
You can remove it, or search for the app and install it manually.
</string>
+
+<!-- Strings for accessibility actions -->
+ <!-- Accessibility action to add an app to workspace. [CHAR_LIMIT=30] -->
+ <string name="action_add_to_workspace">Add To Workspace</string>
</resources>
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<Void, Void, Void>() {
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<Integer, Integer> mItemIdToViewId = new HashMap<Integer, Integer>();
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<AccessibilityAction> mActions =
+ new SparseArray<AccessibilityAction>();
+ 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<Long> screenIDs) {
+ return preferredPage;
+ }
+ };
+ if (item instanceof AppInfo) {
+ final ArrayList<ItemInfo> addShortcuts = new ArrayList<ItemInfo>();
+ 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<Long> 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<ItemInfo> 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<Long, int[]> findNextAvailableIconSpace(Context context, String name,
- Intent launchIntent,
- int firstScreenIndex,
- ArrayList<Long> 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<ItemInfo> 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<Long, int[]>(workspaceScreens.get(screen), tmpCoordinates);
- }
- }
- }
- return null;
- }
-
public void setPackageState(final ArrayList<PackageInstallInfo> 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<ItemInfo> workspaceApps) {
- final Callbacks callbacks = getCallback();
+ addAndBindAddedWorkspaceApps(context, workspaceApps,
+ new ScreenPosProvider() {
+
+ @Override
+ public int getScreenIndex(ArrayList<Long> 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<Rect> 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<Long, int[]> findSpaceForItem(
+ Context context,
+ ScreenPosProvider preferredScreen,
+ int fallbackStartScreen,
+ ArrayList<Long> workspaceScreens,
+ ArrayList<Long> 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<ArrayList<Rect>> screenItems = new LongSparseArray<ArrayList<Rect>>();
+ 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<Rect> items = screenItems.get(screenId);
+ if (items == null) {
+ items = new ArrayList<Rect>();
+ 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<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();
+
+ ArrayList<Long> workspaceScreens = new ArrayList<Long>();
+ TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(context);
+ for (Integer i : orderedScreens.keySet()) {
+ long screenId = orderedScreens.get(i);
+ workspaceScreens.add(screenId);
+ }
+
+ // Find appropriate space for the item.
+ Pair<Long, int[]> 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<ItemInfo> 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<ItemInfo> 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<Long, int[]> 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<Long, int[]> 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 <container, screen, cellX, cellY>
*/
@@ -890,57 +965,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<ItemInfo> getItemsInLocalCoordinates(Context context) {
- ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
- 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.
*/
FolderInfo getFolderById(Context context, HashMap<Long,FolderInfo> folderList, long id) {
@@ -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;
}
@@ -4478,12 +4455,6 @@ public class Workspace extends SmoothPagedView
}
@Override
- protected void onRestoreInstanceState(Parcelable state) {
- super.onRestoreInstanceState(state);
- Launcher.setScreen(mCurrentPage);
- }
-
- @Override
protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
// We don't dispatch restoreInstanceState to our children using this code path.
// Some pages will be restored immediately as their items are bound immediately, and