summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-02 22:54:41 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-02 22:54:41 -0800
commitb28e1b7d95a4a9aeae54dcac6d1a24fa612ab918 (patch)
tree84e76f294704a009453c337f6d4aea69bca5134b /src
parent233a0136ea1fe86c61f02eb7b60dd2a9e3af4d91 (diff)
downloadandroid_packages_apps_Trebuchet-b28e1b7d95a4a9aeae54dcac6d1a24fa612ab918.tar.gz
android_packages_apps_Trebuchet-b28e1b7d95a4a9aeae54dcac6d1a24fa612ab918.tar.bz2
android_packages_apps_Trebuchet-b28e1b7d95a4a9aeae54dcac6d1a24fa612ab918.zip
auto import from //depot/cupcake/@137055
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher/AddAdapter.java2
-rw-r--r--src/com/android/launcher/AllAppsGridView.java49
-rw-r--r--src/com/android/launcher/DeleteZone.java6
-rw-r--r--src/com/android/launcher/DragLayer.java12
-rw-r--r--src/com/android/launcher/Launcher.java170
-rw-r--r--src/com/android/launcher/LauncherGadgetHostView.java4
-rw-r--r--src/com/android/launcher/LauncherModel.java50
-rw-r--r--src/com/android/launcher/LauncherProvider.java189
-rw-r--r--src/com/android/launcher/LauncherSettings.java3
-rw-r--r--src/com/android/launcher/LiveFolder.java47
-rw-r--r--src/com/android/launcher/LiveFolderAdapter.java9
-rw-r--r--src/com/android/launcher/Search.java36
-rw-r--r--src/com/android/launcher/SearchAutoCompleteTextView.java70
-rw-r--r--src/com/android/launcher/Workspace.java26
14 files changed, 591 insertions, 82 deletions
diff --git a/src/com/android/launcher/AddAdapter.java b/src/com/android/launcher/AddAdapter.java
index 14107084e..18b36d5e2 100644
--- a/src/com/android/launcher/AddAdapter.java
+++ b/src/com/android/launcher/AddAdapter.java
@@ -82,7 +82,7 @@ public class AddAdapter extends BaseAdapter {
mItems.add(new ListItem(res, R.string.group_search,
R.drawable.ic_search_gadget, ITEM_SEARCH));
- mItems.add(new ListItem(res, R.string.group_gadgets,
+ mItems.add(new ListItem(res, R.string.group_widgets,
R.drawable.ic_launcher_gadget, ITEM_GADGET));
mItems.add(new ListItem(res, R.string.group_live_folders,
diff --git a/src/com/android/launcher/AllAppsGridView.java b/src/com/android/launcher/AllAppsGridView.java
index a898c1a02..b8f79025f 100644
--- a/src/com/android/launcher/AllAppsGridView.java
+++ b/src/com/android/launcher/AllAppsGridView.java
@@ -19,25 +19,46 @@ package com.android.launcher;
import android.widget.GridView;
import android.widget.AdapterView;
import android.content.Context;
+import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Paint;
+import android.graphics.Canvas;
public class AllAppsGridView extends GridView implements AdapterView.OnItemClickListener,
AdapterView.OnItemLongClickListener, DragSource {
private DragController mDragger;
private Launcher mLauncher;
+ private Bitmap mTexture;
+ private Paint mPaint;
+ private int mTextureWidth;
+ private int mTextureHeight;
public AllAppsGridView(Context context) {
super(context);
}
public AllAppsGridView(Context context, AttributeSet attrs) {
- super(context, attrs);
+ this(context, attrs, com.android.internal.R.attr.gridViewStyle);
}
public AllAppsGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AllAppsGridView, defStyle, 0);
+ final int textureId = a.getResourceId(R.styleable.AllAppsGridView_texture, 0);
+ if (textureId != 0) {
+ mTexture = BitmapFactory.decodeResource(getResources(), textureId);
+ mTextureWidth = mTexture.getWidth();
+ mTextureHeight = mTexture.getHeight();
+
+ mPaint = new Paint();
+ mPaint.setDither(false);
+ }
+ a.recycle();
}
@Override
@@ -46,6 +67,32 @@ public class AllAppsGridView extends GridView implements AdapterView.OnItemClick
setOnItemLongClickListener(this);
}
+ @Override
+ public void draw(Canvas canvas) {
+ final Bitmap texture = mTexture;
+ final Paint paint = mPaint;
+
+ final int width = getWidth();
+ final int height = getHeight();
+
+ final int textureWidth = mTextureWidth;
+ final int textureHeight = mTextureHeight;
+
+ int x = 0;
+ int y;
+
+ while (x < width) {
+ y = 0;
+ while (y < height) {
+ canvas.drawBitmap(texture, x, y, paint);
+ y += textureHeight;
+ }
+ x += textureWidth;
+ }
+
+ super.draw(canvas);
+ }
+
public void onItemClick(AdapterView parent, View v, int position, long id) {
ApplicationInfo app = (ApplicationInfo) parent.getItemAtPosition(position);
mLauncher.startActivitySafely(app.intent);
diff --git a/src/com/android/launcher/DeleteZone.java b/src/com/android/launcher/DeleteZone.java
index 6f67884db..f31a206c5 100644
--- a/src/com/android/launcher/DeleteZone.java
+++ b/src/com/android/launcher/DeleteZone.java
@@ -85,7 +85,11 @@ public class DeleteZone extends ImageView implements DropTarget, DragController.
final LauncherModel model = Launcher.getModel();
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- model.removeDesktopItem(item);
+ if (item instanceof LauncherGadgetInfo) {
+ model.removeDesktopGadget((LauncherGadgetInfo) item);
+ } else {
+ model.removeDesktopItem(item);
+ }
} else {
if (source instanceof UserFolder) {
final UserFolder userFolder = (UserFolder) source;
diff --git a/src/com/android/launcher/DragLayer.java b/src/com/android/launcher/DragLayer.java
index aa6615a22..b542de62a 100644
--- a/src/com/android/launcher/DragLayer.java
+++ b/src/com/android/launcher/DragLayer.java
@@ -32,6 +32,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.KeyEvent;
+import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
/**
@@ -127,6 +128,8 @@ public class DragLayer extends FrameLayout implements DragController {
private int mAnimationType;
private int mAnimationState = ANIMATION_STATE_DONE;
+ private InputMethodManager mInputMethodManager;
+
/**
* Used to create a new DragLayer from XML.
*
@@ -144,7 +147,14 @@ public class DragLayer extends FrameLayout implements DragController {
if (PROFILE_DRAWING_DURING_DRAG) {
android.os.Debug.startMethodTracing("Launcher");
}
-
+
+ // Hide soft keyboard, if visible
+ if (mInputMethodManager == null) {
+ mInputMethodManager = (InputMethodManager)
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ }
+ mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
+
if (mListener != null) {
mListener.onDragStart(v, source, dragInfo, dragAction);
}
diff --git a/src/com/android/launcher/Launcher.java b/src/com/android/launcher/Launcher.java
index 58fcd5a28..e88e55ebf 100644
--- a/src/com/android/launcher/Launcher.java
+++ b/src/com/android/launcher/Launcher.java
@@ -40,6 +40,7 @@ import android.database.ContentObserver;
import android.gadget.GadgetProviderInfo;
import android.gadget.GadgetManager;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
@@ -86,6 +87,7 @@ import java.util.ArrayList;
*/
public final class Launcher extends Activity implements View.OnClickListener, OnLongClickListener {
static final String LOG_TAG = "Launcher";
+ static final boolean LOGD = false;
private static final boolean PROFILE_STARTUP = false;
private static final boolean DEBUG_USER_INTERFACE = false;
@@ -169,7 +171,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
private GadgetManager mGadgetManager;
private LauncherGadgetHost mGadgetHost;
- private static final int GADGET_HOST_ID = 1024;
+ static final int GADGET_HOST_ID = 1024;
private CellLayout.CellInfo mAddItemCellInfo;
private CellLayout.CellInfo mMenuAddInfo;
@@ -191,6 +193,8 @@ public final class Launcher extends Activity implements View.OnClickListener, On
private boolean mWaitingForResult;
private boolean mLocaleChanged;
+ private Bundle mSavedInstanceState;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -201,8 +205,6 @@ public final class Launcher extends Activity implements View.OnClickListener, On
mGadgetHost = new LauncherGadgetHost(this, GADGET_HOST_ID);
mGadgetHost.startListening();
- // TODO: figure out if this is first launch and correctly clear GadgetHost database
-
if (PROFILE_STARTUP) {
android.os.Debug.startMethodTracing("/sdcard/launcher");
}
@@ -355,15 +357,11 @@ public final class Launcher extends Activity implements View.OnClickListener, On
}
return handled;
}
+
private boolean acceptFilter() {
- final Configuration configuration = getResources().getConfiguration();
- final boolean keyboardShowing = configuration.keyboardHidden !=
- Configuration.KEYBOARDHIDDEN_YES;
- final boolean hasKeyboard = configuration.keyboard != Configuration.KEYBOARD_NOKEYS;
final InputMethodManager inputManager = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
- return (hasKeyboard && keyboardShowing) ||
- (!hasKeyboard && !inputManager.isFullscreenMode());
+ return !inputManager.isFullscreenMode();
}
@Override
@@ -633,7 +631,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
mWorkspace.getCurrentScreen(), xy[0], xy[1], false);
if (!mRestoring) {
- sModel.addDesktopItem(launcherInfo);
+ sModel.addDesktopGadget(launcherInfo);
// Perform actual inflation because we're live
launcherInfo.hostView = mGadgetHost.createView(this, gadgetId, gadgetInfo);
@@ -644,7 +642,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
mWorkspace.addInCurrentScreen(launcherInfo.hostView, xy[0], xy[1],
launcherInfo.spanX, launcherInfo.spanY, insertAtFirst);
} else if (sModel.isDesktopLoaded()) {
- sModel.addDesktopItem(launcherInfo);
+ sModel.addDesktopGadget(launcherInfo);
}
}
@@ -746,6 +744,12 @@ public final class Launcher extends Activity implements View.OnClickListener, On
}
@Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ // Do not call super here
+ mSavedInstanceState = savedInstanceState;
+ }
+
+ @Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(RUNTIME_STATE_CURRENT_SCREEN, mWorkspace.getCurrentScreen());
@@ -793,7 +797,11 @@ public final class Launcher extends Activity implements View.OnClickListener, On
super.onDestroy();
- mGadgetHost.stopListening();
+ try {
+ mGadgetHost.stopListening();
+ } catch (NullPointerException ex) {
+ Log.w(LOG_TAG, "problem while stopping GadgetHost during Launcher destruction", ex);
+ }
TextKeyListener.getInstance().release();
@@ -1156,8 +1164,8 @@ public final class Launcher extends Activity implements View.OnClickListener, On
void onDesktopItemsLoaded() {
if (mDestroyed) return;
- bindDesktopItems();
mAllAppsGrid.setAdapter(Launcher.getModel().getApplicationsAdapter());
+ bindDesktopItems();
}
/**
@@ -1165,7 +1173,8 @@ public final class Launcher extends Activity implements View.OnClickListener, On
*/
private void bindDesktopItems() {
final ArrayList<ItemInfo> shortcuts = sModel.getDesktopItems();
- if (shortcuts == null) {
+ final ArrayList<LauncherGadgetInfo> gadgets = sModel.getDesktopGadgets();
+ if (shortcuts == null || gadgets == null) {
return;
}
@@ -1187,19 +1196,17 @@ public final class Launcher extends Activity implements View.OnClickListener, On
});
}
- count = shortcuts.size();
-
- final DesktopItemsBinder binder = new DesktopItemsBinder(this, shortcuts);
- binder.obtainMessage(DesktopItemsBinder.MESSAGE_BIND_ITEMS, 0, count).sendToTarget();
+ final DesktopBinder binder = new DesktopBinder(this, shortcuts, gadgets);
+ binder.startBindingItems();
}
- private void bindItems(Launcher.DesktopItemsBinder binder,
+ private void bindItems(Launcher.DesktopBinder binder,
ArrayList<ItemInfo> shortcuts, int start, int count) {
final Workspace workspace = mWorkspace;
final boolean desktopLocked = mDesktopLocked;
- final int end = Math.min(start + DesktopItemsBinder.ITEMS_COUNT, count);
+ final int end = Math.min(start + DesktopBinder.ITEMS_COUNT, count);
int i = start;
for ( ; i < end; i++) {
@@ -1226,21 +1233,6 @@ public final class Launcher extends Activity implements View.OnClickListener, On
workspace.addInScreen(newLiveFolder, item.screen, item.cellX, item.cellY, 1, 1,
!desktopLocked);
break;
- case LauncherSettings.Favorites.ITEM_TYPE_GADGET:
- final LauncherGadgetInfo launcherInfo = (LauncherGadgetInfo) item;
-
- final int gadgetId = launcherInfo.gadgetId;
- GadgetProviderInfo gadgetInfo = mGadgetManager.getGadgetInfo(gadgetId);
- launcherInfo.hostView = mGadgetHost.createView(this, gadgetId, gadgetInfo);
-
- Log.d(LOG_TAG, "about to setGadget for id="+gadgetId+", info="+gadgetInfo);
- launcherInfo.hostView.setGadget(gadgetId, gadgetInfo);
- launcherInfo.hostView.setTag(launcherInfo);
-
- workspace.addInScreen(launcherInfo.hostView, item.screen, item.cellX,
- item.cellY, item.spanX, item.spanY, !desktopLocked);
-
- break;
case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH:
final int screen = workspace.getCurrentScreen();
final View view = mInflater.inflate(R.layout.widget_search,
@@ -1258,14 +1250,17 @@ public final class Launcher extends Activity implements View.OnClickListener, On
if (end >= count) {
finishBindDesktopItems();
+ binder.startBindingGadgets();
} else {
- binder.obtainMessage(DesktopItemsBinder.MESSAGE_BIND_ITEMS, i, count).sendToTarget();
+ binder.obtainMessage(DesktopBinder.MESSAGE_BIND_ITEMS, i, count).sendToTarget();
}
}
private void finishBindDesktopItems() {
if (mSavedState != null) {
- mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();
+ if (!mWorkspace.hasFocus()) {
+ mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();
+ }
final long[] userFolders = mSavedState.getLongArray(RUNTIME_STATE_USER_FOLDERS);
if (userFolders != null) {
@@ -1278,24 +1273,67 @@ public final class Launcher extends Activity implements View.OnClickListener, On
final Folder openFolder = mWorkspace.getOpenFolder();
if (openFolder != null) {
openFolder.requestFocus();
- } else {
- mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();
}
}
final boolean allApps = mSavedState.getBoolean(RUNTIME_STATE_ALL_APPS_FOLDER, false);
if (allApps) {
mDrawer.open();
- mDrawer.requestFocus();
}
mSavedState = null;
}
+ if (mSavedInstanceState != null) {
+ super.onRestoreInstanceState(mSavedInstanceState);
+ mSavedInstanceState = null;
+ }
+
+ if (mDrawer.isOpened() && !mDrawer.hasFocus()) {
+ mDrawer.requestFocus();
+ }
+
mDesktopLocked = false;
mDrawer.unlock();
}
+ private void bindGadgets(Launcher.DesktopBinder binder,
+ ArrayList<LauncherGadgetInfo> gadgets, int start, int count) {
+
+ final Workspace workspace = mWorkspace;
+ final boolean desktopLocked = mDesktopLocked;
+
+ final int end = Math.min(start + DesktopBinder.GADGETS_COUNT, count);
+ int i = start;
+
+ for ( ; i < end; i++) {
+ final LauncherGadgetInfo item = gadgets.get(i);
+
+ final int gadgetId = item.gadgetId;
+ final GadgetProviderInfo gadgetInfo = mGadgetManager.getGadgetInfo(gadgetId);
+ item.hostView = mGadgetHost.createView(this, gadgetId, gadgetInfo);
+
+ if (LOGD) Log.d(LOG_TAG, String.format("about to setGadget for id=%d, info=%s", gadgetId, gadgetInfo));
+
+ item.hostView.setGadget(gadgetId, gadgetInfo);
+ item.hostView.setTag(item);
+
+ workspace.addInScreen(item.hostView, item.screen, item.cellX,
+ item.cellY, item.spanX, item.spanY, !desktopLocked);
+ }
+
+ workspace.requestLayout();
+
+ if (end >= count) {
+ finishBindDesktopGadgets();
+ } else {
+ binder.obtainMessage(DesktopBinder.MESSAGE_BIND_GADGETS, i, count).sendToTarget();
+ }
+ }
+
+ private void finishBindDesktopGadgets() {
+ }
+
DragController getDragController() {
return mDragLayer;
}
@@ -1419,7 +1457,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On
// This happens when long clicking an item with the dpad/trackball
if (cellInfo == null) {
- return false;
+ return true;
}
if (mWorkspace.allowLongPress()) {
@@ -1450,6 +1488,10 @@ public final class Launcher extends Activity implements View.OnClickListener, On
return !mDrawer.isMoving() && !mDrawer.isOpened();
}
+ boolean isDrawerUp() {
+ return mDrawer.isOpened() && !mDrawer.isMoving();
+ }
+
Workspace getWorkspace() {
return mWorkspace;
}
@@ -1766,6 +1808,16 @@ public final class Launcher extends Activity implements View.OnClickListener, On
public void onDrawerOpened() {
if (!mOpen) {
mHandleIcon.reverseTransition(150);
+ final Rect bounds = mWorkspace.mDrawerBounds;
+
+ View view = mAllAppsGrid;
+ view.getDrawingRect(bounds);
+
+ while (view != mDragLayer) {
+ bounds.offset(view.getLeft(), view.getTop());
+ view = (View) view.getParent();
+ }
+
mOpen = true;
}
}
@@ -1773,41 +1825,63 @@ public final class Launcher extends Activity implements View.OnClickListener, On
public void onDrawerClosed() {
if (mOpen) {
mHandleIcon.reverseTransition(150);
+ mWorkspace.mDrawerBounds.setEmpty();
mOpen = false;
}
mAllAppsGrid.setSelection(0);
mAllAppsGrid.clearTextFilter();
- mWorkspace.clearChildrenCache();
}
public void onScrollStarted() {
- mWorkspace.enableChildrenCache();
}
public void onScrollEnded() {
}
}
- private static class DesktopItemsBinder extends Handler {
+ private static class DesktopBinder extends Handler {
static final int MESSAGE_BIND_ITEMS = 0x1;
+ static final int MESSAGE_BIND_GADGETS = 0x2;
// Number of items to bind in every pass
static final int ITEMS_COUNT = 6;
+ static final int GADGETS_COUNT = 1;
private final ArrayList<ItemInfo> mShortcuts;
+ private final ArrayList<LauncherGadgetInfo> mGadgets;
private final WeakReference<Launcher> mLauncher;
- DesktopItemsBinder(Launcher launcher, ArrayList<ItemInfo> shortcuts) {
+ DesktopBinder(Launcher launcher, ArrayList<ItemInfo> shortcuts,
+ ArrayList<LauncherGadgetInfo> gadgets) {
+
mLauncher = new WeakReference<Launcher>(launcher);
mShortcuts = shortcuts;
+ mGadgets = gadgets;
+ }
+
+ public void startBindingItems() {
+ obtainMessage(MESSAGE_BIND_ITEMS, 0, mShortcuts.size()).sendToTarget();
}
+ public void startBindingGadgets() {
+ obtainMessage(MESSAGE_BIND_GADGETS, 0, mGadgets.size()).sendToTarget();
+ }
+
@Override
public void handleMessage(Message msg) {
+ Launcher launcher = mLauncher.get();
+ if (launcher == null) {
+ return;
+ }
+
switch (msg.what) {
- case MESSAGE_BIND_ITEMS:
- Launcher launcher = mLauncher.get();
- if (launcher != null) launcher.bindItems(this, mShortcuts, msg.arg1, msg.arg2);
+ case MESSAGE_BIND_ITEMS: {
+ launcher.bindItems(this, mShortcuts, msg.arg1, msg.arg2);
+ break;
+ }
+ case MESSAGE_BIND_GADGETS: {
+ launcher.bindGadgets(this, mGadgets, msg.arg1, msg.arg2);
break;
+ }
}
}
}
diff --git a/src/com/android/launcher/LauncherGadgetHostView.java b/src/com/android/launcher/LauncherGadgetHostView.java
index dd098aac2..2b5f7f7f4 100644
--- a/src/com/android/launcher/LauncherGadgetHostView.java
+++ b/src/com/android/launcher/LauncherGadgetHostView.java
@@ -58,13 +58,13 @@ public class LauncherGadgetHostView extends GadgetHostView {
break;
}
- case MotionEvent.ACTION_UP: {
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
mHasPerformedLongPress = false;
if (mPendingCheckForLongPress != null) {
removeCallbacks(mPendingCheckForLongPress);
}
break;
- }
}
// Otherwise continue letting touch events fall through to children
diff --git a/src/com/android/launcher/LauncherModel.java b/src/com/android/launcher/LauncherModel.java
index 783eef2db..40b5402c0 100644
--- a/src/com/android/launcher/LauncherModel.java
+++ b/src/com/android/launcher/LauncherModel.java
@@ -57,6 +57,7 @@ public class LauncherModel {
private boolean mDesktopItemsLoaded;
private ArrayList<ItemInfo> mDesktopItems;
+ private ArrayList<LauncherGadgetInfo> mDesktopGadgets;
private HashMap<Long, FolderInfo> mFolders;
private ArrayList<ApplicationInfo> mApplications;
@@ -202,6 +203,7 @@ public class LauncherModel {
final ApplicationsAdapter applicationList = mApplicationList;
final int count = buffer.size();
+ applicationList.setNotifyOnChange(false);
applicationList.clear();
for (int i = 0; i < count; i++) {
applicationList.setNotifyOnChange(false);
@@ -222,7 +224,7 @@ public class LauncherModel {
}
boolean isDesktopLoaded() {
- return mDesktopItems != null && mDesktopItemsLoaded;
+ return mDesktopItems != null && mDesktopGadgets != null && mDesktopItemsLoaded;
}
/**
@@ -232,7 +234,7 @@ public class LauncherModel {
void loadUserItems(boolean isLaunching, Launcher launcher, boolean localeChanged,
boolean loadApplications) {
- if (isLaunching && mDesktopItems != null && mDesktopItemsLoaded) {
+ if (isLaunching && isDesktopLoaded()) {
if (loadApplications) startApplicationsLoader(launcher);
// We have already loaded our data from the DB
launcher.onDesktopItemsLoaded();
@@ -358,9 +360,11 @@ public class LauncherModel {
}
mDesktopItems = new ArrayList<ItemInfo>();
+ mDesktopGadgets = new ArrayList<LauncherGadgetInfo>();
mFolders = new HashMap<Long, FolderInfo>();
final ArrayList<ItemInfo> desktopItems = mDesktopItems;
+ final ArrayList<LauncherGadgetInfo> desktopGadgets = mDesktopGadgets;
final Cursor c = contentResolver.query(
LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
@@ -386,8 +390,8 @@ public class LauncherModel {
ApplicationInfo info;
String intentDescription;
- Widget widgetInfo = null;
- LauncherGadgetInfo gadgetInfo = null;
+ Widget widgetInfo;
+ LauncherGadgetInfo gadgetInfo;
int container;
long id;
Intent intent;
@@ -536,7 +540,7 @@ public class LauncherModel {
}
gadgetInfo.container = c.getInt(containerIndex);
- desktopItems.add(gadgetInfo);
+ desktopGadgets.add(gadgetInfo);
break;
}
} catch (Exception e) {
@@ -643,6 +647,7 @@ public class LauncherModel {
mApplicationsAdapter = null;
unbindAppDrawables(mApplications);
unbindDrawables(mDesktopItems);
+ unbindGadgetHostViews(mDesktopGadgets);
}
/**
@@ -658,6 +663,7 @@ public class LauncherModel {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
((ApplicationInfo)item).icon.setCallback(null);
+ break;
}
}
}
@@ -677,6 +683,19 @@ public class LauncherModel {
}
/**
+ * Remove any {@link LauncherGadgetHostView} references in our gadgets.
+ */
+ private void unbindGadgetHostViews(ArrayList<LauncherGadgetInfo> gadgets) {
+ if (gadgets != null) {
+ final int count = gadgets.size();
+ for (int i = 0; i < count; i++) {
+ LauncherGadgetInfo launcherInfo = gadgets.get(i);
+ launcherInfo.hostView = null;
+ }
+ }
+ }
+
+ /**
* @return The current list of applications
*/
public ArrayList<ApplicationInfo> getApplications() {
@@ -696,6 +715,13 @@ public class LauncherModel {
public ArrayList<ItemInfo> getDesktopItems() {
return mDesktopItems;
}
+
+ /**
+ * @return The current list of desktop items
+ */
+ public ArrayList<LauncherGadgetInfo> getDesktopGadgets() {
+ return mDesktopGadgets;
+ }
/**
* Add an item to the desktop
@@ -716,6 +742,20 @@ public class LauncherModel {
}
/**
+ * Add a gadget to the desktop
+ */
+ public void addDesktopGadget(LauncherGadgetInfo info) {
+ mDesktopGadgets.add(info);
+ }
+
+ /**
+ * Remove a gadget from the desktop
+ */
+ public void removeDesktopGadget(LauncherGadgetInfo info) {
+ mDesktopGadgets.remove(info);
+ }
+
+ /**
* Make an ApplicationInfo object for an application
*/
private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent) {
diff --git a/src/com/android/launcher/LauncherProvider.java b/src/com/android/launcher/LauncherProvider.java
index 47db647e4..539d5ae44 100644
--- a/src/com/android/launcher/LauncherProvider.java
+++ b/src/com/android/launcher/LauncherProvider.java
@@ -30,6 +30,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.database.Cursor;
import android.database.SQLException;
+import android.gadget.GadgetHost;
import android.util.Log;
import android.util.Xml;
import android.net.Uri;
@@ -41,19 +42,25 @@ import java.io.FileReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.ArrayList;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import com.android.internal.util.XmlUtils;
+import com.android.launcher.LauncherSettings.Favorites;
public class LauncherProvider extends ContentProvider {
- private static final String LOG_TAG = "LauncherSettingsProvider";
+ private static final String LOG_TAG = "LauncherProvider";
+ private static final boolean LOGD = true;
private static final String DATABASE_NAME = "launcher.db";
private static final int DATABASE_VERSION = 2;
static final String AUTHORITY = "com.android.launcher.settings";
+
+ static final String EXTRA_BIND_SOURCES = "com.android.launcher.settings.bindsources";
+ static final String EXTRA_BIND_TARGETS = "com.android.launcher.settings.bindtargets";
static final String TABLE_FAVORITES = "favorites";
static final String PARAMETER_NOTIFY = "notify";
@@ -170,14 +177,18 @@ public class LauncherProvider extends ContentProvider {
private static final String ATTRIBUTE_Y = "y";
private final Context mContext;
+ private final GadgetHost mGadgetHost;
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
+ mGadgetHost = new GadgetHost(context, Launcher.GADGET_HOST_ID);
}
@Override
public void onCreate(SQLiteDatabase db) {
+ if (LOGD) Log.d(LOG_TAG, "creating new launcher database");
+
db.execSQL("CREATE TABLE favorites (" +
"_id INTEGER PRIMARY KEY," +
"title TEXT," +
@@ -199,11 +210,11 @@ public class LauncherProvider extends ContentProvider {
"displayMode INTEGER" +
");");
- // TODO: During first database creation, trigger wipe of any gadgets that
- // might have been left around during a wipe-data.
-// GadgetManager gadgetManager = GadgetManager.getInstance(mContext);
-
-
+ // Database was just created, so wipe any previous gadgets
+ if (mGadgetHost != null) {
+ mGadgetHost.deleteHost();
+ }
+
if (!convertDatabase(db)) {
// Populate favorites table with initial favorites
loadFavorites(db, DEFAULT_FAVORITES_PATH);
@@ -211,6 +222,7 @@ public class LauncherProvider extends ContentProvider {
}
private boolean convertDatabase(SQLiteDatabase db) {
+ if (LOGD) Log.d(LOG_TAG, "converting database from an older format, but not onUpgrade");
boolean converted = false;
final Uri uri = Uri.parse("content://" + Settings.AUTHORITY +
@@ -236,6 +248,12 @@ public class LauncherProvider extends ContentProvider {
resolver.delete(uri, null, null);
}
}
+
+ if (converted) {
+ // Convert widgets from this import into gadgets
+ if (LOGD) Log.d(LOG_TAG, "converted and now triggering widget upgrade");
+ convertWidgets(db);
+ }
return converted;
}
@@ -299,16 +317,16 @@ public class LauncherProvider extends ContentProvider {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (LOGD) Log.d(LOG_TAG, "onUpgrade triggered");
+
int version = oldVersion;
if (version == 1) {
// upgrade 1 -> 2 added gadgetId column
db.beginTransaction();
try {
- // TODO: convert any existing widgets for search and clock
- // this might involve a FORCE_ADD_GADGET permission in GadgetManager that
- // Launcher could then use to add these gadgets without user interaction
+ // Insert new column for holding gadgetIds
db.execSQL("ALTER TABLE favorites " +
- "ADD COLUMN gadgetId INTEGER NOT NULL DEFAULT -1;");
+ "ADD COLUMN gadgetId INTEGER NOT NULL DEFAULT -1;");
db.setTransactionSuccessful();
version = 2;
} catch (SQLException ex) {
@@ -317,6 +335,11 @@ public class LauncherProvider extends ContentProvider {
} finally {
db.endTransaction();
}
+
+ // Convert existing widgets only if table upgrade was successful
+ if (version == 2) {
+ convertWidgets(db);
+ }
}
if (version != DATABASE_VERSION) {
@@ -325,8 +348,99 @@ public class LauncherProvider extends ContentProvider {
onCreate(db);
}
}
+
+ /**
+ * Upgrade existing clock and photo frame widgets into their new gadget
+ * equivalents. This method allocates gadgetIds, and then hands off to
+ * LauncherGadgetBinder to finish the actual binding.
+ */
+ private void convertWidgets(SQLiteDatabase db) {
+ final int[] bindSources = new int[] {
+ Favorites.ITEM_TYPE_WIDGET_CLOCK,
+ Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME,
+ };
+
+ final ArrayList<ComponentName> bindTargets = new ArrayList<ComponentName>();
+ bindTargets.add(new ComponentName("com.android.alarmclock",
+ "com.android.alarmclock.AnalogGadgetProvider"));
+ bindTargets.add(new ComponentName("com.android.camera",
+ "com.android.camera.PhotoGadgetProvider"));
+
+ final String selectWhere = buildOrWhereString(Favorites.ITEM_TYPE, bindSources);
+
+ Cursor c = null;
+ boolean allocatedGadgets = false;
+
+ db.beginTransaction();
+ try {
+ // Select and iterate through each matching widget
+ c = db.query(TABLE_FAVORITES, new String[] { Favorites._ID },
+ selectWhere, null, null, null, null);
+
+ if (LOGD) Log.d(LOG_TAG, "found upgrade cursor count="+c.getCount());
+
+ final ContentValues values = new ContentValues();
+ while (c != null && c.moveToNext()) {
+ long favoriteId = c.getLong(0);
+
+ // Allocate and update database with new gadgetId
+ try {
+ int gadgetId = mGadgetHost.allocateGadgetId();
+
+ if (LOGD) Log.d(LOG_TAG, "allocated gadgetId="+gadgetId+" for favoriteId="+favoriteId);
+
+ values.clear();
+ values.put(LauncherSettings.Favorites.GADGET_ID, gadgetId);
+
+ // Original widgets might not have valid spans when upgrading
+ values.put(LauncherSettings.Favorites.SPANX, 2);
+ values.put(LauncherSettings.Favorites.SPANY, 2);
+
+ String updateWhere = Favorites._ID + "=" + favoriteId;
+ db.update(TABLE_FAVORITES, values, updateWhere, null);
+
+ allocatedGadgets = true;
+ } catch (RuntimeException ex) {
+ Log.e(LOG_TAG, "Problem allocating gadgetId", ex);
+ }
+ }
+
+ db.setTransactionSuccessful();
+ } catch (SQLException ex) {
+ Log.w(LOG_TAG, "Problem while allocating gadgetIds for existing widgets", ex);
+ } finally {
+ db.endTransaction();
+ if (c != null) {
+ c.close();
+ }
+ }
+
+ // If any gadgetIds allocated, then launch over to binder
+ if (allocatedGadgets) {
+ launchGadgetBinder(bindSources, bindTargets);
+ }
+ }
-
+ /**
+ * Launch the gadget binder that walks through the Launcher database,
+ * binding any matching widgets to the corresponding targets. We can't
+ * bind ourselves because our parent process can't obtain the
+ * BIND_GADGET permission.
+ */
+ private void launchGadgetBinder(int[] bindSources, ArrayList<ComponentName> bindTargets) {
+ final Intent intent = new Intent();
+ intent.setComponent(new ComponentName("com.android.settings",
+ "com.android.settings.LauncherGadgetBinder"));
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ final Bundle extras = new Bundle();
+ extras.putIntArray(EXTRA_BIND_SOURCES, bindSources);
+ extras.putParcelableArrayList(EXTRA_BIND_TARGETS, bindTargets);
+ intent.putExtras(extras);
+
+ mContext.startActivity(intent);
+ }
+
/**
* Loads the default set of favorite packages from an xml file.
*
@@ -413,13 +527,62 @@ public class LauncherProvider extends ContentProvider {
values.put(LauncherSettings.Favorites.SPANY, 1);
db.insert(TABLE_FAVORITES, null, values);
- // TODO: automatically add clock and search gadget to
- // default locations. this might need the FORCE permission mentioned above
+ final int[] bindSources = new int[] {
+ Favorites.ITEM_TYPE_WIDGET_CLOCK,
+ };
+
+ final ArrayList<ComponentName> bindTargets = new ArrayList<ComponentName>();
+ bindTargets.add(new ComponentName("com.android.alarmclock",
+ "com.android.alarmclock.AnalogGadgetProvider"));
+
+ boolean allocatedGadgets = false;
+
+ // Try binding to an analog clock gadget
+ try {
+ int gadgetId = mGadgetHost.allocateGadgetId();
+
+ values.clear();
+ values.put(LauncherSettings.Favorites.CONTAINER,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP);
+ values.put(LauncherSettings.Favorites.ITEM_TYPE,
+ LauncherSettings.Favorites.ITEM_TYPE_WIDGET_CLOCK);
+ values.put(LauncherSettings.Favorites.SCREEN, 1);
+ values.put(LauncherSettings.Favorites.CELLX, 1);
+ values.put(LauncherSettings.Favorites.CELLY, 0);
+ values.put(LauncherSettings.Favorites.SPANX, 2);
+ values.put(LauncherSettings.Favorites.SPANY, 2);
+ values.put(LauncherSettings.Favorites.GADGET_ID, gadgetId);
+ db.insert(TABLE_FAVORITES, null, values);
+
+ allocatedGadgets = true;
+ } catch (RuntimeException ex) {
+ Log.e(LOG_TAG, "Problem allocating gadgetId", ex);
+ }
+ // If any gadgetIds allocated, then launch over to binder
+ if (allocatedGadgets) {
+ launchGadgetBinder(bindSources, bindTargets);
+ }
+
return i;
}
}
+ /**
+ * Build a query string that will match any row where the column matches
+ * anything in the values list.
+ */
+ static String buildOrWhereString(String column, int[] values) {
+ StringBuilder selectWhere = new StringBuilder();
+ for (int i = values.length - 1; i >= 0; i--) {
+ selectWhere.append(column).append("=").append(values[i]);
+ if (i > 0) {
+ selectWhere.append(" OR ");
+ }
+ }
+ return selectWhere.toString();
+ }
+
static class SqlArguments {
public final String table;
public final String where;
diff --git a/src/com/android/launcher/LauncherSettings.java b/src/com/android/launcher/LauncherSettings.java
index 77bdc73fe..461cca4fe 100644
--- a/src/com/android/launcher/LauncherSettings.java
+++ b/src/com/android/launcher/LauncherSettings.java
@@ -24,7 +24,8 @@ import android.net.Uri;
*/
class LauncherSettings {
/**
- * Favorites.
+ * Favorites. When changing these values, be sure to update
+ * {@link com.android.settings.LauncherGadgetBinder} as needed.
*/
static final class Favorites implements BaseColumns {
/**
diff --git a/src/com/android/launcher/LiveFolder.java b/src/com/android/launcher/LiveFolder.java
index 37b98e0f7..5d727f830 100644
--- a/src/com/android/launcher/LiveFolder.java
+++ b/src/com/android/launcher/LiveFolder.java
@@ -24,8 +24,14 @@ import android.view.View;
import android.widget.AdapterView;
import android.net.Uri;
import android.provider.LiveFolders;
+import android.os.AsyncTask;
+import android.database.Cursor;
+
+import java.lang.ref.WeakReference;
public class LiveFolder extends Folder {
+ private AsyncTask<LiveFolderInfo,Void,Cursor> mLoadingTask;
+
public LiveFolder(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -66,7 +72,10 @@ public class LiveFolder extends Folder {
void bind(FolderInfo info) {
super.bind(info);
- setContentAdapter(new LiveFolderAdapter(mLauncher, (LiveFolderInfo) info));
+ if (mLoadingTask != null && mLoadingTask.getStatus() == AsyncTask.Status.RUNNING) {
+ mLoadingTask.cancel(true);
+ }
+ mLoadingTask = new FolderLoadingTask(this).execute((LiveFolderInfo) info);
}
@Override
@@ -78,6 +87,42 @@ public class LiveFolder extends Folder {
@Override
void onClose() {
super.onClose();
+ if (mLoadingTask != null && mLoadingTask.getStatus() == AsyncTask.Status.RUNNING) {
+ mLoadingTask.cancel(true);
+ }
((LiveFolderAdapter) mContent.getAdapter()).cleanup();
}
+
+ static class FolderLoadingTask extends AsyncTask<LiveFolderInfo, Void, Cursor> {
+ private final WeakReference<LiveFolder> mFolder;
+ private LiveFolderInfo mInfo;
+
+ FolderLoadingTask(LiveFolder folder) {
+ mFolder = new WeakReference<LiveFolder>(folder);
+ }
+
+ protected Cursor doInBackground(LiveFolderInfo... params) {
+ final LiveFolder folder = mFolder.get();
+ if (folder != null) {
+ mInfo = params[0];
+ return LiveFolderAdapter.query(folder.mLauncher, mInfo);
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Cursor cursor) {
+ if (!isCancelled()) {
+ if (cursor != null) {
+ final LiveFolder folder = mFolder.get();
+ if (folder != null) {
+ final Launcher launcher = folder.mLauncher;
+ folder.setContentAdapter(new LiveFolderAdapter(launcher, mInfo, cursor));
+ }
+ }
+ } else if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
}
diff --git a/src/com/android/launcher/LiveFolderAdapter.java b/src/com/android/launcher/LiveFolderAdapter.java
index 71ed85d34..4a5c077c8 100644
--- a/src/com/android/launcher/LiveFolderAdapter.java
+++ b/src/com/android/launcher/LiveFolderAdapter.java
@@ -45,8 +45,8 @@ class LiveFolderAdapter extends CursorAdapter {
new HashMap<Long, SoftReference<Drawable>>();
private final Launcher mLauncher;
- LiveFolderAdapter(Launcher launcher, LiveFolderInfo info) {
- super(launcher, query(launcher, info), true);
+ LiveFolderAdapter(Launcher launcher, LiveFolderInfo info, Cursor cursor) {
+ super(launcher, cursor, true);
mIsList = info.displayMode == LiveFolders.DISPLAY_MODE_LIST;
mInflater = LayoutInflater.from(launcher);
mLauncher = launcher;
@@ -54,8 +54,9 @@ class LiveFolderAdapter extends CursorAdapter {
mLauncher.startManagingCursor(getCursor());
}
- private static Cursor query(Context context, LiveFolderInfo info) {
- return context.getContentResolver().query(info.uri, null, null, null, LiveFolders.NAME + " ASC");
+ static Cursor query(Context context, LiveFolderInfo info) {
+ return context.getContentResolver().query(info.uri, null, null,
+ null, LiveFolders.NAME + " ASC");
}
public View newView(Context context, Cursor cursor, ViewGroup parent) {
diff --git a/src/com/android/launcher/Search.java b/src/com/android/launcher/Search.java
index d33fd69fa..522a43262 100644
--- a/src/com/android/launcher/Search.java
+++ b/src/com/android/launcher/Search.java
@@ -57,8 +57,6 @@ import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
-import java.util.List;
-
public class Search extends LinearLayout implements OnClickListener, OnKeyListener,
OnLongClickListener, TextWatcher, OnItemClickListener, OnItemSelectedListener {
@@ -81,6 +79,7 @@ public class Search extends LinearLayout implements OnClickListener, OnKeyListen
private Intent mVoiceSearchIntent;
private Rect mTempRect = new Rect();
+ private boolean mRestoreFocus = false;
/**
* Used to inflate the Workspace from XML.
@@ -170,7 +169,26 @@ public class Search extends LinearLayout implements OnClickListener, OnKeyListen
getContext().startActivity(launcher);
}
-
+
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ if (!hasWindowFocus && hasFocus()) {
+ mRestoreFocus = true;
+ }
+
+ super.onWindowFocusChanged(hasWindowFocus);
+
+ if (hasWindowFocus && mRestoreFocus) {
+ if (isInTouchMode()) {
+ final AutoCompleteTextView searchText = mSearchText;
+ searchText.setSelectAllOnFocus(false);
+ searchText.requestFocusFromTouch();
+ searchText.setSelectAllOnFocus(true);
+ }
+ mRestoreFocus = false;
+ }
+ }
+
/**
* Implements TextWatcher (for EditText)
*/
@@ -371,6 +389,18 @@ public class Search extends LinearLayout implements OnClickListener, OnKeyListen
}
/**
+ * Remove internal cursor references when detaching from window which
+ * prevents {@link Context} leaks.
+ */
+ @Override
+ public void onDetachedFromWindow() {
+ if (mSuggestionsAdapter != null) {
+ mSuggestionsAdapter.changeCursor(null);
+ mSuggestionsAdapter = null;
+ }
+ }
+
+ /**
* Implements OnItemClickListener
*/
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
diff --git a/src/com/android/launcher/SearchAutoCompleteTextView.java b/src/com/android/launcher/SearchAutoCompleteTextView.java
new file mode 100644
index 000000000..18a464a5c
--- /dev/null
+++ b/src/com/android/launcher/SearchAutoCompleteTextView.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher;
+
+import android.widget.AutoCompleteTextView;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.graphics.Rect;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+import android.app.Activity;
+
+/**
+ * This class is not for the faint of heart. Home works in the pan & scan
+ * soft input mode. However, this mode gets rid of the soft keyboard on rotation,
+ * which is a probelm when the Search widget has focus. This special class
+ * changes Home's soft input method temporarily as long as the Search widget holds
+ * the focus. This way, the soft keyboard remains after rotation.
+ */
+public class SearchAutoCompleteTextView extends AutoCompleteTextView {
+ public SearchAutoCompleteTextView(Context context) {
+ super(context);
+ }
+
+ public SearchAutoCompleteTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SearchAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
+ super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+
+ final WindowManager.LayoutParams lp = ((Activity) getContext()).getWindow().getAttributes();
+ if (gainFocus) {
+ lp.softInputMode =
+ (lp.softInputMode & ~WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) |
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
+ } else {
+ //noinspection PointlessBitwiseExpression
+ lp.softInputMode =
+ (lp.softInputMode & ~WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) |
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED;
+
+ // Hide the soft keyboard when the search widget loses the focus
+ InputMethodManager.peekInstance().hideSoftInputFromWindow(getWindowToken(), 0);
+ }
+
+ final WindowManager manager = (WindowManager)
+ getContext().getSystemService(Context.WINDOW_SERVICE);
+ manager.updateViewLayout(getRootView(), lp);
+ }
+}
diff --git a/src/com/android/launcher/Workspace.java b/src/com/android/launcher/Workspace.java
index 6d8eef5f1..d93fe1436 100644
--- a/src/com/android/launcher/Workspace.java
+++ b/src/com/android/launcher/Workspace.java
@@ -17,6 +17,8 @@
package com.android.launcher;
import android.content.Context;
+import android.content.Intent;
+import android.content.ComponentName;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -91,6 +93,9 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
private int mTouchSlop;
+ final Rect mDrawerBounds = new Rect();
+ final Rect mClipBounds = new Rect();
+
/**
* Used to inflate the Workspace from XML.
*
@@ -437,6 +442,18 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
@Override
protected void dispatchDraw(Canvas canvas) {
+ // If the all apps drawer is open and the drawing region for the workspace
+ // is contained within the drawer's bounds, we skip the drawing. This requires
+ // the drawer to be fully opaque.
+ if (mLauncher.isDrawerUp()) {
+ final Rect clipBounds = mClipBounds;
+ canvas.getClipBounds(clipBounds);
+ clipBounds.offset(-mScrollX, -mScrollY);
+ if (mDrawerBounds.contains(clipBounds)) {
+ return;
+ }
+ }
+
float x = mScrollX * mWallpaperOffset;
if (x + mWallpaperWidth < mRight - mLeft) {
x = mRight - mLeft - mWallpaperWidth;
@@ -673,6 +690,7 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
// Release the drag
clearChildrenCache();
mTouchState = TOUCH_STATE_REST;
+ mAllowLongPress = false;
break;
}
@@ -1152,7 +1170,13 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
Object tag = view.getTag();
if (tag instanceof ApplicationInfo) {
ApplicationInfo info = (ApplicationInfo) tag;
- if (packageName.equals(info.intent.getComponent().getPackageName())) {
+ // We need to check for ACTION_MAIN otherwise getComponent() might
+ // return null for some shortcuts (for instance, for shortcuts to
+ // web pages.)
+ final Intent intent = info.intent;
+ final ComponentName name = intent.getComponent();
+ if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
+ name != null && packageName.equals(name.getPackageName())) {
model.removeDesktopItem(info);
LauncherModel.deleteItemFromDatabase(mLauncher, info);
childrenToRemove.add(view);