Reconcile with gingerbread-release honeycomb-release honeycomb-mr1-release

Change-Id: I91591a34a635eab5a75caa9841fff830987c85be
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 444dbd8..f78a1b2 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -45,7 +45,9 @@
 #$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
 
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher2_intermediates)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
-# ************************************************
\ No newline at end of file
+# ************************************************
diff --git a/proguard.flags b/proguard.flags
index 699f23e..c2b2c65 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -20,6 +20,28 @@
   public void setHoverAlpha(float);
 }
 
+-keep class com.android.launcher2.DragLayer$LayoutParams {
+  public void setWidth(int);
+  public int getWidth();
+  public void setHeight(int);
+  public int getHeight();
+  public void setX(int);
+  public int getX();
+  public void setY(int);
+  public int getY();
+}
+
+-keep class com.android.launcher2.CellLayout$LayoutParams {
+  public void setWidth(int);
+  public int getWidth();
+  public void setHeight(int);
+  public int getHeight();
+  public void setX(int);
+  public int getX();
+  public void setY(int);
+  public int getY();
+}
+
 -keep class com.android.launcher2.Workspace {
   public float getBackgroundAlpha();
   public void setBackgroundAlpha(float);
diff --git a/res/anim/all_apps_2d_fade_in.xml b/res/anim/all_apps_2d_fade_in.xml
index 0f1e4f4..9d2171a 100644
--- a/res/anim/all_apps_2d_fade_in.xml
+++ b/res/anim/all_apps_2d_fade_in.xml
@@ -20,4 +20,4 @@
     android:fromAlpha="0.0"
     android:toAlpha="1.0"
 
-    android:duration="@integer/config_allAppsFadeInTime" />
+    android:duration="@integer/config_appsCustomizeFadeInTime" />
diff --git a/res/anim/all_apps_2d_fade_out.xml b/res/anim/all_apps_2d_fade_out.xml
index cc47691..90520c7 100644
--- a/res/anim/all_apps_2d_fade_out.xml
+++ b/res/anim/all_apps_2d_fade_out.xml
@@ -20,4 +20,4 @@
     android:fromAlpha="1.0"
     android:toAlpha="0.0"
 
-    android:duration="@integer/config_allAppsFadeOutTime" />
+    android:duration="@integer/config_appsCustomizeFadeOutTime" />
diff --git a/res/anim/fade_in_slow.xml b/res/anim/fade_in_slow.xml
index 0f1e4f4..9d2171a 100644
--- a/res/anim/fade_in_slow.xml
+++ b/res/anim/fade_in_slow.xml
@@ -20,4 +20,4 @@
     android:fromAlpha="0.0"
     android:toAlpha="1.0"
 
-    android:duration="@integer/config_allAppsFadeInTime" />
+    android:duration="@integer/config_appsCustomizeFadeInTime" />
diff --git a/res/anim/fade_out_slow.xml b/res/anim/fade_out_slow.xml
index cc47691..90520c7 100644
--- a/res/anim/fade_out_slow.xml
+++ b/res/anim/fade_out_slow.xml
@@ -20,4 +20,4 @@
     android:fromAlpha="1.0"
     android:toAlpha="0.0"
 
-    android:duration="@integer/config_allAppsFadeOutTime" />
+    android:duration="@integer/config_appsCustomizeFadeOutTime" />
diff --git a/res/drawable-hdpi/box_launcher_top_normal.9.png b/res/drawable-hdpi/box_launcher_top_normal.9.png
index 98997ad..af04b07 100644
--- a/res/drawable-hdpi/box_launcher_top_normal.9.png
+++ b/res/drawable-hdpi/box_launcher_top_normal.9.png
Binary files differ
diff --git a/res/drawable-hdpi/box_launcher_top_pressed.9.png b/res/drawable-hdpi/box_launcher_top_pressed.9.png
index f52fd48..af04b07 100644
--- a/res/drawable-hdpi/box_launcher_top_pressed.9.png
+++ b/res/drawable-hdpi/box_launcher_top_pressed.9.png
Binary files differ
diff --git a/res/drawable-hdpi/box_launcher_top_selected.9.png b/res/drawable-hdpi/box_launcher_top_selected.9.png
index 8cacf0e..af04b07 100644
--- a/res/drawable-hdpi/box_launcher_top_selected.9.png
+++ b/res/drawable-hdpi/box_launcher_top_selected.9.png
Binary files differ
diff --git a/res/drawable-hdpi/focused_bg.9.png b/res/drawable-hdpi/focused_bg.9.png
new file mode 100644
index 0000000..1b0d3fa
--- /dev/null
+++ b/res/drawable-hdpi/focused_bg.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/home_press.9.png b/res/drawable-hdpi/home_press.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/home_press.9.png
rename to res/drawable-hdpi/home_press.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/ic_home_delete_holo_dark.png b/res/drawable-hdpi/ic_home_delete_holo_dark.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/ic_home_delete_holo_dark.png
rename to res/drawable-hdpi/ic_home_delete_holo_dark.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/ic_home_delete_hover_holo_dark.png b/res/drawable-hdpi/ic_home_delete_hover_holo_dark.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/ic_home_delete_hover_holo_dark.png
rename to res/drawable-hdpi/ic_home_delete_hover_holo_dark.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/ic_home_info_holo_dark.png b/res/drawable-hdpi/ic_home_info_holo_dark.png
similarity index 100%
copy from res/drawable-xlarge-hdpi/ic_home_info_holo_dark.png
copy to res/drawable-hdpi/ic_home_info_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_container_holo.9.png b/res/drawable-hdpi/portal_container_holo.9.png
new file mode 100644
index 0000000..af2fa98
--- /dev/null
+++ b/res/drawable-hdpi/portal_container_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_inner_holo.png b/res/drawable-hdpi/portal_ring_inner_holo.png
new file mode 100644
index 0000000..8a9e85b
--- /dev/null
+++ b/res/drawable-hdpi/portal_ring_inner_holo.png
Binary files differ
diff --git a/res/drawable-hdpi/portal_ring_outer_holo.png b/res/drawable-hdpi/portal_ring_outer_holo.png
new file mode 100644
index 0000000..5b46419
--- /dev/null
+++ b/res/drawable-hdpi/portal_ring_outer_holo.png
Binary files differ
diff --git a/res/drawable-hdpi/wallpaper_divider.png b/res/drawable-hdpi/wallpaper_divider.png
new file mode 100644
index 0000000..2f92d60
--- /dev/null
+++ b/res/drawable-hdpi/wallpaper_divider.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_frame_holo.9.png b/res/drawable-hdpi/widget_resize_frame_holo.9.png
new file mode 100644
index 0000000..8da665b
--- /dev/null
+++ b/res/drawable-hdpi/widget_resize_frame_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_handle_bottom.png b/res/drawable-hdpi/widget_resize_handle_bottom.png
new file mode 100644
index 0000000..495476b
--- /dev/null
+++ b/res/drawable-hdpi/widget_resize_handle_bottom.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_handle_left.png b/res/drawable-hdpi/widget_resize_handle_left.png
new file mode 100644
index 0000000..c73cf0e
--- /dev/null
+++ b/res/drawable-hdpi/widget_resize_handle_left.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_handle_right.png b/res/drawable-hdpi/widget_resize_handle_right.png
new file mode 100644
index 0000000..9532302
--- /dev/null
+++ b/res/drawable-hdpi/widget_resize_handle_right.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_resize_handle_top.png b/res/drawable-hdpi/widget_resize_handle_top.png
new file mode 100644
index 0000000..a3d2f7c
--- /dev/null
+++ b/res/drawable-hdpi/widget_resize_handle_top.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/app_market_generic.png b/res/drawable-large-hdpi/app_market_generic.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/app_market_generic.png
rename to res/drawable-large-hdpi/app_market_generic.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/divider_launcher_holo.9.png b/res/drawable-large-hdpi/divider_launcher_holo.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/divider_launcher_holo.9.png
rename to res/drawable-large-hdpi/divider_launcher_holo.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/homescreen_large_blue.9.png b/res/drawable-large-hdpi/homescreen_large_blue.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/homescreen_large_blue.9.png
rename to res/drawable-large-hdpi/homescreen_large_blue.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/homescreen_large_blue_strong.9.png b/res/drawable-large-hdpi/homescreen_large_blue_strong.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/homescreen_large_blue_strong.9.png
rename to res/drawable-large-hdpi/homescreen_large_blue_strong.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/homescreen_large_green.9.png b/res/drawable-large-hdpi/homescreen_large_green.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/homescreen_large_green.9.png
rename to res/drawable-large-hdpi/homescreen_large_green.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/homescreen_large_green_strong.9.png b/res/drawable-large-hdpi/homescreen_large_green_strong.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/homescreen_large_green_strong.9.png
rename to res/drawable-large-hdpi/homescreen_large_green_strong.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/homescreen_small_blue.9.png b/res/drawable-large-hdpi/homescreen_small_blue.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/homescreen_small_blue.9.png
rename to res/drawable-large-hdpi/homescreen_small_blue.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/homescreen_small_blue_strong.9.png b/res/drawable-large-hdpi/homescreen_small_blue_strong.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/homescreen_small_blue_strong.9.png
rename to res/drawable-large-hdpi/homescreen_small_blue_strong.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/homescreen_small_green.9.png b/res/drawable-large-hdpi/homescreen_small_green.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/homescreen_small_green.9.png
rename to res/drawable-large-hdpi/homescreen_small_green.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/homescreen_small_green_strong.9.png b/res/drawable-large-hdpi/homescreen_small_green_strong.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/homescreen_small_green_strong.9.png
rename to res/drawable-large-hdpi/homescreen_small_green_strong.9.png
Binary files differ
diff --git a/res/drawable-large-hdpi/ic_generic_search.png b/res/drawable-large-hdpi/ic_generic_search.png
new file mode 100644
index 0000000..67bac5c
--- /dev/null
+++ b/res/drawable-large-hdpi/ic_generic_search.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/ic_home_all_apps_holo_dark.png b/res/drawable-large-hdpi/ic_home_all_apps_holo_dark.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/ic_home_all_apps_holo_dark.png
rename to res/drawable-large-hdpi/ic_home_all_apps_holo_dark.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/ic_home_info_holo_dark.png b/res/drawable-large-hdpi/ic_home_info_holo_dark.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/ic_home_info_holo_dark.png
rename to res/drawable-large-hdpi/ic_home_info_holo_dark.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/ic_no_applications.png b/res/drawable-large-hdpi/ic_no_applications.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/ic_no_applications.png
rename to res/drawable-large-hdpi/ic_no_applications.png
Binary files differ
diff --git a/res/drawable-large-hdpi/ic_voice_search.png b/res/drawable-large-hdpi/ic_voice_search.png
new file mode 100644
index 0000000..5d2f341
--- /dev/null
+++ b/res/drawable-large-hdpi/ic_voice_search.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/tab_selected_focused_holo.9.png b/res/drawable-large-hdpi/tab_selected_focused_holo.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/tab_selected_focused_holo.9.png
rename to res/drawable-large-hdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/tab_selected_holo.9.png b/res/drawable-large-hdpi/tab_selected_holo.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/tab_selected_holo.9.png
rename to res/drawable-large-hdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/tab_selected_pressed_focused_holo.9.png b/res/drawable-large-hdpi/tab_selected_pressed_focused_holo.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/tab_selected_pressed_focused_holo.9.png
rename to res/drawable-large-hdpi/tab_selected_pressed_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/tab_selected_pressed_holo.9.png b/res/drawable-large-hdpi/tab_selected_pressed_holo.9.png
similarity index 100%
rename from res/drawable-xlarge-hdpi/tab_selected_pressed_holo.9.png
rename to res/drawable-large-hdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable-large-hdpi/widget_resize_frame_holo.9.png b/res/drawable-large-hdpi/widget_resize_frame_holo.9.png
new file mode 100644
index 0000000..7d16d7d
--- /dev/null
+++ b/res/drawable-large-hdpi/widget_resize_frame_holo.9.png
Binary files differ
diff --git a/res/drawable-large-hdpi/widget_resize_handle_bottom.png b/res/drawable-large-hdpi/widget_resize_handle_bottom.png
new file mode 100644
index 0000000..045c15e
--- /dev/null
+++ b/res/drawable-large-hdpi/widget_resize_handle_bottom.png
Binary files differ
diff --git a/res/drawable-large-hdpi/widget_resize_handle_left.png b/res/drawable-large-hdpi/widget_resize_handle_left.png
new file mode 100644
index 0000000..f0fc4d6
--- /dev/null
+++ b/res/drawable-large-hdpi/widget_resize_handle_left.png
Binary files differ
diff --git a/res/drawable-large-hdpi/widget_resize_handle_right.png b/res/drawable-large-hdpi/widget_resize_handle_right.png
new file mode 100644
index 0000000..9c1f366
--- /dev/null
+++ b/res/drawable-large-hdpi/widget_resize_handle_right.png
Binary files differ
diff --git a/res/drawable-large-hdpi/widget_resize_handle_top.png b/res/drawable-large-hdpi/widget_resize_handle_top.png
new file mode 100644
index 0000000..f7839ed
--- /dev/null
+++ b/res/drawable-large-hdpi/widget_resize_handle_top.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/app_market_generic.png b/res/drawable-large-mdpi/app_market_generic.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/app_market_generic.png
rename to res/drawable-large-mdpi/app_market_generic.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/divider_launcher_holo.9.png b/res/drawable-large-mdpi/divider_launcher_holo.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/divider_launcher_holo.9.png
rename to res/drawable-large-mdpi/divider_launcher_holo.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/homescreen_large_blue.9.png b/res/drawable-large-mdpi/homescreen_large_blue.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/homescreen_large_blue.9.png
rename to res/drawable-large-mdpi/homescreen_large_blue.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/homescreen_large_green.9.png b/res/drawable-large-mdpi/homescreen_large_green.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/homescreen_large_green.9.png
rename to res/drawable-large-mdpi/homescreen_large_green.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/homescreen_large_green_strong.9.png b/res/drawable-large-mdpi/homescreen_large_green_strong.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/homescreen_large_green_strong.9.png
rename to res/drawable-large-mdpi/homescreen_large_green_strong.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/homescreen_small_blue.9.png b/res/drawable-large-mdpi/homescreen_small_blue.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/homescreen_small_blue.9.png
rename to res/drawable-large-mdpi/homescreen_small_blue.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/homescreen_small_blue_strong.9.png b/res/drawable-large-mdpi/homescreen_small_blue_strong.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/homescreen_small_blue_strong.9.png
rename to res/drawable-large-mdpi/homescreen_small_blue_strong.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/homescreen_small_green.9.png b/res/drawable-large-mdpi/homescreen_small_green.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/homescreen_small_green.9.png
rename to res/drawable-large-mdpi/homescreen_small_green.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/homescreen_small_green_strong.9.png b/res/drawable-large-mdpi/homescreen_small_green_strong.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/homescreen_small_green_strong.9.png
rename to res/drawable-large-mdpi/homescreen_small_green_strong.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/ic_generic_search.png b/res/drawable-large-mdpi/ic_generic_search.png
new file mode 100644
index 0000000..e3fd5a2
--- /dev/null
+++ b/res/drawable-large-mdpi/ic_generic_search.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/ic_home_add_holo_dark.png b/res/drawable-large-mdpi/ic_home_add_holo_dark.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/ic_home_add_holo_dark.png
rename to res/drawable-large-mdpi/ic_home_add_holo_dark.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/ic_home_all_apps_holo_dark.png b/res/drawable-large-mdpi/ic_home_all_apps_holo_dark.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/ic_home_all_apps_holo_dark.png
rename to res/drawable-large-mdpi/ic_home_all_apps_holo_dark.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/ic_no_applications.png b/res/drawable-large-mdpi/ic_no_applications.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/ic_no_applications.png
rename to res/drawable-large-mdpi/ic_no_applications.png
Binary files differ
diff --git a/res/drawable-large-mdpi/ic_voice_search.png b/res/drawable-large-mdpi/ic_voice_search.png
new file mode 100644
index 0000000..3c52e2a
--- /dev/null
+++ b/res/drawable-large-mdpi/ic_voice_search.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/tab_selected_focused_holo.9.png b/res/drawable-large-mdpi/tab_selected_focused_holo.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/tab_selected_focused_holo.9.png
rename to res/drawable-large-mdpi/tab_selected_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/tab_selected_holo.9.png b/res/drawable-large-mdpi/tab_selected_holo.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/tab_selected_holo.9.png
rename to res/drawable-large-mdpi/tab_selected_holo.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/tab_selected_pressed_focused_holo.9.png b/res/drawable-large-mdpi/tab_selected_pressed_focused_holo.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/tab_selected_pressed_focused_holo.9.png
rename to res/drawable-large-mdpi/tab_selected_pressed_focused_holo.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/tab_selected_pressed_holo.9.png b/res/drawable-large-mdpi/tab_selected_pressed_holo.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/tab_selected_pressed_holo.9.png
rename to res/drawable-large-mdpi/tab_selected_pressed_holo.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/widget_resize_frame_holo.9.png b/res/drawable-large-mdpi/widget_resize_frame_holo.9.png
new file mode 100644
index 0000000..e2e1396
--- /dev/null
+++ b/res/drawable-large-mdpi/widget_resize_frame_holo.9.png
Binary files differ
diff --git a/res/drawable-large-mdpi/widget_resize_handle_bottom.png b/res/drawable-large-mdpi/widget_resize_handle_bottom.png
new file mode 100644
index 0000000..99ac1b2
--- /dev/null
+++ b/res/drawable-large-mdpi/widget_resize_handle_bottom.png
Binary files differ
diff --git a/res/drawable-large-mdpi/widget_resize_handle_left.png b/res/drawable-large-mdpi/widget_resize_handle_left.png
new file mode 100644
index 0000000..d031ddd
--- /dev/null
+++ b/res/drawable-large-mdpi/widget_resize_handle_left.png
Binary files differ
diff --git a/res/drawable-large-mdpi/widget_resize_handle_right.png b/res/drawable-large-mdpi/widget_resize_handle_right.png
new file mode 100644
index 0000000..f1b689c
--- /dev/null
+++ b/res/drawable-large-mdpi/widget_resize_handle_right.png
Binary files differ
diff --git a/res/drawable-large-mdpi/widget_resize_handle_top.png b/res/drawable-large-mdpi/widget_resize_handle_top.png
new file mode 100644
index 0000000..40bef02
--- /dev/null
+++ b/res/drawable-large-mdpi/widget_resize_handle_top.png
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/all_apps_bg_gradient.9.png b/res/drawable-large-nodpi/all_apps_bg_gradient.9.png
similarity index 100%
rename from res/drawable-xlarge-nodpi/all_apps_bg_gradient.9.png
rename to res/drawable-large-nodpi/all_apps_bg_gradient.9.png
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/bluecrystal.jpg b/res/drawable-large-nodpi/bluecrystal.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/bluecrystal.jpg
rename to res/drawable-large-nodpi/bluecrystal.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/bluecrystal_small.jpg b/res/drawable-large-nodpi/bluecrystal_small.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/bluecrystal_small.jpg
rename to res/drawable-large-nodpi/bluecrystal_small.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/bluelinebots.jpg b/res/drawable-large-nodpi/bluelinebots.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/bluelinebots.jpg
rename to res/drawable-large-nodpi/bluelinebots.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/bluelinebots_small.jpg b/res/drawable-large-nodpi/bluelinebots_small.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/bluelinebots_small.jpg
rename to res/drawable-large-nodpi/bluelinebots_small.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/bots.jpg b/res/drawable-large-nodpi/bots.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/bots.jpg
rename to res/drawable-large-nodpi/bots.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/bots_small.jpg b/res/drawable-large-nodpi/bots_small.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/bots_small.jpg
rename to res/drawable-large-nodpi/bots_small.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/bucky.jpg b/res/drawable-large-nodpi/bucky.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/bucky.jpg
rename to res/drawable-large-nodpi/bucky.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/bucky_small.jpg b/res/drawable-large-nodpi/bucky_small.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/bucky_small.jpg
rename to res/drawable-large-nodpi/bucky_small.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/city.jpg b/res/drawable-large-nodpi/city.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/city.jpg
rename to res/drawable-large-nodpi/city.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/city_small.jpg b/res/drawable-large-nodpi/city_small.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/city_small.jpg
rename to res/drawable-large-nodpi/city_small.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/customize_bg_gradient.png b/res/drawable-large-nodpi/customize_bg_gradient.png
similarity index 100%
rename from res/drawable-xlarge-nodpi/customize_bg_gradient.png
rename to res/drawable-large-nodpi/customize_bg_gradient.png
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/flowerbot.jpg b/res/drawable-large-nodpi/flowerbot.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/flowerbot.jpg
rename to res/drawable-large-nodpi/flowerbot.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/flowerbot_small.jpg b/res/drawable-large-nodpi/flowerbot_small.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/flowerbot_small.jpg
rename to res/drawable-large-nodpi/flowerbot_small.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/glowy_hex.jpg b/res/drawable-large-nodpi/glowy_hex.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/glowy_hex.jpg
rename to res/drawable-large-nodpi/glowy_hex.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/glowy_hex_small.jpg b/res/drawable-large-nodpi/glowy_hex_small.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/glowy_hex_small.jpg
rename to res/drawable-large-nodpi/glowy_hex_small.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/lotus.jpg b/res/drawable-large-nodpi/lotus.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/lotus.jpg
rename to res/drawable-large-nodpi/lotus.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/lotus_small.jpg b/res/drawable-large-nodpi/lotus_small.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/lotus_small.jpg
rename to res/drawable-large-nodpi/lotus_small.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/village.jpg b/res/drawable-large-nodpi/village.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/village.jpg
rename to res/drawable-large-nodpi/village.jpg
Binary files differ
diff --git a/res/drawable-xlarge-nodpi/village_small.jpg b/res/drawable-large-nodpi/village_small.jpg
similarity index 100%
rename from res/drawable-xlarge-nodpi/village_small.jpg
rename to res/drawable-large-nodpi/village_small.jpg
Binary files differ
diff --git a/res/drawable-xlarge/delete_zone_selector.xml b/res/drawable-large/delete_zone_selector.xml
similarity index 100%
rename from res/drawable-xlarge/delete_zone_selector.xml
rename to res/drawable-large/delete_zone_selector.xml
diff --git a/res/drawable-mdpi/box_launcher_top_normal.9.png b/res/drawable-mdpi/box_launcher_top_normal.9.png
index 8adf2cf..af04b07 100644
--- a/res/drawable-mdpi/box_launcher_top_normal.9.png
+++ b/res/drawable-mdpi/box_launcher_top_normal.9.png
Binary files differ
diff --git a/res/drawable-mdpi/box_launcher_top_pressed.9.png b/res/drawable-mdpi/box_launcher_top_pressed.9.png
index 7a20c54..af04b07 100644
--- a/res/drawable-mdpi/box_launcher_top_pressed.9.png
+++ b/res/drawable-mdpi/box_launcher_top_pressed.9.png
Binary files differ
diff --git a/res/drawable-mdpi/box_launcher_top_selected.9.png b/res/drawable-mdpi/box_launcher_top_selected.9.png
index 9e636f0..af04b07 100644
--- a/res/drawable-mdpi/box_launcher_top_selected.9.png
+++ b/res/drawable-mdpi/box_launcher_top_selected.9.png
Binary files differ
diff --git a/res/drawable-mdpi/focused_bg.9.png b/res/drawable-mdpi/focused_bg.9.png
new file mode 100644
index 0000000..1b0d3fa
--- /dev/null
+++ b/res/drawable-mdpi/focused_bg.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/home_press.9.png b/res/drawable-mdpi/home_press.9.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/home_press.9.png
rename to res/drawable-mdpi/home_press.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/ic_home_delete_holo_dark.png b/res/drawable-mdpi/ic_home_delete_holo_dark.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/ic_home_delete_holo_dark.png
rename to res/drawable-mdpi/ic_home_delete_holo_dark.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/ic_home_delete_hover_holo_dark.png b/res/drawable-mdpi/ic_home_delete_hover_holo_dark.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/ic_home_delete_hover_holo_dark.png
rename to res/drawable-mdpi/ic_home_delete_hover_holo_dark.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/ic_home_info_holo_dark.png b/res/drawable-mdpi/ic_home_info_holo_dark.png
similarity index 100%
rename from res/drawable-xlarge-mdpi/ic_home_info_holo_dark.png
rename to res/drawable-mdpi/ic_home_info_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_container_holo.9.png b/res/drawable-mdpi/portal_container_holo.9.png
new file mode 100644
index 0000000..42aca5f
--- /dev/null
+++ b/res/drawable-mdpi/portal_container_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_inner_holo.png b/res/drawable-mdpi/portal_ring_inner_holo.png
new file mode 100644
index 0000000..4a64694
--- /dev/null
+++ b/res/drawable-mdpi/portal_ring_inner_holo.png
Binary files differ
diff --git a/res/drawable-mdpi/portal_ring_outer_holo.png b/res/drawable-mdpi/portal_ring_outer_holo.png
new file mode 100644
index 0000000..90cf77f
--- /dev/null
+++ b/res/drawable-mdpi/portal_ring_outer_holo.png
Binary files differ
diff --git a/res/drawable-mdpi/wallpaper_divider.png b/res/drawable-mdpi/wallpaper_divider.png
new file mode 100644
index 0000000..1b453c5
--- /dev/null
+++ b/res/drawable-mdpi/wallpaper_divider.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_frame_holo.9.png b/res/drawable-mdpi/widget_resize_frame_holo.9.png
new file mode 100644
index 0000000..0572f89
--- /dev/null
+++ b/res/drawable-mdpi/widget_resize_frame_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_handle_bottom.png b/res/drawable-mdpi/widget_resize_handle_bottom.png
new file mode 100644
index 0000000..6c93973
--- /dev/null
+++ b/res/drawable-mdpi/widget_resize_handle_bottom.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_handle_left.png b/res/drawable-mdpi/widget_resize_handle_left.png
new file mode 100644
index 0000000..7139415
--- /dev/null
+++ b/res/drawable-mdpi/widget_resize_handle_left.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_handle_right.png b/res/drawable-mdpi/widget_resize_handle_right.png
new file mode 100644
index 0000000..442224b
--- /dev/null
+++ b/res/drawable-mdpi/widget_resize_handle_right.png
Binary files differ
diff --git a/res/drawable-mdpi/widget_resize_handle_top.png b/res/drawable-mdpi/widget_resize_handle_top.png
new file mode 100644
index 0000000..2435884
--- /dev/null
+++ b/res/drawable-mdpi/widget_resize_handle_top.png
Binary files differ
diff --git a/res/drawable-nodpi/apps_customize_bg_gradient.9.png b/res/drawable-nodpi/apps_customize_bg_gradient.9.png
new file mode 100644
index 0000000..e766bd6
--- /dev/null
+++ b/res/drawable-nodpi/apps_customize_bg_gradient.9.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/ic_generic_search.png b/res/drawable-xlarge-mdpi/ic_generic_search.png
deleted file mode 100644
index d92071b..0000000
--- a/res/drawable-xlarge-mdpi/ic_generic_search.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/ic_voice_search.png b/res/drawable-xlarge-mdpi/ic_voice_search.png
deleted file mode 100644
index a2fe874..0000000
--- a/res/drawable-xlarge-mdpi/ic_voice_search.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xlarge/button_bg.xml b/res/drawable/button_bg.xml
similarity index 85%
rename from res/drawable-xlarge/button_bg.xml
rename to res/drawable/button_bg.xml
index 9e6e1ff..a830594 100644
--- a/res/drawable-xlarge/button_bg.xml
+++ b/res/drawable/button_bg.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true" android:drawable="@drawable/focused_bg" />
     <item android:state_pressed="true" android:drawable="@drawable/home_press" />
     <item android:drawable="@android:color/transparent" />
 </selector>
diff --git a/res/drawable/delete_zone_selector.xml b/res/drawable/delete_zone_selector.xml
index 0c54b1d7..e2b37f4 100644
--- a/res/drawable/delete_zone_selector.xml
+++ b/res/drawable/delete_zone_selector.xml
@@ -19,6 +19,6 @@
 -->
 
 <transition xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@drawable/trashcan"  />
-    <item android:drawable="@drawable/trashcan_hover"  />
+    <item android:drawable="@drawable/ic_home_delete_holo_dark"  />
+    <item android:drawable="@drawable/ic_home_delete_hover_holo_dark"  />
 </transition>
diff --git a/res/drawable-xlarge/button_bg.xml b/res/drawable/focusable_view_bg.xml
similarity index 77%
copy from res/drawable-xlarge/button_bg.xml
copy to res/drawable/focusable_view_bg.xml
index 9e6e1ff..66661e2 100644
--- a/res/drawable-xlarge/button_bg.xml
+++ b/res/drawable/focusable_view_bg.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -15,6 +15,5 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true" android:drawable="@drawable/home_press" />
-    <item android:drawable="@android:color/transparent" />
+    <item android:state_focused="true" android:drawable="@drawable/focused_bg" />
 </selector>
diff --git a/res/layout-land/all_apps_2d.xml b/res/layout-land/all_apps_2d.xml
deleted file mode 100644
index b7fcd45..0000000
--- a/res/layout-land/all_apps_2d.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<!-- Sapphire gets 2D all apps view -->
-<com.android.launcher2.AllApps2D
-    xmlns:android="http://schemas.android.com/apk/res/android"
-
-    android:id="@+id/all_apps_view"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:padding="2dip"
-    android:background="#FF000000">
-
-    <GridView android:id="@+id/all_apps_2d_grid"
-        android:tag="all_apps_2d_grid"
-        android:scrollbars="none"
-        android:drawSelectorOnTop="false"
-        android:listSelector="@drawable/grid_selector"
-        android:verticalSpacing="10dip"
-        android:numColumns="6"
-        android:fadingEdgeLength="48dip"
-        android:cacheColorHint="#FF000000"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_alignParentRight="true"
-        android:layout_marginRight="@dimen/button_bar_height_portrait"
-        android:nextFocusRight="@+id/all_apps_2d_home"
-        android:nextFocusUp="@null"
-        android:nextFocusLeft="@null"
-        android:nextFocusDown="@null"
-        />
-
-    <view
-        class="com.android.launcher2.AllApps2D$HomeButton"
-        android:id="@+id/all_apps_2d_home"
-        android:tag="all_apps_2d_home"
-        android:src="@drawable/home_button"
-        android:background="#FF000000"
-        android:layout_alignParentRight="true"
-        android:layout_centerVertical="true"
-        android:layout_height="wrap_content"
-        android:layout_width="@dimen/button_bar_height_portrait"
-        android:paddingBottom="@dimen/status_bar_height"
-        android:nextFocusLeft="@+id/all_apps_2d_grid"
-        android:nextFocusDown="@null"
-        android:nextFocusUp="@null"
-        android:nextFocusRight="@null"
-        />
-
-</com.android.launcher2.AllApps2D>
diff --git a/res/layout-land/application.xml b/res/layout-land/application.xml
index 6e8c31e..9ed1fa1 100644
--- a/res/layout-land/application.xml
+++ b/res/layout-land/application.xml
@@ -15,4 +15,6 @@
 -->
 
 <com.android.launcher2.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
-   style="@style/WorkspaceIcon.Landscape" />
+   style="@style/WorkspaceIcon.Landscape"
+   android:focusable="true"
+   android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 6e797f8..b2b2c9f 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -22,8 +22,6 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <include layout="@layout/all_apps" />
-
     <!-- The workspace contains 5 screens of cells -->
     <com.android.launcher2.Workspace
         android:id="@+id/workspace"
@@ -43,6 +41,12 @@
 
     </com.android.launcher2.Workspace>
 
+    <include layout="@layout/apps_customize_pane"
+        android:id="@+id/apps_customize_pane"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="invisible" />
+
     <com.android.launcher2.ClippedImageView
         android:id="@+id/previous_screen"
         android:layout_width="93dip"
@@ -96,38 +100,26 @@
         android:layout_height="fill_parent"
         android:layout_width="@dimen/button_bar_height_portrait"
         android:layout_gravity="right|center_vertical"
-        android:layout_marginBottom="@dimen/half_status_bar_height"
-        >
-
+        android:layout_marginBottom="@dimen/half_status_bar_height">
+        <ImageView
+            android:id="@+id/hotseat_left"
+            style="@style/HotseatButton.Left"
+            android:layout_below="@id/all_apps_button"
+            android:src="@drawable/hotseat_phone"
+            android:onClick="launchHotSeat" />
         <com.android.launcher2.HandleView
             style="@style/HotseatButton"
             android:id="@+id/all_apps_button"
             android:layout_centerVertical="true"
             android:layout_alignParentRight="true"
-
             android:src="@drawable/all_apps_button"
-            launcher:direction="vertical"
-            />
-
-        <ImageView
-            android:id="@+id/hotseat_left"
-            style="@style/HotseatButton.Left"
-            android:layout_below="@id/all_apps_button"
-
-            android:src="@drawable/hotseat_phone"
-
-            android:onClick="launchHotSeat"
-            />
-
+            launcher:direction="vertical" />
         <ImageView
             android:id="@+id/hotseat_right"
             style="@style/HotseatButton.Right"
             android:layout_above="@id/all_apps_button"
-
             android:src="@drawable/hotseat_browser"
-
-            android:onClick="launchHotSeat"
-            />
+            android:onClick="launchHotSeat" />
 
     </RelativeLayout>
 </com.android.launcher2.DragLayer>
diff --git a/res/layout-land/user_folder.xml b/res/layout-land/user_folder.xml
index 5da4aa5..87499e7 100644
--- a/res/layout-land/user_folder.xml
+++ b/res/layout-land/user_folder.xml
@@ -14,39 +14,27 @@
      limitations under the License.
 -->
 
-<com.android.launcher2.UserFolder xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical">
-    
-    <Button
-        android:id="@+id/folder_close"
-    	android:background="@drawable/box_launcher_top"
-        android:gravity="left|center_vertical"
-        android:textSize="14sp"
-        android:textColor="#404040"
-        android:textStyle="bold"
-        android:layout_width="match_parent"
-    	android:layout_height="wrap_content" />
+<com.android.launcher2.Folder
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+    android:orientation="vertical"
+    android:background="@drawable/portal_container_holo">
 
-    <FrameLayout
-         android:layout_width="match_parent"
-	   android:layout_height="0dip"
-         android:layout_weight="1"
-         android:background="@drawable/box_launcher_bottom">
+    <com.android.launcher2.CellLayout
+        android:id="@id/folder_content"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
 
-        <GridView
-             android:id="@id/folder_content"
-             android:layout_width="match_parent"
-             android:layout_height="match_parent"
+        android:cacheColorHint="#ff333333"
 
-             android:cacheColorHint="#ff333333"
+        android:hapticFeedbackEnabled="false"
+        launcher:widthGap="@dimen/workspace_width_gap"
+        launcher:heightGap="@dimen/workspace_height_gap"
+        launcher:cellWidth="@dimen/workspace_cell_width"
+        launcher:cellHeight="@dimen/workspace_cell_height"
+        launcher:xAxisStartPadding="0dip"
+        launcher:xAxisEndPadding="0dip"
+        launcher:yAxisStartPadding="8dip"
+        launcher:yAxisEndPadding="8dip"/>
 
-             android:scrollbarAlwaysDrawVerticalTrack="true"
-             android:scrollbarStyle="insideInset"
-             android:drawSelectorOnTop="false"
-             android:listSelector="@drawable/grid_selector"
-
-             android:verticalSpacing="10dip"
-             android:numColumns="5" />
-    </FrameLayout>
-
-</com.android.launcher2.UserFolder>
+</com.android.launcher2.Folder>
diff --git a/res/layout-xlarge-land/application.xml b/res/layout-large-land/application.xml
similarity index 85%
rename from res/layout-xlarge-land/application.xml
rename to res/layout-large-land/application.xml
index 2598e5a..9393f7e 100644
--- a/res/layout-xlarge-land/application.xml
+++ b/res/layout-large-land/application.xml
@@ -15,4 +15,6 @@
 -->
 
 <com.android.launcher2.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
-   style="@style/WorkspaceIcon.Landscape" />
+   style="@style/WorkspaceIcon.Landscape"
+   android:focusable="true"
+   android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-large-land/workspace.xml b/res/layout-large-land/workspace.xml
new file mode 100644
index 0000000..e8ea782
--- /dev/null
+++ b/res/layout-large-land/workspace.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- The workspace contains 5 screens of cells -->
+<com.android.launcher2.Workspace
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+    android:paddingTop="?android:attr/actionBarSize"
+    android:paddingBottom="10dp"
+    launcher:defaultScreen="2"
+    launcher:pageSpacing="@dimen/workspace_page_spacing_land">
+      <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
+      <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
+      <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
+      <include android:id="@+id/cell4" layout="@layout/workspace_screen" />
+      <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
+</com.android.launcher2.Workspace>
\ No newline at end of file
diff --git a/res/layout-xlarge-land/workspace_screen.xml b/res/layout-large-land/workspace_screen.xml
similarity index 72%
copy from res/layout-xlarge-land/workspace_screen.xml
copy to res/layout-large-land/workspace_screen.xml
index e983b79..25b05e9 100644
--- a/res/layout-xlarge-land/workspace_screen.xml
+++ b/res/layout-large-land/workspace_screen.xml
@@ -24,9 +24,10 @@
 
     launcher:cellWidth="@dimen/workspace_cell_width"
     launcher:cellHeight="@dimen/workspace_cell_height"
-    launcher:widthGap="@dimen/workspace_width_gap"
-    launcher:heightGap="@dimen/workspace_height_gap"
-    launcher:yAxisStartPadding="15dip"
-    launcher:yAxisEndPadding="15dip"
-    launcher:xAxisStartPadding="25dip"
-    launcher:xAxisEndPadding="25dip" />
+    launcher:widthGap="@dimen/workspace_width_gap_land"
+    launcher:heightGap="@dimen/workspace_height_gap_land"
+
+    launcher:xAxisStartPadding="@dimen/workspace_x_axis_start_padding_land"
+    launcher:xAxisEndPadding="@dimen/workspace_x_axis_end_padding_land"
+    launcher:yAxisStartPadding="@dimen/workspace_y_axis_start_padding_land"
+    launcher:yAxisEndPadding="@dimen/workspace_y_axis_end_padding_land" />
diff --git a/res/layout-xlarge-port/application.xml b/res/layout-large-port/application.xml
similarity index 100%
rename from res/layout-xlarge-port/application.xml
rename to res/layout-large-port/application.xml
diff --git a/res/layout-large-port/workspace.xml b/res/layout-large-port/workspace.xml
new file mode 100644
index 0000000..ccd7d33
--- /dev/null
+++ b/res/layout-large-port/workspace.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- The workspace contains 5 screens of cells -->
+<com.android.launcher2.Workspace
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+    android:paddingTop="?android:attr/actionBarSize"
+    android:paddingBottom="10dp"
+    launcher:defaultScreen="2"
+    launcher:pageSpacing="@dimen/workspace_page_spacing_port">
+      <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
+      <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
+      <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
+      <include android:id="@+id/cell4" layout="@layout/workspace_screen" />
+      <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
+</com.android.launcher2.Workspace>
\ No newline at end of file
diff --git a/res/layout-xlarge-land/workspace_screen.xml b/res/layout-large-port/workspace_screen.xml
similarity index 72%
rename from res/layout-xlarge-land/workspace_screen.xml
rename to res/layout-large-port/workspace_screen.xml
index e983b79..e33c612 100644
--- a/res/layout-xlarge-land/workspace_screen.xml
+++ b/res/layout-large-port/workspace_screen.xml
@@ -24,9 +24,10 @@
 
     launcher:cellWidth="@dimen/workspace_cell_width"
     launcher:cellHeight="@dimen/workspace_cell_height"
-    launcher:widthGap="@dimen/workspace_width_gap"
-    launcher:heightGap="@dimen/workspace_height_gap"
-    launcher:yAxisStartPadding="15dip"
-    launcher:yAxisEndPadding="15dip"
-    launcher:xAxisStartPadding="25dip"
-    launcher:xAxisEndPadding="25dip" />
+    launcher:widthGap="@dimen/workspace_width_gap_port"
+    launcher:heightGap="@dimen/workspace_height_gap_port"
+
+    launcher:xAxisStartPadding="@dimen/workspace_x_axis_start_padding_port"
+    launcher:xAxisEndPadding="@dimen/workspace_x_axis_end_padding_port"
+    launcher:yAxisStartPadding="@dimen/workspace_y_axis_start_padding_port"
+    launcher:yAxisEndPadding="@dimen/workspace_y_axis_end_padding_port" />
diff --git a/res/layout-xlarge/all_apps_no_items_placeholder.xml b/res/layout-large/all_apps_no_items_placeholder.xml
similarity index 94%
rename from res/layout-xlarge/all_apps_no_items_placeholder.xml
rename to res/layout-large/all_apps_no_items_placeholder.xml
index 247870c..b766df1 100644
--- a/res/layout-xlarge/all_apps_no_items_placeholder.xml
+++ b/res/layout-large/all_apps_no_items_placeholder.xml
@@ -32,4 +32,5 @@
     android:drawablePadding="0dip"
 
     android:maxLines="2"
-    android:fadingEdge="horizontal" />
+    android:fadingEdge="horizontal"
+    android:focusable="false" />
diff --git a/res/layout-xlarge/all_apps_paged_view_application.xml b/res/layout-large/all_apps_paged_view_application.xml
similarity index 89%
rename from res/layout-xlarge/all_apps_paged_view_application.xml
rename to res/layout-large/all_apps_paged_view_application.xml
index e5f07bf..16e5d82 100644
--- a/res/layout-xlarge/all_apps_paged_view_application.xml
+++ b/res/layout-large/all_apps_paged_view_application.xml
@@ -21,9 +21,12 @@
     launcher:blurColor="#FF6B8CF0"
     launcher:outlineColor="#FF8CD2FF"
 
+    style="@style/WorkspaceIcon.AllApps"
+
     android:id="@+id/application_icon"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:gravity="center_horizontal"
 
-    style="@style/WorkspaceIcon.AllApps" />
+    android:focusable="true"
+    android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-xlarge-land/all_apps_tabbed.xml b/res/layout-large/all_apps_tabbed.xml
similarity index 63%
rename from res/layout-xlarge-land/all_apps_tabbed.xml
rename to res/layout-large/all_apps_tabbed.xml
index d03a571..b00b3c3 100644
--- a/res/layout-xlarge-land/all_apps_tabbed.xml
+++ b/res/layout-large/all_apps_tabbed.xml
@@ -16,16 +16,23 @@
 <com.android.launcher2.AllAppsTabbed
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
+    <com.android.launcher2.AllAppsBackground
+        android:id="@+id/all_apps_background"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
     <LinearLayout
         android:orientation="vertical"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
+        <!-- The layout_width of this RelativeLayout gets overwritten in
+             AllAppsTabbed.onFinishInflate -->
         <RelativeLayout
-            android:layout_width="952dp"
+            android:id="@+id/all_apps_tab_bar"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
             android:background="@drawable/tab_unselected_holo">
-            <TabWidget
+            <com.android.launcher2.FocusOnlyTabWidget
                 android:id="@android:id/tabs"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
@@ -43,17 +50,28 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_gravity="center"
-                    android:visibility="invisible"/>
-                <ImageView
+                    android:visibility="invisible"
+                    android:background="@drawable/focusable_view_bg"
+                    android:focusable="true" />
+                <TextView
                     android:id="@+id/market_button"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_gravity="center"
-                    android:onClick="onClickAppMarketButton"/>
+                    android:gravity="center"
+                    android:paddingRight="22dp"
+                    android:text="@string/market"
+                    android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
+                    android:textSize="18sp"
+                    android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
+                    android:shadowDx="0.0"
+                    android:shadowDy="0.0"
+                    android:shadowRadius="2.0"
+                    android:background="@drawable/focusable_view_bg"
+                    android:focusable="true" />
             </FrameLayout>
             <com.android.launcher2.DeleteZone
                 android:id="@+id/all_apps_delete_zone"
-                android:text="@string/delete_zone_label_all_apps"
                 android:drawablePadding="@dimen/delete_zone_drawable_padding"
                 android:drawableLeft="@drawable/delete_zone_selector"
                 android:layout_width="wrap_content"
@@ -64,13 +82,16 @@
                 android:paddingRight="22dp"
                 launcher:direction="horizontal"
 
-                android:gravity="center_horizontal|center_vertical"
+                android:gravity="center"
                 android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
                 android:textSize="18sp"
                 android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
                 android:shadowDx="0.0"
                 android:shadowDy="0.0"
-                android:shadowRadius="2.0" />
+                android:shadowRadius="2.0"
+
+                android:background="@drawable/focusable_view_bg"
+                android:focusable="true" />
         </RelativeLayout>
         <FrameLayout
             android:id="@android:id/tabcontent"
@@ -80,14 +101,14 @@
                 android:id="@+id/all_apps_paged_view"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                launcher:cellCountX="7"
-                launcher:cellCountY="5"
-                launcher:pageLayoutWidthGap="36dp"
-                launcher:pageLayoutHeightGap="6dp"
-                launcher:pageLayoutPaddingTop="20dp"
-                launcher:pageLayoutPaddingBottom="15dp"
-                launcher:pageLayoutPaddingLeft="40dp"
-                launcher:pageLayoutPaddingRight="40dp">
+                launcher:cellCountX="@integer/all_apps_view_cellCountX"
+                launcher:cellCountY="@integer/all_apps_view_cellCountY"
+                launcher:pageLayoutWidthGap="@dimen/all_apps_view_pageLayoutWidthGap"
+                launcher:pageLayoutHeightGap="@dimen/all_apps_view_pageLayoutHeightGap"
+                launcher:pageLayoutPaddingTop="@dimen/all_apps_view_pageLayoutPaddingTop"
+                launcher:pageLayoutPaddingBottom="@dimen/all_apps_view_pageLayoutPaddingBottom"
+                launcher:pageLayoutPaddingLeft="@dimen/all_apps_view_pageLayoutPaddingLeft"
+                launcher:pageLayoutPaddingRight="@dimen/all_apps_view_pageLayoutPaddingRight">
             </com.android.launcher2.AllAppsPagedView>
         </FrameLayout>
     </LinearLayout>
diff --git a/res/layout-large/button_bar.xml b/res/layout-large/button_bar.xml
new file mode 100644
index 0000000..62115f7
--- /dev/null
+++ b/res/layout-large/button_bar.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+    android:focusable="false">
+
+   <!-- Global search icon -->
+   <ImageView
+        android:id="@+id/search_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentLeft="true"
+        android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
+        android:paddingRight="@dimen/toolbar_button_horizontal_padding"
+        android:paddingTop="@dimen/toolbar_button_vertical_padding"
+        android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+        android:src="@drawable/ic_generic_search"
+        android:background="@drawable/button_bg"
+        android:onClick="onClickSearchButton"
+
+        android:focusable="true"
+        android:clickable="true"
+        android:contentDescription="@string/accessibility_search_button" />
+
+    <ImageView
+        android:id="@+id/search_divider"
+        android:src="@drawable/divider_launcher_holo"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_toRightOf="@+id/search_button"
+        android:paddingTop="@dimen/toolbar_button_vertical_padding"
+        android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+
+        android:onClick="onClickSearchButton"
+        android:focusable="false"
+        android:clickable="true" />
+
+    <!-- Voice search icon -->
+    <ImageView
+        android:id="@+id/voice_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toRightOf="@+id/search_divider"
+        android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
+        android:paddingRight="@dimen/toolbar_button_horizontal_padding"
+        android:paddingTop="@dimen/toolbar_button_vertical_padding"
+        android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+        android:src="@drawable/ic_voice_search"
+        android:background="@drawable/button_bg"
+        android:onClick="onClickVoiceButton"
+
+        android:focusable="true"
+        android:clickable="true"
+        android:contentDescription="@string/accessibility_voice_search_button" />
+
+    <!-- AllApps icon -->
+    <com.android.launcher2.StrokedTextView
+        android:id="@+id/all_apps_button"
+        android:text="@string/all_apps_button_label"
+        android:drawablePadding="@dimen/all_apps_button_drawable_padding"
+        android:drawableLeft="@drawable/ic_home_all_apps_holo_dark"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_toLeftOf="@+id/all_apps_divider"
+        android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
+        android:paddingRight="@dimen/toolbar_button_horizontal_padding"
+        android:paddingTop="@dimen/all_apps_button_vertical_padding"
+        android:paddingBottom="@dimen/all_apps_button_vertical_padding"
+        android:background="@drawable/button_bg"
+
+        android:gravity="center_horizontal|center_vertical"
+        android:textColor="#CCFFFFFF"
+        android:textSize="18sp"
+
+        launcher:strokeColor="#991e3157"
+        launcher:strokeTextColor="#DDFFFFFF"
+        launcher:strokeWidth="2.5"
+
+        android:shadowColor="#DA000000"
+        android:shadowDx="0.0"
+        android:shadowDy="0.0"
+        android:shadowRadius="2.5"
+
+        android:focusable="true"
+        android:clickable="true"
+        android:contentDescription="@string/accessibility_all_apps_button" />
+
+    <ImageView
+        android:id="@+id/all_apps_divider"
+        android:src="@drawable/divider_launcher_holo"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_toLeftOf="@+id/configure_button"
+        android:paddingTop="@dimen/toolbar_button_vertical_padding"
+        android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+
+        android:focusable="false"
+        android:clickable="true" />
+
+    <!-- Customize icon -->
+    <ImageView
+        android:id="@+id/configure_button"
+        android:src="@drawable/ic_home_add_holo_dark"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentRight="true"
+        android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
+        android:paddingRight="@dimen/toolbar_button_horizontal_padding"
+        android:paddingTop="@dimen/toolbar_button_vertical_padding"
+        android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+        android:background="@drawable/button_bg"
+        android:focusable="true"
+        android:contentDescription="@string/accessibility_customize_button" />
+
+    <!-- Delete icon -->
+    <com.android.launcher2.DeleteZone
+        android:id="@+id/delete_zone"
+        android:text="@string/delete_zone_label_workspace"
+        android:drawablePadding="@dimen/delete_zone_drawable_padding"
+        android:drawableLeft="@drawable/delete_zone_selector"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignRight="@+id/configure_button"
+        android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
+        android:paddingRight="@dimen/toolbar_button_horizontal_padding"
+        android:paddingTop="@dimen/toolbar_button_vertical_padding"
+        android:paddingBottom="@dimen/toolbar_button_vertical_padding"
+       android:background="@drawable/button_bg"
+
+        android:gravity="center_horizontal|center_vertical"
+        android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
+        android:textSize="18sp"
+        android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
+        android:shadowDx="0.0"
+        android:shadowDy="0.0"
+        android:shadowRadius="2.0"
+
+        android:visibility="gone"
+        launcher:direction="horizontal"
+
+        android:focusable="true"
+        android:contentDescription="@string/accessibility_delete_button" />
+</RelativeLayout>
diff --git a/res/layout-large/customization_drawer.xml b/res/layout-large/customization_drawer.xml
new file mode 100644
index 0000000..d8db066
--- /dev/null
+++ b/res/layout-large/customization_drawer.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+<com.android.launcher2.CustomizeTrayTabHost
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <!-- The layout_width of this RelativeLayout gets overwritten in
+             CustomizeTrayTabHost.onFinishInflate -->
+        <com.android.launcher2.FocusOnlyTabWidget
+            android:id="@android:id/tabs"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal"
+            android:background="@drawable/tab_unselected_holo"
+            android:tabStripEnabled="false" />
+        <FrameLayout
+            android:id="@android:id/tabcontent"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <com.android.launcher2.CustomizePagedView
+                android:id="@+id/customization_drawer_tab_contents"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                launcher:wallpaperCellSpanX="@integer/customization_drawer_contents_wallpaperCellSpanX"
+                launcher:wallpaperCellCountX="@integer/customization_drawer_contents_wallpaperCellCountX"
+                launcher:widgetCellCountX="@integer/customization_drawer_contents_widgetCellCountX"
+                launcher:cellCountX="@integer/customization_drawer_contents_cellCountX"
+                launcher:cellCountY="@integer/customization_drawer_contents_cellCountY"
+                launcher:pageLayoutWidthGap="@dimen/customization_drawer_contents_pageLayoutWidthGap"
+                launcher:pageLayoutHeightGap="12dp"
+                launcher:pageLayoutPaddingTop="40dp"
+                launcher:pageLayoutPaddingBottom="25dp"
+                launcher:pageLayoutPaddingLeft="20dp"
+                launcher:pageLayoutPaddingRight="20dp"
+                launcher:pageLayoutMaxHeight="@dimen/customization_drawer_content_height" />
+         </FrameLayout>
+      </LinearLayout>
+</com.android.launcher2.CustomizeTrayTabHost>
\ No newline at end of file
diff --git a/res/layout-xlarge/customize_paged_view_item.xml b/res/layout-large/customize_paged_view_item.xml
similarity index 88%
rename from res/layout-xlarge/customize_paged_view_item.xml
rename to res/layout-large/customize_paged_view_item.xml
index b2e5f08..80d678e 100644
--- a/res/layout-xlarge/customize_paged_view_item.xml
+++ b/res/layout-large/customize_paged_view_item.xml
@@ -25,4 +25,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
 
-    style="@style/WorkspaceIcon.Landscape" />
+    style="@style/WorkspaceIcon.Landscape"
+
+    android:background="@drawable/focusable_view_bg"
+    android:focusable="true" />
diff --git a/res/layout-xlarge/customize_paged_view_wallpaper.xml b/res/layout-large/customize_paged_view_wallpaper.xml
similarity index 85%
rename from res/layout-xlarge/customize_paged_view_wallpaper.xml
rename to res/layout-large/customize_paged_view_wallpaper.xml
index e3be86d..d6284c2 100644
--- a/res/layout-xlarge/customize_paged_view_wallpaper.xml
+++ b/res/layout-large/customize_paged_view_wallpaper.xml
@@ -18,22 +18,25 @@
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
 
     android:layout_width="wrap_content"
-    android:layout_height="365dp"
-    android:paddingLeft="12.5dp"
-    android:paddingRight="12.5dp"
-    android:paddingBottom="50dp"
-    android:gravity="top"
+    android:layout_height="match_parent"
+    android:layout_weight="1"
     android:orientation="vertical"
+    android:paddingRight="25dp"
+    android:paddingBottom="50dp"
 
     launcher:blurColor="#FF6B8CF0"
-    launcher:outlineColor="#FF8CD2FF">
+    launcher:outlineColor="#FF8CD2FF"
+
+    android:background="@drawable/focusable_view_bg"
+    android:focusable="true">
 
     <!-- The preview image for the wallpaper. -->
     <ImageView
         android:id="@+id/wallpaper_preview"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_weight="1.0"
+        android:layout_weight="1"
+        android:adjustViewBounds="true"
         android:scaleType="fitStart" />
 
     <!-- The divider image. -->
@@ -41,6 +44,7 @@
         android:id="@+id/divider"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_weight="0"
         android:paddingTop="10dp"
         android:paddingBottom="10dp"
         android:src="@drawable/widget_divider" />
@@ -50,6 +54,7 @@
         android:id="@+id/wallpaper_name"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_weight="0"
         android:gravity="left"
 
         android:textColor="#FFFFFFFF"
diff --git a/res/layout-xlarge/customize_paged_view_widget.xml b/res/layout-large/customize_paged_view_widget.xml
similarity index 86%
rename from res/layout-xlarge/customize_paged_view_widget.xml
rename to res/layout-large/customize_paged_view_widget.xml
index 3b95ebc..35791f5 100644
--- a/res/layout-xlarge/customize_paged_view_widget.xml
+++ b/res/layout-large/customize_paged_view_widget.xml
@@ -18,23 +18,25 @@
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
 
     android:layout_width="wrap_content"
-    android:layout_height="365dp"
-    android:paddingLeft="12.5dp"
-    android:paddingTop="12.5dp"
-    android:paddingRight="12.5dp"
-    android:paddingBottom="50dp"
-    android:gravity="top"
+    android:layout_height="match_parent"
+    android:layout_weight="1"
     android:orientation="vertical"
+    android:paddingRight="25dp"
+    android:paddingBottom="50dp"
 
     launcher:blurColor="#FF6B8CF0"
-    launcher:outlineColor="#FF8CD2FF">
+    launcher:outlineColor="#FF8CD2FF"
+
+    android:background="@drawable/focusable_view_bg"
+    android:focusable="true">
 
     <!-- The icon of the widget. -->
     <ImageView
         android:id="@+id/widget_preview"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_weight="1.0"
+        android:layout_weight="1"
+        android:adjustViewBounds="true"
         android:scaleType="fitStart" />
 
     <!-- The divider image. -->
@@ -42,6 +44,7 @@
         android:id="@+id/divider"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_weight="0"
         android:paddingTop="10dp"
         android:paddingBottom="10dp"
         android:src="@drawable/widget_divider" />
@@ -51,6 +54,7 @@
         android:id="@+id/widget_name"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_weight="0"
         android:gravity="left"
 
         android:textColor="#FFFFFFFF"
@@ -69,6 +73,7 @@
         android:id="@+id/widget_dims"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_weight="0"
         android:gravity="left"
 
         android:textColor="#FF999999"
diff --git a/res/layout-xlarge/external_widget_drop_list_item.xml b/res/layout-large/external_widget_drop_list_item.xml
similarity index 100%
rename from res/layout-xlarge/external_widget_drop_list_item.xml
rename to res/layout-large/external_widget_drop_list_item.xml
diff --git a/res/layout-large/launcher.xml b/res/layout-large/launcher.xml
new file mode 100644
index 0000000..6a16eb5
--- /dev/null
+++ b/res/layout-large/launcher.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<com.android.launcher2.DragLayer
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+
+    android:id="@+id/drag_layer"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:focusable="false">
+
+    <include layout="@layout/workspace"
+        android:id="@+id/workspace"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <include layout="@layout/button_bar"
+        android:id="@+id/all_apps_button_cluster"
+        android:layout_width="fill_parent"
+        android:layout_height="?android:attr/actionBarSize"
+        android:layout_gravity="top" />
+
+    <include layout="@layout/all_apps_tabbed"
+        android:id="@+id/all_apps_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_gravity="top"
+        android:visibility="invisible" />
+
+    <include layout="@layout/customization_drawer"
+        android:id="@+id/customization_drawer"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/customization_drawer_height"
+        android:layout_gravity="bottom"
+        android:visibility="invisible" />
+</com.android.launcher2.DragLayer>
diff --git a/res/layout-xlarge/tab_widget_indicator.xml b/res/layout-large/tab_widget_indicator.xml
similarity index 89%
rename from res/layout-xlarge/tab_widget_indicator.xml
rename to res/layout-large/tab_widget_indicator.xml
index 7794e29..c09c853 100644
--- a/res/layout-xlarge/tab_widget_indicator.xml
+++ b/res/layout-large/tab_widget_indicator.xml
@@ -14,6 +14,6 @@
      limitations under the License.
 -->
 
-<TextView
+<com.android.launcher2.AccessibleTabView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/TabIndicator" />
+    style="@style/TabIndicator.Wide" />
diff --git a/res/layout-xlarge/wallpaper_chooser.xml b/res/layout-large/wallpaper_chooser.xml
similarity index 100%
rename from res/layout-xlarge/wallpaper_chooser.xml
rename to res/layout-large/wallpaper_chooser.xml
diff --git a/res/layout-xlarge/wallpaper_chooser_base.xml b/res/layout-large/wallpaper_chooser_base.xml
similarity index 100%
rename from res/layout-xlarge/wallpaper_chooser_base.xml
rename to res/layout-large/wallpaper_chooser_base.xml
diff --git a/res/layout-xlarge/wallpaper_item.xml b/res/layout-large/wallpaper_item.xml
similarity index 100%
rename from res/layout-xlarge/wallpaper_item.xml
rename to res/layout-large/wallpaper_item.xml
diff --git a/res/layout-port/all_apps_2d.xml b/res/layout-port/all_apps_2d.xml
deleted file mode 100644
index 081cba2..0000000
--- a/res/layout-port/all_apps_2d.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<!-- Sapphire gets 2D all apps view -->
-<com.android.launcher2.AllApps2D
-    xmlns:android="http://schemas.android.com/apk/res/android"
-
-    android:id="@+id/all_apps_view"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:padding="2dip"
-    android:background="#FF000000">
-
-    <GridView android:id="@+id/all_apps_2d_grid"
-        android:tag="all_apps_2d_grid"
-        android:scrollbars="none"
-        android:drawSelectorOnTop="false"
-        android:listSelector="@drawable/grid_selector"
-        android:verticalSpacing="10dip"
-        android:numColumns="4"
-        android:fadingEdgeLength="48dip"
-        android:cacheColorHint="#FF000000"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_alignParentBottom="true"
-        android:layout_marginBottom="@dimen/button_bar_height"
-        android:layout_marginTop="8dip"
-        android:nextFocusDown="@+id/all_apps_2d_home"
-        android:nextFocusUp="@null"
-        android:nextFocusLeft="@null"
-        android:nextFocusRight="@null"
-        />
-
-    <view
-        class="com.android.launcher2.AllApps2D$HomeButton"
-        android:id="@+id/all_apps_2d_home"
-        android:tag="all_apps_2d_home"
-        android:src="@drawable/home_button"
-        android:background="#FF000000"
-        android:layout_centerHorizontal="true"
-        android:layout_alignParentBottom="true"
-        android:layout_width="wrap_content"
-        android:layout_height="@dimen/button_bar_height"
-        android:nextFocusUp="@+id/all_apps_2d_grid"
-        android:nextFocusDown="@null"
-        android:nextFocusLeft="@null"
-        android:nextFocusRight="@null"
-        />
-
-</com.android.launcher2.AllApps2D>
diff --git a/res/layout-port/application.xml b/res/layout-port/application.xml
index 32c1510..ddc8354 100644
--- a/res/layout-port/application.xml
+++ b/res/layout-port/application.xml
@@ -15,4 +15,6 @@
 -->
 
 <com.android.launcher2.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
-   style="@style/WorkspaceIcon.Portrait" />
+   style="@style/WorkspaceIcon.Portrait"
+   android:focusable="true"
+   android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index b7c61d8..c7bcbb0 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -22,8 +22,6 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <include layout="@layout/all_apps" />
-
     <!-- The workspace contains 5 screens of cells -->
     <com.android.launcher2.Workspace
         android:id="@+id/workspace"
@@ -41,6 +39,12 @@
                 
     </com.android.launcher2.Workspace>
 
+    <include layout="@layout/apps_customize_pane"
+        android:id="@+id/apps_customize_pane"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="invisible" />
+
     <ImageView
         android:id="@+id/previous_screen"
         android:layout_width="93dip"
@@ -89,39 +93,26 @@
         android:layout_width="fill_parent"
         android:layout_height="@dimen/button_bar_height"
         android:layout_gravity="bottom|center_horizontal"
-        android:paddingTop="2dip"
-        >
-
+        android:paddingTop="2dip">
+        <ImageView
+            android:id="@+id/hotseat_left"
+            style="@style/HotseatButton.Left"
+            android:layout_toLeftOf="@id/all_apps_button"
+            android:src="@drawable/hotseat_phone"
+            android:onClick="launchHotSeat" />
         <com.android.launcher2.HandleView
             style="@style/HotseatButton"
             android:id="@+id/all_apps_button"
             android:layout_centerHorizontal="true"
             android:layout_alignParentBottom="true"
-
             android:src="@drawable/all_apps_button"
-            launcher:direction="horizontal"
-            />
-
-        <ImageView
-            android:id="@+id/hotseat_left"
-            style="@style/HotseatButton.Left"
-            android:layout_toLeftOf="@id/all_apps_button"
-
-            android:src="@drawable/hotseat_phone"
-
-            android:onClick="launchHotSeat"
-            />
-
+            launcher:direction="horizontal" />
         <ImageView
             android:id="@+id/hotseat_right"
             style="@style/HotseatButton.Right"
             android:layout_toRightOf="@id/all_apps_button"
-
             android:src="@drawable/hotseat_browser"
-
-            android:onClick="launchHotSeat"
-            />
-
+            android:onClick="launchHotSeat" />
     </RelativeLayout>
 
 </com.android.launcher2.DragLayer>
diff --git a/res/layout-port/user_folder.xml b/res/layout-port/user_folder.xml
index 0e6df66..0d383c1 100644
--- a/res/layout-port/user_folder.xml
+++ b/res/layout-port/user_folder.xml
@@ -14,38 +14,27 @@
      limitations under the License.
 -->
 
-<com.android.launcher2.UserFolder xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical">
-        
-    <Button
-        android:id="@+id/folder_close"
-   		android:background="@drawable/box_launcher_top"
-        android:gravity="left|center_vertical"
-        android:textSize="14sp"
-        android:textColor="#404040"
-        android:textStyle="bold"
+<com.android.launcher2.Folder
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+    android:orientation="vertical"
+    android:background="@drawable/portal_container_holo">
+
+    <com.android.launcher2.CellLayout
+        android:id="@id/folder_content"
         android:layout_width="match_parent"
-    	android:layout_height="wrap_content" />
+        android:layout_height="match_parent"
 
-    <FrameLayout
-         android:layout_width="match_parent"
-	   android:layout_height="0dip"
-         android:layout_weight="1"
-         android:background="@drawable/box_launcher_bottom">
-        <GridView
-             android:id="@id/folder_content"
-             android:layout_width="match_parent"
-	       android:layout_height="match_parent"
+        android:cacheColorHint="#ff333333"
 
-             android:cacheColorHint="#ff333333"
+        android:hapticFeedbackEnabled="false"
+        launcher:widthGap="@dimen/workspace_width_gap"
+        launcher:heightGap="@dimen/workspace_height_gap"
+        launcher:cellWidth="@dimen/workspace_cell_width"
+        launcher:cellHeight="@dimen/workspace_cell_height"
+        launcher:xAxisStartPadding="0dip"
+        launcher:xAxisEndPadding="0dip"
+        launcher:yAxisStartPadding="8dip"
+        launcher:yAxisEndPadding="8dip"/>
 
-             android:scrollbarAlwaysDrawVerticalTrack="true"
-             android:scrollbarStyle="insideInset"
-             android:drawSelectorOnTop="false"
-             android:listSelector="@drawable/grid_selector"
-
-             android:verticalSpacing="10dip"
-             android:numColumns="4" />
-    </FrameLayout>
-
-</com.android.launcher2.UserFolder>
+</com.android.launcher2.Folder>
diff --git a/res/layout-xlarge-land/customization_drawer.xml b/res/layout-xlarge-land/customization_drawer.xml
deleted file mode 100644
index 50e7b66..0000000
--- a/res/layout-xlarge-land/customization_drawer.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-<com.android.launcher2.CustomizePagedView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
-
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    launcher:wallpaperCellSpanX="3"
-    launcher:wallpaperCellCountX="12"
-    launcher:widgetCellCountX="14"
-    launcher:cellCountX="8"
-    launcher:cellCountY="3"
-    launcher:pageLayoutWidthGap="32dp"
-    launcher:pageLayoutHeightGap="12dp"
-    launcher:pageLayoutPaddingTop="40dp"
-    launcher:pageLayoutPaddingBottom="25dp"
-    launcher:pageLayoutPaddingLeft="20dp"
-    launcher:pageLayoutPaddingRight="20dp" />
\ No newline at end of file
diff --git a/res/layout-xlarge-land/launcher.xml b/res/layout-xlarge-land/launcher.xml
deleted file mode 100644
index 957327e..0000000
--- a/res/layout-xlarge-land/launcher.xml
+++ /dev/null
@@ -1,215 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<com.android.launcher2.DragLayer
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
-
-    android:id="@+id/drag_layer"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <!-- The workspace contains 5 screens of cells -->
-    <com.android.launcher2.Workspace
-        android:id="@+id/workspace"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:paddingTop="?android:attr/actionBarSize"
-        android:paddingBottom="10dp"
-        launcher:defaultScreen="2"
-        launcher:cellCountX="8"
-        launcher:cellCountY="7"
-        launcher:pageSpacing="50dp">
-
-        <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
-        <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
-        <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
-        <include android:id="@+id/cell4" layout="@layout/workspace_screen" />
-        <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
-    </com.android.launcher2.Workspace>
-
-    <include
-        layout="@layout/all_apps_tabbed"
-        android:id="@+id/all_apps_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_gravity="top" />
-
-    <RelativeLayout
-        android:id="@+id/all_apps_button_cluster"
-        android:layout_width="fill_parent"
-        android:layout_height="?android:attr/actionBarSize"
-        android:layout_gravity="top">
-
-       <!-- Global search icon -->
-       <ImageView
-           android:id="@+id/search_button"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:layout_alignParentTop="true"
-           android:layout_alignParentLeft="true"
-           android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
-           android:paddingRight="@dimen/toolbar_button_horizontal_padding"
-           android:paddingTop="@dimen/toolbar_button_vertical_padding"
-           android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-           android:src="@drawable/ic_generic_search"
-           android:background="@drawable/button_bg"
-           android:onClick="onClickSearchButton"
-           android:focusable="true"
-           android:clickable="true" />
-           
-        <ImageView
-            android:id="@+id/search_divider"
-            android:src="@drawable/divider_launcher_holo"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_toRightOf="@id/search_button"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-
-            android:onClick="onClickSearchButton"
-            android:focusable="false"
-            android:clickable="true" />
-
-        <!-- Voice search icon -->
-        <ImageView
-            android:id="@+id/voice_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/search_divider"
-            android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
-            android:paddingRight="@dimen/toolbar_button_horizontal_padding"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-            android:src="@drawable/ic_voice_search"
-            android:background="@drawable/button_bg"
-            android:onClick="onClickVoiceButton"
-            android:focusable="true"
-            android:clickable="true"/>
-
-        <ImageView
-            android:id="@+id/configure_button"
-            android:src="@drawable/ic_home_add_holo_dark"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
-            android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
-            android:paddingRight="@dimen/toolbar_button_horizontal_padding"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-            android:background="@drawable/button_bg"
-
-            android:onClick="onClickConfigureButton"
-            android:focusable="true"
-            android:clickable="true" />
-        <ImageView
-            android:id="@+id/divider"
-            android:src="@drawable/divider_launcher_holo"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_toLeftOf="@id/configure_button"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-
-            android:onClick="onClickAllAppsButton"
-            android:focusable="false"
-            android:clickable="true" />
-        <TextView
-            android:id="@+id/all_apps_button"
-            android:text="@string/all_apps_button_label"
-            android:drawablePadding="@dimen/all_apps_button_drawable_padding"
-            android:drawableLeft="@drawable/ic_home_all_apps_holo_dark"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toLeftOf="@id/divider"
-            android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
-            android:paddingRight="@dimen/toolbar_button_horizontal_padding"
-            android:paddingTop="@dimen/all_apps_button_vertical_padding"
-            android:paddingBottom="@dimen/all_apps_button_vertical_padding"
-            android:background="@drawable/button_bg"
-            
-            android:gravity="center_horizontal|center_vertical"
-            android:textColor="#CCFFFFFF"
-            android:textSize="18sp"
-
-            android:shadowColor="#DA000000"
-            android:shadowDx="0.0"
-            android:shadowDy="0.0"
-            android:shadowRadius="2.5"
-
-            android:onClick="onClickAllAppsButton"
-            android:focusable="true"
-            android:clickable="true" />
-        <ImageView
-            android:id="@+id/divider_during_drag"
-            android:src="@drawable/divider_launcher_holo"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_toLeftOf="@id/configure_button"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-            android:visibility="gone"/>
-        <com.android.launcher2.DeleteZone
-            android:id="@+id/delete_zone"
-            android:text="@string/delete_zone_label_workspace"
-            android:drawablePadding="@dimen/delete_zone_drawable_padding"
-            android:drawableLeft="@drawable/delete_zone_selector"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignRight="@id/configure_button"
-            android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
-            android:paddingRight="@dimen/toolbar_button_horizontal_padding"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-            android:background="@drawable/button_bg"
-
-            android:gravity="center_horizontal|center_vertical"
-            android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
-            android:textSize="18sp"
-            android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
-            android:shadowDx="0.0"
-            android:shadowDy="0.0"
-            android:shadowRadius="2.0"
-
-            android:visibility="gone"
-            launcher:direction="horizontal" />
-    </RelativeLayout>
-
-    <TabHost
-        android:id="@+id/customization_drawer"
-        android:layout_width="match_parent"
-        android:layout_height="480dp"
-        android:layout_gravity="bottom">
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent">
-            <TabWidget
-                android:id="@android:id/tabs"
-                android:layout_width="952dp"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:background="@drawable/tab_unselected_holo"
-                android:tabStripEnabled="false" />
-            <FrameLayout
-                android:id="@android:id/tabcontent"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
-             </FrameLayout>
-          </LinearLayout>
-    </TabHost>
-</com.android.launcher2.DragLayer>
diff --git a/res/layout-xlarge-port/all_apps_tabbed.xml b/res/layout-xlarge-port/all_apps_tabbed.xml
deleted file mode 100644
index 269fa12..0000000
--- a/res/layout-xlarge-port/all_apps_tabbed.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-<com.android.launcher2.AllAppsTabbed
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
-    <LinearLayout
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-        <RelativeLayout
-            android:layout_width="700dp"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_horizontal"
-            android:background="@drawable/tab_unselected_holo">
-            <TabWidget
-                android:id="@android:id/tabs"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentLeft="true"
-                android:tabStripEnabled="false" />
-            <FrameLayout
-                android:id="@+id/market_info_frame"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_centerVertical="true">
-                <com.android.launcher2.ApplicationInfoDropTarget
-                    android:id="@+id/all_apps_info_target"
-                    android:drawableRight="@drawable/ic_home_info_holo_dark"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:visibility="invisible"/>
-                <ImageView
-                    android:id="@+id/market_button"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:onClick="onClickAppMarketButton"/>
-            </FrameLayout>
-            <com.android.launcher2.DeleteZone
-                android:id="@+id/all_apps_delete_zone"
-                android:text="@string/delete_zone_label_all_apps"
-                android:drawablePadding="@dimen/delete_zone_drawable_padding"
-                android:drawableLeft="@drawable/delete_zone_selector"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_toLeftOf="@id/market_info_frame"
-                android:layout_centerVertical="true"
-                android:visibility="invisible"
-                android:paddingRight="22dp"
-                launcher:direction="horizontal"
-
-                android:gravity="center_horizontal|center_vertical"
-                android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
-                android:textSize="18sp"
-                android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
-                android:shadowDx="0.0"
-                android:shadowDy="0.0"
-                android:shadowRadius="2.0" />
-        </RelativeLayout>
-        <FrameLayout
-            android:id="@android:id/tabcontent"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent">
-            <com.android.launcher2.AllAppsPagedView
-                android:id="@+id/all_apps_paged_view"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                launcher:cellCountX="5"
-                launcher:cellCountY="7"
-                launcher:pageLayoutWidthGap="36dp"
-                launcher:pageLayoutHeightGap="36dp"
-                launcher:pageLayoutPaddingTop="25dp"
-                launcher:pageLayoutPaddingBottom="10dp"
-                launcher:pageLayoutPaddingLeft="20dp"
-                launcher:pageLayoutPaddingRight="20dp">
-            </com.android.launcher2.AllAppsPagedView>
-        </FrameLayout>
-    </LinearLayout>
-</com.android.launcher2.AllAppsTabbed>
diff --git a/res/layout-xlarge-port/customization_drawer.xml b/res/layout-xlarge-port/customization_drawer.xml
deleted file mode 100644
index a1bc7cc..0000000
--- a/res/layout-xlarge-port/customization_drawer.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-<com.android.launcher2.CustomizePagedView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
-
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    launcher:wallpaperCellSpanX="3"
-    launcher:wallpaperCellCountX="9"
-    launcher:widgetCellCountX="10"
-    launcher:cellCountX="5"
-    launcher:cellCountY="3"
-    launcher:pageLayoutWidthGap="36dp"
-    launcher:pageLayoutHeightGap="12dp"
-    launcher:pageLayoutPaddingTop="40dp"
-    launcher:pageLayoutPaddingBottom="25dp"
-    launcher:pageLayoutPaddingLeft="20dp"
-    launcher:pageLayoutPaddingRight="20dp" />
diff --git a/res/layout-xlarge-port/launcher.xml b/res/layout-xlarge-port/launcher.xml
deleted file mode 100644
index a8087f4..0000000
--- a/res/layout-xlarge-port/launcher.xml
+++ /dev/null
@@ -1,215 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<com.android.launcher2.DragLayer
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
-
-    android:id="@+id/drag_layer"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <!-- The workspace contains 5 screens of cells -->
-    <com.android.launcher2.Workspace
-        android:id="@+id/workspace"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:paddingTop="?android:attr/actionBarSize"
-        android:paddingBottom="10dp"
-        launcher:defaultScreen="2"
-        launcher:cellCountX="8"
-        launcher:cellCountY="7"
-        launcher:pageSpacing="64dp">
-
-        <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
-        <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
-        <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
-        <include android:id="@+id/cell4" layout="@layout/workspace_screen" />
-        <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
-    </com.android.launcher2.Workspace>
-
-    <include
-        layout="@layout/all_apps_tabbed"
-        android:id="@+id/all_apps_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_gravity="top" />
-
-    <RelativeLayout
-        android:id="@+id/all_apps_button_cluster"
-        android:layout_width="fill_parent"
-        android:layout_height="?android:attr/actionBarSize"
-        android:layout_gravity="top">
-
-       <!-- Global search icon -->
-       <ImageView
-           android:id="@+id/search_button"
-           android:layout_width="wrap_content"
-           android:layout_height="wrap_content"
-           android:layout_alignParentTop="true"
-           android:layout_alignParentLeft="true"
-           android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
-           android:paddingRight="@dimen/toolbar_button_horizontal_padding"
-           android:paddingTop="@dimen/toolbar_button_vertical_padding"
-           android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-           android:src="@drawable/ic_generic_search"
-           android:background="@drawable/button_bg"
-           android:onClick="onClickSearchButton"
-           android:focusable="true"
-           android:clickable="true" />
-           
-        <ImageView
-            android:id="@+id/search_divider"
-            android:src="@drawable/divider_launcher_holo"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_toRightOf="@id/search_button"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-
-            android:onClick="onClickSearchButton"
-            android:focusable="false"
-            android:clickable="true" />
-
-        <!-- Voice search icon -->
-        <ImageView
-            android:id="@+id/voice_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toRightOf="@id/search_divider"
-            android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
-            android:paddingRight="@dimen/toolbar_button_horizontal_padding"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-            android:src="@drawable/ic_voice_search"
-            android:background="@drawable/button_bg"
-            android:onClick="onClickVoiceButton"
-            android:focusable="true"
-            android:clickable="true"/>
-
-        <ImageView
-            android:id="@+id/configure_button"
-            android:src="@drawable/ic_home_add_holo_dark"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
-            android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
-            android:paddingRight="@dimen/toolbar_button_horizontal_padding"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-            android:background="@drawable/button_bg"
-
-            android:onClick="onClickConfigureButton"
-            android:focusable="true"
-            android:clickable="true" />
-        <ImageView
-            android:id="@+id/divider"
-            android:src="@drawable/divider_launcher_holo"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_toLeftOf="@id/configure_button"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-
-            android:onClick="onClickAllAppsButton"
-            android:focusable="false"
-            android:clickable="true" />
-        <TextView
-            android:id="@+id/all_apps_button"
-            android:text="@string/all_apps_button_label"
-            android:drawablePadding="@dimen/all_apps_button_drawable_padding"
-            android:drawableLeft="@drawable/ic_home_all_apps_holo_dark"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_toLeftOf="@id/divider"
-            android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
-            android:paddingRight="@dimen/toolbar_button_horizontal_padding"
-            android:paddingTop="@dimen/all_apps_button_vertical_padding"
-            android:paddingBottom="@dimen/all_apps_button_vertical_padding"
-            android:background="@drawable/button_bg"
-            
-            android:gravity="center_horizontal|center_vertical"
-            android:textColor="#CCFFFFFF"
-            android:textSize="18sp"
-
-            android:shadowColor="#DA000000"
-            android:shadowDx="0.0"
-            android:shadowDy="0.0"
-            android:shadowRadius="2.5"
-
-            android:onClick="onClickAllAppsButton"
-            android:focusable="true"
-            android:clickable="true" />
-        <ImageView
-            android:id="@+id/divider_during_drag"
-            android:src="@drawable/divider_launcher_holo"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_toLeftOf="@id/configure_button"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-            android:visibility="gone"/>
-        <com.android.launcher2.DeleteZone
-            android:id="@+id/delete_zone"
-            android:text="@string/delete_zone_label_workspace"
-            android:drawablePadding="@dimen/delete_zone_drawable_padding"
-            android:drawableLeft="@drawable/delete_zone_selector"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignRight="@id/configure_button"
-            android:paddingLeft="@dimen/toolbar_button_horizontal_padding"
-            android:paddingRight="@dimen/toolbar_button_horizontal_padding"
-            android:paddingTop="@dimen/toolbar_button_vertical_padding"
-            android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-            android:background="@drawable/button_bg"
-
-            android:gravity="center_horizontal|center_vertical"
-            android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
-            android:textSize="18sp"
-            android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
-            android:shadowDx="0.0"
-            android:shadowDy="0.0"
-            android:shadowRadius="2.0"
-
-            android:visibility="gone"
-            launcher:direction="horizontal" />
-    </RelativeLayout>
-
-    <TabHost
-        android:id="@+id/customization_drawer"
-        android:layout_width="match_parent"
-        android:layout_height="800dp"
-        android:layout_gravity="bottom">
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent">
-            <TabWidget
-                android:id="@android:id/tabs"
-                android:layout_width="700dp"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:background="@drawable/tab_unselected_holo"
-                android:tabStripEnabled="false" />
-            <FrameLayout
-                android:id="@android:id/tabcontent"
-                android:layout_width="match_parent"
-                android:layout_height="650dp">
-             </FrameLayout>
-          </LinearLayout>
-    </TabHost>
-</com.android.launcher2.DragLayer>
diff --git a/res/layout-xlarge-port/tab_widget_indicator.xml b/res/layout-xlarge-port/tab_widget_indicator.xml
deleted file mode 100644
index b113b7b..0000000
--- a/res/layout-xlarge-port/tab_widget_indicator.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/TabIndicator.Portrait" />
diff --git a/res/layout-xlarge-port/workspace_screen.xml b/res/layout-xlarge-port/workspace_screen.xml
deleted file mode 100644
index 406441d..0000000
--- a/res/layout-xlarge-port/workspace_screen.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<com.android.launcher2.CellLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
-
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:hapticFeedbackEnabled="false"
-
-    launcher:cellWidth="@dimen/workspace_cell_width"
-    launcher:cellHeight="@dimen/workspace_cell_height"
-    launcher:widthGap="@dimen/workspace_width_gap"
-    launcher:heightGap="@dimen/workspace_height_gap"
-    launcher:yAxisStartPadding="25dip"
-    launcher:yAxisEndPadding="25dip"
-    launcher:xAxisStartPadding="15dip"
-    launcher:xAxisEndPadding="15dip"/>
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
deleted file mode 100644
index fadf736..0000000
--- a/res/layout/all_apps.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<!-- switch to all_apps_3d on devices that support RenderScript -->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <include layout="@layout/all_apps_2d" />
-</merge>
diff --git a/res/layout/all_apps_3d.xml b/res/layout/all_apps_3d.xml
deleted file mode 100644
index 7975df4..0000000
--- a/res/layout/all_apps_3d.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<!-- Replace with AllAppsView to use 2D version -->
-<com.android.launcher2.AllApps3D
-    xmlns:android="http://schemas.android.com/apk/res/android"
-
-    android:id="@+id/all_apps_view"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-
-    android:scrollbarStyle="outsideInset"
-    android:drawSelectorOnTop="false"
-    android:listSelector="@drawable/grid_selector"
-    android:verticalSpacing="10dip"
-    android:numColumns="4"
-    android:fadingEdgeLength="20dip"
-    android:padding="2dip"
-    android:cacheColorHint="#FF000000"
-    />
diff --git a/res/layout/application_list.xml b/res/layout/application_list.xml
deleted file mode 100644
index b515c9e..0000000
--- a/res/layout/application_list.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * 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.
- */
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight"
-
-    android:paddingLeft="10dip"
-
-    android:orientation="horizontal">
-
-    <ImageView android:id="@+id/icon"
-        android:layout_width="@android:dimen/app_icon_size"
-        android:layout_height="@android:dimen/app_icon_size"
-        android:layout_gravity="center_vertical"
-        android:scaleType="fitCenter" />
-
-    <LinearLayout
-        android:layout_width="0dip"
-        android:layout_weight="1.0"
-        android:layout_height="match_parent"
-
-        android:paddingLeft="8dip"
-        android:paddingRight="8dip"
-
-        android:orientation="vertical"
-        android:gravity="center_vertical">
-
-        <TextView android:id="@+id/name"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-
-            android:singleLine="true"
-            android:ellipsize="end"
-
-            android:textAppearance="?android:attr/textAppearanceLarge" />
-
-        <TextView android:id="@+id/description"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-
-            android:layout_below="@id/name"
-            android:layout_alignLeft="@id/name"
-
-            android:singleLine="true"
-            android:ellipsize="end"
-
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorSecondary" />
-
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout-xlarge/all_apps_paged_view_application.xml b/res/layout/apps_customize_application.xml
similarity index 84%
copy from res/layout-xlarge/all_apps_paged_view_application.xml
copy to res/layout/apps_customize_application.xml
index e5f07bf..4f36326 100644
--- a/res/layout-xlarge/all_apps_paged_view_application.xml
+++ b/res/layout/apps_customize_application.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -18,12 +18,15 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
 
-    launcher:blurColor="#FF6B8CF0"
-    launcher:outlineColor="#FF8CD2FF"
+    style="@style/WorkspaceIcon.AllApps"
 
     android:id="@+id/application_icon"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:gravity="center_horizontal"
 
-    style="@style/WorkspaceIcon.AllApps" />
+    launcher:blurColor="#FF6B8CF0"
+    launcher:outlineColor="#FF8CD2FF"
+
+    android:focusable="true"
+    android:background="@drawable/focusable_view_bg" />
diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml
new file mode 100644
index 0000000..05884ef
--- /dev/null
+++ b/res/layout/apps_customize_pane.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<com.android.launcher2.AppsCustomizeTabHost
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher">
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@drawable/apps_customize_bg_gradient">
+        <!-- The layout_width of the tab bar gets overriden to align the content
+             with the text in the tabs in AppsCustomizeTabHost. -->
+        <FrameLayout
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/apps_customize_tab_bar_height"
+            android:layout_gravity="center_horizontal">
+            <com.android.launcher2.FocusOnlyTabWidget
+                android:id="@android:id/tabs"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_gravity="left"
+                android:background="@drawable/tab_unselected_holo"
+                android:tabStripEnabled="false" />
+            <FrameLayout
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_gravity="right">
+                <LinearLayout
+                    android:layout_width="wrap_content"
+                    android:layout_height="match_parent"
+                    android:visibility="gone">
+                    <com.android.launcher2.ApplicationInfoDropTarget
+                        android:id="@+id/all_apps_info_target"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:layout_gravity="center"
+                        android:gravity="center"
+                        android:drawableLeft="@drawable/ic_home_info_holo_dark"
+                        android:background="@drawable/focusable_view_bg"
+                        android:focusable="true"
+                        android:visibility="gone" />
+                    <com.android.launcher2.DeleteZone
+                        style="@style/DeleteZone"
+                        android:id="@+id/all_apps_delete_zone"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:layout_gravity="center"
+                        android:gravity="center"
+                        android:background="@drawable/focusable_view_bg"
+                        android:focusable="true"
+                        android:visibility="gone"
+                        launcher:direction="horizontal" />
+                </LinearLayout>
+                <TextView
+                    style="@style/MarketButton"
+                    android:id="@+id/market_button"
+                    android:layout_width="wrap_content"
+                    android:layout_height="match_parent"
+                    android:layout_gravity="center"
+                    android:gravity="center"
+                    android:background="@drawable/tab_widget_indicator_selector"
+                    android:focusable="true" />
+            </FrameLayout>
+        </FrameLayout>
+        <FrameLayout
+            android:id="@android:id/tabcontent"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <com.android.launcher2.AppsCustomizePagedView
+                android:id="@+id/apps_customize_pane_content"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                launcher:cellCountX="@integer/all_apps_view_cellCountX"
+                launcher:cellCountY="@integer/all_apps_view_cellCountY"
+                launcher:pageLayoutWidthGap="@dimen/all_apps_view_pageLayoutWidthGap"
+                launcher:pageLayoutHeightGap="@dimen/all_apps_view_pageLayoutHeightGap"
+                launcher:pageLayoutPaddingTop="@dimen/all_apps_view_pageLayoutPaddingTop"
+                launcher:pageLayoutPaddingBottom="@dimen/all_apps_view_pageLayoutPaddingBottom"
+                launcher:pageLayoutPaddingLeft="@dimen/all_apps_view_pageLayoutPaddingLeft"
+                launcher:pageLayoutPaddingRight="@dimen/all_apps_view_pageLayoutPaddingRight"
+                launcher:widgetCellWidthGap="@dimen/apps_customize_widget_cell_width_gap"
+                launcher:widgetCellHeightGap="@dimen/apps_customize_widget_cell_height_gap"
+                launcher:widgetCountX="@integer/apps_customize_widget_cell_count_x"
+                launcher:widgetCountY="@integer/apps_customize_widget_cell_count_y"
+                launcher:wallpaperCountX="@integer/apps_customize_wallpaper_cell_count_x"
+                launcher:wallpaperCountY="@integer/apps_customize_wallpaper_cell_count_y" />
+         </FrameLayout>
+      </LinearLayout>
+</com.android.launcher2.AppsCustomizeTabHost>
diff --git a/res/layout-xlarge/customize_paged_view_wallpaper.xml b/res/layout/apps_customize_wallpaper.xml
similarity index 69%
copy from res/layout-xlarge/customize_paged_view_wallpaper.xml
copy to res/layout/apps_customize_wallpaper.xml
index e3be86d..d93825f 100644
--- a/res/layout-xlarge/customize_paged_view_wallpaper.xml
+++ b/res/layout/apps_customize_wallpaper.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -17,23 +17,25 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
 
-    android:layout_width="wrap_content"
-    android:layout_height="365dp"
-    android:paddingLeft="12.5dp"
-    android:paddingRight="12.5dp"
-    android:paddingBottom="50dp"
-    android:gravity="top"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_weight="1"
     android:orientation="vertical"
 
     launcher:blurColor="#FF6B8CF0"
-    launcher:outlineColor="#FF8CD2FF">
+    launcher:outlineColor="#FF8CD2FF"
 
-    <!-- The preview image for the wallpaper. -->
+    android:background="@drawable/focusable_view_bg"
+    android:focusable="true">
+
+    <!-- The wallpaper preview. -->
     <ImageView
-        android:id="@+id/wallpaper_preview"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_weight="1.0"
+        android:id="@+id/widget_preview"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:paddingBottom="10dp"
+        android:adjustViewBounds="true"
         android:scaleType="fitStart" />
 
     <!-- The divider image. -->
@@ -41,16 +43,18 @@
         android:id="@+id/divider"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_weight="0"
         android:paddingTop="10dp"
         android:paddingBottom="10dp"
         android:src="@drawable/widget_divider" />
 
-    <!-- The name of the wallpaper -->
+    <!-- The name of the wallpaper. -->
     <TextView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/wallpaper_name"
+        android:id="@+id/widget_name"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:gravity="left"
+        android:layout_weight="0"
+        android:gravity="left|bottom"
 
         android:textColor="#FFFFFFFF"
         android:textSize="14sp"
diff --git a/res/layout-xlarge/customize_paged_view_widget.xml b/res/layout/apps_customize_widget.xml
similarity index 71%
copy from res/layout-xlarge/customize_paged_view_widget.xml
copy to res/layout/apps_customize_widget.xml
index 3b95ebc..9d0764c 100644
--- a/res/layout-xlarge/customize_paged_view_widget.xml
+++ b/res/layout/apps_customize_widget.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -17,41 +17,34 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
 
-    android:layout_width="wrap_content"
-    android:layout_height="365dp"
-    android:paddingLeft="12.5dp"
-    android:paddingTop="12.5dp"
-    android:paddingRight="12.5dp"
-    android:paddingBottom="50dp"
-    android:gravity="top"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_weight="1"
     android:orientation="vertical"
 
     launcher:blurColor="#FF6B8CF0"
-    launcher:outlineColor="#FF8CD2FF">
+    launcher:outlineColor="#FF8CD2FF"
+
+    android:background="@drawable/focusable_view_bg"
+    android:focusable="true">
 
     <!-- The icon of the widget. -->
     <ImageView
         android:id="@+id/widget_preview"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_weight="1.0"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:paddingBottom="5dp"
+        android:adjustViewBounds="true"
         android:scaleType="fitStart" />
 
-    <!-- The divider image. -->
-    <ImageView
-        android:id="@+id/divider"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:paddingTop="10dp"
-        android:paddingBottom="10dp"
-        android:src="@drawable/widget_divider" />
-
     <!-- The name of the widget. -->
     <TextView xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/widget_name"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:gravity="left"
+        android:layout_weight="0"
+        android:gravity="left|bottom"
 
         android:textColor="#FFFFFFFF"
         android:textSize="14sp"
@@ -69,7 +62,8 @@
         android:id="@+id/widget_dims"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:gravity="left"
+        android:layout_weight="0"
+        android:gravity="left|bottom"
 
         android:textColor="#FF999999"
         android:textSize="14sp"
diff --git a/res/layout-xlarge/tab_widget_indicator.xml b/res/layout/tab_widget_indicator.xml
similarity index 87%
copy from res/layout-xlarge/tab_widget_indicator.xml
copy to res/layout/tab_widget_indicator.xml
index 7794e29..b3694fe 100644
--- a/res/layout-xlarge/tab_widget_indicator.xml
+++ b/res/layout/tab_widget_indicator.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -14,6 +14,6 @@
      limitations under the License.
 -->
 
-<TextView
+<com.android.launcher2.AccessibleTabView
     xmlns:android="http://schemas.android.com/apk/res/android"
     style="@style/TabIndicator" />
diff --git a/res/values-ar-xlarge/strings.xml b/res/values-ar-large/strings.xml
similarity index 100%
rename from res/values-ar-xlarge/strings.xml
rename to res/values-ar-large/strings.xml
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index f872444..cb4c1f3 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"المجلدات"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"المزيد"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"الخلفيات"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"اختصارات التطبيقات"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"اختصارات التطبيقات"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"ستكون هذه علامة تبويب الخلفيات"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"الكل"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"التطبيقات"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"الألعاب"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"منزّلة"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"تطبيقاتي"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"لم يتم العثور على ألعاب"</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"لم يُعثر على تطبيقات منزّلة"</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"ليس لديك أي تطبيقات تم تنزيلها."</string>
+    <string name="market" msgid="2652226429823445833">"تسوق"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"تعذر إسقاط العنصر على هذه الشاشة الرئيسية"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"تحديد أداة للإنشاء"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"اسم المجلد"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"الرئيسية"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"إزالة"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"إزالة"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"بحث"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"البحث الصوتي"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"التطبيقات"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"تخصيص"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"إزالة"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"إزالة التحديث"</string>
     <string name="menu_add" msgid="3065046628354640854">"إضافة"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"إدارة التطبيقات"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"خلفية"</string>
diff --git a/res/values-bg-xlarge/strings.xml b/res/values-bg-large/strings.xml
similarity index 100%
rename from res/values-bg-xlarge/strings.xml
rename to res/values-bg-large/strings.xml
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 2686210..0f0f07d 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Папки"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Още"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Тапети"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Преки пътища на приложения"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Преки пътища на приложения"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Това ще бъде разделът с тапети"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Всички"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Приложения"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Игри"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Изтеглени"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Моите приложения"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Няма намерени игри."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Няма изтеглени приложения."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Нямате изтеглени приложения."</string>
+    <string name="market" msgid="2652226429823445833">"Магазин"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Елементът не можа да се премести на началния екран"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Избор на създаващо приспособление"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Име на папка"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Начало"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Премахване"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Деинсталиране"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Търсене"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Гласово търсене"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Приложения"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Персонализиране"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Премахване"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Деинстал. на актуализацията"</string>
     <string name="menu_add" msgid="3065046628354640854">"Добавяне"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Управление на приложенията"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Тапет"</string>
diff --git a/res/values-ca-xlarge/strings.xml b/res/values-ca-large/strings.xml
similarity index 100%
rename from res/values-ca-xlarge/strings.xml
rename to res/values-ca-large/strings.xml
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 8051418..85058ba 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Carpetes"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Més"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Empaperats"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Dreceres d\'aplicacions"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Dreceres d\'aplicacions"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Aquesta serà la pestanya dels empaperats"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Totes"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicacions"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Jocs"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Baixat"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Les meves aplicacions"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"No s\'ha trobat cap joc."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"No s\'ha trobat cap aplicació baixada."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"No has baixat cap aplicació."</string>
+    <string name="market" msgid="2652226429823445833">"Botiga"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"No s\'ha pogut trasll. l\'element a la pant. d\'inici"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Selecciona un widget per crear-lo"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Nom de la carpeta"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Pàgina d\'inici"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Elimina"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstal·la"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Cerca"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Cerca per veu"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicacions"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Personalitza"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Elimina"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstal·la l\'actualització"</string>
     <string name="menu_add" msgid="3065046628354640854">"Afegeix"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Gestiona les aplicacions"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Empaperat"</string>
diff --git a/res/values-cs-xlarge/strings.xml b/res/values-cs-large/strings.xml
similarity index 100%
rename from res/values-cs-xlarge/strings.xml
rename to res/values-cs-large/strings.xml
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index b61068e..af04cb6 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Složky"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Další"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Tapety"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Zástupci aplikací"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Zástupci aplikací"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Toto bude karta Tapety"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Vše"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplikace"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Hry"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Stažené"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Moje aplikace"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Nenalezeny žádné hry."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Žádné stažené aplikace."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nemáte žádné stažené aplikace."</string>
+    <string name="market" msgid="2652226429823445833">"Obchod"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Na tuto plochu nelze položku přetáhnout"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Vyberte widget"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Název složky"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Plocha"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odebrat"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinstalovat"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Hledat"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Hlasové vyhledávání"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplikace"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizovat"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Odebrat"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinstalovat aktualizaci"</string>
     <string name="menu_add" msgid="3065046628354640854">"Přidat"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Spravovat aplikace"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Tapeta"</string>
diff --git a/res/values-da-xlarge/strings.xml b/res/values-da-large/strings.xml
similarity index 100%
rename from res/values-da-xlarge/strings.xml
rename to res/values-da-large/strings.xml
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 66386a6..10bd77f 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Mapper"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Flere"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Tapeter"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Programgenvej"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Programgenveje"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Dette er fanen for tapeter"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Alle"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Programmer"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Spil"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Downloadet"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mine apps"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Ingen spil."</string>
     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Du har ingen downloadede applikationer."</string>
+    <string name="market" msgid="2652226429823445833">"Butik"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Kunne ikke slippe elementet på denne startskærm"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Vælg widget for at oprette"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Mappenavn"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Start"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Fjern"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Afinstaller"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Søg"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Stemmesøgning"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Programmer"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Tilpas"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Fjern"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Afinstaller opdatering"</string>
     <string name="menu_add" msgid="3065046628354640854">"Tilføj"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Administrer programmer"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Tapet"</string>
diff --git a/res/values-de-xlarge/strings.xml b/res/values-de-large/strings.xml
similarity index 100%
rename from res/values-de-xlarge/strings.xml
rename to res/values-de-large/strings.xml
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index e035b27..87124a3 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -25,20 +25,21 @@
     <string name="chooser_wallpaper" msgid="5988031014201479733">"Hintergrund auswählen"</string>
     <string name="wallpaper_instructions" msgid="4215640646180727542">"Hintergrund festlegen"</string>
     <string name="pick_wallpaper" msgid="5630222540525626723">"Hintergrundbilder"</string>
-    <string name="activity_not_found" msgid="5591731020063337696">"Die Anwendung ist nicht installiert."</string>
+    <string name="activity_not_found" msgid="5591731020063337696">"Anwendung ist nicht installiert."</string>
     <string name="configure_wallpaper" msgid="2820186271419674623">"Konfigurieren..."</string>
     <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
     <string name="folders_tab_label" msgid="1145293785541489736">"Ordner"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Mehr"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Hintergründe"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"App-Verknüpfungen"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"App-Verknüpfungen"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Dies ist der Tab \"Hintergründe\""</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Alle"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Spiele"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Heruntergeladen"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Meine Apps"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Keine Spiele gefunden."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Keine heruntergeladenen Apps gefunden"</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Keine heruntergeladenen Anwendungen vorhanden"</string>
+    <string name="market" msgid="2652226429823445833">"Shop"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Element wurde nicht auf Startbildschirm abgelegt."</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Widget für Erstellung auswählen"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Ordnername"</string>
@@ -46,7 +47,7 @@
     <string name="rename_action" msgid="6016003384693240896">"OK"</string>
     <string name="cancel_action" msgid="3811860427489435048">"Abbrechen"</string>
     <string name="menu_item_add_item" msgid="6233177331075781114">"Zum Startbildschirm hinzufügen"</string>
-    <string name="group_applications" msgid="4118484163419674240">"Anwendungen"</string>
+    <string name="group_applications" msgid="4118484163419674240">"Apps"</string>
     <string name="group_shortcuts" msgid="9133529424900391877">"Verknüpfungen"</string>
     <string name="group_folder" msgid="5143593791798929193">"Neuer Ordner"</string>
     <string name="group_live_folders" msgid="2664945399140647217">"Ordner"</string>
@@ -62,10 +63,16 @@
     <string name="title_select_shortcut" msgid="2858897527672831763">"Tastenkürzel auswählen"</string>
     <string name="title_select_application" msgid="8031072293115454221">"Anwendung auswählen"</string>
     <string name="title_select_live_folder" msgid="3753447798805166749">"Ordner auswählen"</string>
-    <string name="all_apps_button_label" msgid="2578400570124163469">"Anwendungen"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Apps"</string>
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Startseite"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Entfernen"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Deinstallieren"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Suchen"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Sprachsuche"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Apps"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Anpassen"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Entfernen"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Update deinstallieren"</string>
     <string name="menu_add" msgid="3065046628354640854">"Hinzufügen"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Apps verwalten"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Hintergrund"</string>
diff --git a/res/values-el-xlarge/strings.xml b/res/values-el-large/strings.xml
similarity index 100%
rename from res/values-el-xlarge/strings.xml
rename to res/values-el-large/strings.xml
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index e8b518fe..59ef926 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Φάκελοι"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Περισσότερα"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Ταπετσαρίες"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Συντομεύσεις Εφαρμογών"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Συντομεύσεις εφαρμογών"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Αυτή θα είναι η καρτέλα ταπετσαριών"</string>
-    <string name="all_apps_tab_all" msgid="2942727589595027258">"Κάθε ηλικία"</string>
+    <string name="all_apps_tab_all" msgid="2942727589595027258">"Όλες"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Εφαρμογές"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Παιχνίδια"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Η λήψη ολοκληρώθηκε"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Οι εφαρμογές μου"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Δεν βρέθηκαν παιχνίδια."</string>
     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Δεν υπάρχουν εφαρμογές από λήψη."</string>
+    <string name="market" msgid="2652226429823445833">"Αγορές"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Δεν έγινε η απόθ. του στοιχείου στην αρχική οθόνη"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Επιλογή γραφ. στοιχείου δημιουργίας"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Όνομα φακέλου"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Αρχική σελίδα"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Κατάργηση"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Κατάργηση εγκατάστασης"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Αναζήτηση"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Φωνητική αναζήτηση"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Εφαρμογές"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Προσαρμογή"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Κατάργηση"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Κατάργηση εγκατάστασης ενημέρωσης"</string>
     <string name="menu_add" msgid="3065046628354640854">"Προσθήκη"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Διαχείριση εφαρμογών"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Ταπετσαρία"</string>
diff --git a/res/values-en-rGB-xlarge/strings.xml b/res/values-en-rGB-large/strings.xml
similarity index 75%
rename from res/values-en-rGB-xlarge/strings.xml
rename to res/values-en-rGB-large/strings.xml
index 60042b2..276ab94 100644
--- a/res/values-en-rGB-xlarge/strings.xml
+++ b/res/values-en-rGB-large/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="wallpaper_dialog_title" msgid="5764793286524787718">"Select wallpaper"</string>
-    <string name="wallpaper_chooser_empty" msgid="7358237455389125747">"No wallpaper available"</string>
-    <string name="wallpaper_cancel" msgid="6502936522490675611">"Cancel"</string>
+    <string name="wallpaper_dialog_title" msgid="8362944198120933329">"Select wallpaper"</string>
+    <string name="wallpaper_chooser_empty" msgid="6543937491391049913">"No wallpaper available"</string>
+    <string name="wallpaper_cancel" msgid="5942480248232268588">"Cancel"</string>
 </resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index f15a01c..f07752c 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Folders"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"More"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Wallpaper"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"App Shortcuts"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"App shortcuts"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"This will be the wallpaper tab"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"All"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Games"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Downloaded"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"My apps"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"No games found."</string>
     <string name="all_apps_no_downloads" msgid="2284720393234453761">"You have no downloaded applications."</string>
+    <string name="market" msgid="2652226429823445833">"Shop"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Could not drop item onto this home screen"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Select widget to create"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Folder name"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remove"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Uninstall"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Search"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Voice Search"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Applications"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Customise"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Remove"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Uninstall update"</string>
     <string name="menu_add" msgid="3065046628354640854">"Add"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Manage apps"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Wallpaper"</string>
diff --git a/res/values-es-xlarge/strings.xml b/res/values-es-large/strings.xml
similarity index 100%
rename from res/values-es-xlarge/strings.xml
rename to res/values-es-large/strings.xml
diff --git a/res/values-es-rUS-xlarge/strings.xml b/res/values-es-rUS-large/strings.xml
similarity index 100%
rename from res/values-es-rUS-xlarge/strings.xml
rename to res/values-es-rUS-large/strings.xml
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index ede2003..46781f1 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Carpetas"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Más"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Papeles tapiz"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Accesos directos a aplicaciones"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Accesos directos a aplicaciones"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Ésta será la pestaña para los papeles tapiz"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Todos"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicaciones"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Juegos"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Descargado"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mis aplicaciones"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"No se encontraron juegos."</string>
     <string name="all_apps_no_downloads" msgid="2284720393234453761">"No has descargado ninguna aplicación."</string>
+    <string name="market" msgid="2652226429823445833">"Comprar"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"No se pudo colocar el elemento en esta pantalla principal"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Seleccionar widget para crear"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Nombre de carpeta"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Página principal"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Quitar"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Buscar"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Búsqueda por voz"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicaciones"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizar"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Eliminar"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar la actualización"</string>
     <string name="menu_add" msgid="3065046628354640854">"Agregar"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Administrar aplicaciones"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Papel tapiz"</string>
@@ -82,7 +89,7 @@
     <string name="permlab_install_shortcut" msgid="1201690825493376489">"instalar accesos directos"</string>
     <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Permite a una aplicación agregar accesos directos sin intervención del usuario."</string>
     <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"desinstalar papel tapiz"</string>
-    <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Permite a una aplicación suprimir accesos directos sin intervención del usuario."</string>
+    <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Permite a una aplicación eliminar accesos directos sin intervención del usuario."</string>
     <string name="permlab_read_settings" msgid="3452408290738106747">"leer configuración y accesos directos de la página principal"</string>
     <string name="permdesc_read_settings" msgid="8377434937176025492">"Permite a una aplicación leer la configuración y los accesos directos de la página principal."</string>
     <string name="permlab_write_settings" msgid="1360567537236705628">"escribir configuración y accesos directos de la página principal"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index bca032c..3d162b9 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Carpetas"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Más"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Fondos de pantalla"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Accesos directos de aplicaciones"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Accesos directos de aplicaciones"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Será la carpeta de fondos de pantalla."</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Todas las aplicaciones"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicaciones"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Juegos"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Descargadas"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mis aplicaciones"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"No hay juegos."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Sin aplicaciones descargadas"</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"No tienes aplicaciones descargadas."</string>
+    <string name="market" msgid="2652226429823445833">"Tienda"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"No se puede soltar el elemento en este escritorio."</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Seleccionar widget"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Nombre de carpeta"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Inicio"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eliminar del  escritorio"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Buscar"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Búsqueda por voz"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicaciones"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizar"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Eliminar"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar actualización"</string>
     <string name="menu_add" msgid="3065046628354640854">"Añadir"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Administrar aplicaciones"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Fondo de pantalla"</string>
diff --git a/res/values-fa-xlarge/strings.xml b/res/values-fa-large/strings.xml
similarity index 100%
rename from res/values-fa-xlarge/strings.xml
rename to res/values-fa-large/strings.xml
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 4e2b7d3..1170d79 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"پوشه ها"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"بیشتر"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"تصاویر زمینه"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"میانبرهای برنامه کاربردی"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"میانبرهای برنامه"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"این برگه تصاویر زمینه خواهد بود"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"همه"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"برنامه های کاربردی"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"بازی ها"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"دانلود شد"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"برنامه های من"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"هیچ بازی پیدا نشد."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"هیچ برنامه دانلود شده ای پیدا نشد."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"شما هیچ برنامه کاربردی دانلود شده ای ندارید."</string>
+    <string name="market" msgid="2652226429823445833">"فروشگاه"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"نمی توان موردی در این صفحه اصلی انداخت"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"انتخاب ابزارک جهت ایجاد"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"نام پوشه"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"صفحه اصلی"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"حذف"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"حذف نصب"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"جستجو"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"جستجوی صوتی"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"برنامه های کاربردی"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"سفارشی کردن"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"حذف"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"حذف نصب به روزرسانی"</string>
     <string name="menu_add" msgid="3065046628354640854">"افزودن"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"مدیریت برنامه ها"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"تصویر زمینه"</string>
diff --git a/res/values-fi-xlarge/strings.xml b/res/values-fi-large/strings.xml
similarity index 100%
rename from res/values-fi-xlarge/strings.xml
rename to res/values-fi-large/strings.xml
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 5ea5af6..4e40e56 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Kansiot"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Lisää"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Taustakuvat"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Sovelluspikakuvakkeet"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Sovelluspikakuvakkeet"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Tämä on taustakuvavälilehti"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Kaikki"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Sovellukset"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Pelit"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Ladatut"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Omat sovellukset"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Ei pelejä."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Ei ladattuja sovelluksia."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Ei ladattuja sovelluksia."</string>
+    <string name="market" msgid="2652226429823445833">"Myymälä"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Kohdetta ei voi lisätä etusivulle"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Valitse luotava widget"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Kansion nimi"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Etusivu"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Poista"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Poista"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Haku"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Äänihaku"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Sovellukset"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Muokkaa"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Poista"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Poista päivitys"</string>
     <string name="menu_add" msgid="3065046628354640854">"Lisää"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Hallinnoi sovelluksia"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Taustakuva"</string>
diff --git a/res/values-fr-xlarge/strings.xml b/res/values-fr-large/strings.xml
similarity index 100%
rename from res/values-fr-xlarge/strings.xml
rename to res/values-fr-large/strings.xml
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 170dcfd..83d71d8 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Dossiers"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Plus"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Fonds d\'écran"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Raccourcis des applications"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Raccourcis applications"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Onglet des fonds d\'écran"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Toutes"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Applications"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Jeux"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Téléchargées"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mes applications"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Aucun jeu n\'a été trouvé."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Aucune application téléchargée trouvée"</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Vous n\'avez téléchargé aucune application."</string>
+    <string name="market" msgid="2652226429823445833">"Acheter"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Impossible de déposer l\'élément sur l\'écran d\'accueil."</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Sélectionner le widget à créer"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Nom du dossier"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Page d\'accueil"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Supprimer"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Désinstaller"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Rechercher"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Recherche vocale"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Applications"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Personnaliser"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Supprimer"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Désinstaller la mise à jour"</string>
     <string name="menu_add" msgid="3065046628354640854">"Ajouter"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Gérer les applications"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Fond d\'écran"</string>
diff --git a/res/values-hr-xlarge/strings.xml b/res/values-hr-large/strings.xml
similarity index 100%
rename from res/values-hr-xlarge/strings.xml
rename to res/values-hr-large/strings.xml
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index c93d64b..34487a5 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Mape"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Više"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Pozadinske slike"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Prečaci aplikacija"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Prečaci aplikacija"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Ovo će biti kartica pozadinske slike"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Sve"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplikacije"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Igre"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Preuzeto"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Moje aplikacije"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Igre nisu pronađene."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nema preuzetih aplikacija"</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nemate preuzetih aplikacija"</string>
+    <string name="market" msgid="2652226429823445833">"Trgovina"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Nije bilo moguće spustiti stavku na početni zaslon"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Odabir widgeta za stvaranje"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Naziv mape"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Početna"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Ukloni"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Deinstaliraj"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Pretraži"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Glasovno pretraživanje"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplikacije"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Prilagodi"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Ukloni"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Deinstalacija ažuriranja"</string>
     <string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Upravljaj aplikacijama"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Pozadinska slika"</string>
diff --git a/res/values-hu-xlarge/strings.xml b/res/values-hu-large/strings.xml
similarity index 100%
rename from res/values-hu-xlarge/strings.xml
rename to res/values-hu-large/strings.xml
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index af42d2d..dfa267b 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Mappák"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Egyebek"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Háttérképek"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Alkalmazás-parancsikonok"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Alkalmazás-parancsikonok"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Ez lesz a háttérképek lapja"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Összes"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Alkalmazások"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Játékok"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Letöltött"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Saját alkalmazások"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Nincsenek játékok."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nincs letöltött alk."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nincsenek letöltött alkalmazásai."</string>
+    <string name="market" msgid="2652226429823445833">"Bolt"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Nem lehet elhelyezni az elemet ezen a főoldalon"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"A létrehozandó modul kiválasztása"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Mappa neve"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Főoldal"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eltávolítás"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Eltávolítás"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Keresés"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Hangalapú keresés"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Alkalmazások"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Személyre szabás"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Törlés"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Eltávolítja a frissítést"</string>
     <string name="menu_add" msgid="3065046628354640854">"Hozzáadás"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Alkalmazások kezelése"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Háttérkép"</string>
diff --git a/res/values-in-xlarge/strings.xml b/res/values-in-large/strings.xml
similarity index 100%
rename from res/values-in-xlarge/strings.xml
rename to res/values-in-large/strings.xml
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 22b5dde..d9a6d28 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Map"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Lainnya"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Wallpaper"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Pintasan App"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Pintasan apl"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Ini akan menjadi tab wallpaper"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Semua"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Permainan"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Diunduh"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Apl saya"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Tidak ditemukan permainan."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Tidak ada aplikasi yang diunduh."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Anda tidak memiliki aplikasi yang diunduh."</string>
+    <string name="market" msgid="2652226429823445833">"Belanja"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Tidak dapat menaruh item pada layar utama ini"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Pilih widget untuk membuat"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Nama map"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Rumah"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Hapus"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Copot pemasangan"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Telusuri"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Penelusuran Suara"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplikasi"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Ubahsuaikan"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Hapus"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Copot pemasangan pemutakhiran"</string>
     <string name="menu_add" msgid="3065046628354640854">"Tambahkan"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Mengelola aplikasi"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Wallpaper"</string>
diff --git a/res/values-it-xlarge/strings.xml b/res/values-it-large/strings.xml
similarity index 75%
rename from res/values-it-xlarge/strings.xml
rename to res/values-it-large/strings.xml
index e667b75..249f880 100644
--- a/res/values-it-xlarge/strings.xml
+++ b/res/values-it-large/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="wallpaper_dialog_title" msgid="5764793286524787718">"Seleziona sfondo"</string>
-    <string name="wallpaper_chooser_empty" msgid="7358237455389125747">"Nessuno sfondo disponibile"</string>
-    <string name="wallpaper_cancel" msgid="6502936522490675611">"Annulla"</string>
+    <string name="wallpaper_dialog_title" msgid="8362944198120933329">"Seleziona sfondo"</string>
+    <string name="wallpaper_chooser_empty" msgid="6543937491391049913">"Nessuno sfondo disponibile"</string>
+    <string name="wallpaper_cancel" msgid="5942480248232268588">"Annulla"</string>
 </resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 62112b4..0a1f4fd 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Cartelle"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Altro"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Sfondi"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Scorciatoie applicazioni"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Scorciatoie applicazioni"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Questa sarà la scheda degli sfondi"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Tutte"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Applicazioni"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Giochi"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Scaricate"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Le mie applicazioni"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Nessun gioco trovato."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nessuna applicazione scaricata trovata."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Non hai applicazioni scaricate."</string>
+    <string name="market" msgid="2652226429823445833">"Acquista"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Impossibile rilasciare elemento in schermata Home"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Seleziona il widget da creare"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Nome cartella"</string>
@@ -56,7 +57,7 @@
     <string name="add_clock" msgid="2337943840175865746">"Orologio"</string>
     <string name="add_photo_frame" msgid="3154058437359487954">"Cornice immagini"</string>
     <string name="out_of_space" msgid="8365249326091984698">"Spazio nella schermata Home esaurito."</string>
-    <string name="shortcut_installed" msgid="7071557296331322355">"Scoriciatoia \"<xliff:g id="NAME">%s</xliff:g>\" creata."</string>
+    <string name="shortcut_installed" msgid="7071557296331322355">"Scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" creata."</string>
     <string name="shortcut_uninstalled" msgid="2129499669449749995">"La scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" è stata rimossa."</string>
     <string name="shortcut_duplicate" msgid="4757756326465060694">"Scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" già presente."</string>
     <string name="title_select_shortcut" msgid="2858897527672831763">"Seleziona scorciatoia"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Rimuovi"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Disinstalla"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Cerca"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Ricerca vocale"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Applicazioni"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizza"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Rimuovi"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Disinstalla aggiornamento"</string>
     <string name="menu_add" msgid="3065046628354640854">"Aggiungi"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Gestisci applicazioni"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Sfondo"</string>
diff --git a/res/values-iw-xlarge/strings.xml b/res/values-iw-large/strings.xml
similarity index 100%
rename from res/values-iw-xlarge/strings.xml
rename to res/values-iw-large/strings.xml
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index cb80a49..535cf73 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"תיקיות"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"עוד"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"טפטים"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"קיצורי דרך של יישומים"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"קיצורי דרך של יישומים"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"זו תהיה כרטיסיית הטפטים"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"הכל"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"יישומים"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"משחקים"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"מהורדות"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"היישומים שלי"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"לא נמצאו משחקים."</string>
     <string name="all_apps_no_downloads" msgid="2284720393234453761">"לא הורדת יישומים."</string>
+    <string name="market" msgid="2652226429823445833">"קנה"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"אין אפשרות להניח פריט במסך בית זה"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"בחר widget כדי ליצור"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"שם תיקיה"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"דף הבית"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"הסר"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"הסר התקנה"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"חפש"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"חיפוש קולי"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"יישומים"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"התאם אישית"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"הסר"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"הסר את התקנת העדכון"</string>
     <string name="menu_add" msgid="3065046628354640854">"הוסף"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"נהל יישומים"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"טפט"</string>
diff --git a/res/values-ja-xlarge/strings.xml b/res/values-ja-large/strings.xml
similarity index 100%
rename from res/values-ja-xlarge/strings.xml
rename to res/values-ja-large/strings.xml
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 9d45452..4b2d31d 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"フォルダ"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"その他"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"壁紙"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"アプリのショートカット"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"アプリのショートカット"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"ここが壁紙タブになります"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"すべて"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"アプリ"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"ゲーム"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"ダウンロード済み"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"マイアプリ"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"ゲームなし"</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"ダウンロードしたアプリケーションは見つかりません。"</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"ダウンロードしたアプリケーションはありません。"</string>
+    <string name="market" msgid="2652226429823445833">"ショップ"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"このホーム画面にアイテムをドロップできませんでした"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"作成するウィジェットを選択"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"フォルダ名"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"ホーム"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"削除"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"アンインストール"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"検索"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"音声検索"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"アプリケーション"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"カスタマイズ"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"削除"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"アップデートをアンインストール"</string>
     <string name="menu_add" msgid="3065046628354640854">"追加"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"アプリの管理"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"壁紙"</string>
diff --git a/res/values-ko-xlarge/strings.xml b/res/values-ko-large/strings.xml
similarity index 100%
rename from res/values-ko-xlarge/strings.xml
rename to res/values-ko-large/strings.xml
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 5bd3246..9f6ee4a 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"폴더"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"더보기"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"배경화면"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"앱 바로가기"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"앱 바로가기"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"배경화면 탭이 됩니다."</string>
-    <string name="all_apps_tab_all" msgid="2942727589595027258">"모두"</string>
+    <string name="all_apps_tab_all" msgid="2942727589595027258">"전체"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"애플리케이션"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"게임"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"다운로드됨"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"내 애플리케이션"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"게임이 없습니다."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"다운로드한 애플리케이션이 없습니다."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"다운로드한 애플리케이션이 없습니다."</string>
+    <string name="market" msgid="2652226429823445833">"쇼핑"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"홈 화면에 항목을 드롭할 수 없습니다."</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"만들 위젯 선택"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"폴더 이름"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"홈"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"삭제"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"제거"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"검색"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"음성 검색"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"애플리케이션"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"맞춤설정"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"삭제"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"업데이트 제거"</string>
     <string name="menu_add" msgid="3065046628354640854">"추가"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"애플리케이션 관리"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"배경화면"</string>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 159cbb4..e1b0214 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -17,5 +17,23 @@
 <resources>
     <dimen name="workspace_cell_width">106dip</dimen>
     <dimen name="workspace_cell_height">74dip</dimen>
+    <dimen name="folder_cell_width">100dip</dimen>
+    <dimen name="folder_cell_height">74dip</dimen>
     <dimen name="button_bar_height">62dip</dimen>
+
+    <integer name="all_apps_view_cellCountX">6</integer>
+    <integer name="all_apps_view_cellCountY">3</integer>
+    <dimen name="all_apps_view_pageLayoutWidthGap">10dp</dimen>
+    <dimen name="all_apps_view_pageLayoutHeightGap">5dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingTop">10dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingBottom">10dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingLeft">2dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingRight">2dp</dimen>
+
+    <dimen name="apps_customize_widget_cell_width_gap">30dp</dimen>
+    <dimen name="apps_customize_widget_cell_height_gap">0dp</dimen>
+    <integer name="apps_customize_widget_cell_count_x">3</integer>
+    <integer name="apps_customize_widget_cell_count_y">1</integer>
+    <integer name="apps_customize_wallpaper_cell_count_x">3</integer>
+    <integer name="apps_customize_wallpaper_cell_count_y">1</integer>
 </resources>
diff --git a/res/values-large-land/dimens.xml b/res/values-large-land/dimens.xml
new file mode 100644
index 0000000..196cdb0
--- /dev/null
+++ b/res/values-large-land/dimens.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<resources>
+    <!-- the area at the edge of the screen that makes the workspace go left
+         or right while you're dragging. -->
+    <dimen name="scroll_zone">100dip</dimen>
+
+    <dimen name="customization_drawer_height">480dp</dimen>
+    <dimen name="customization_drawer_content_height">420dp</dimen>
+
+    <integer name="all_apps_view_cellCountX">7</integer>
+    <integer name="all_apps_view_cellCountY">5</integer>
+    <dimen name="all_apps_view_pageLayoutWidthGap">36dp</dimen>
+    <dimen name="all_apps_view_pageLayoutHeightGap">6dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingTop">20dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingBottom">14dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingLeft">40dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingRight">40dp</dimen>
+
+    <integer name="customization_drawer_contents_wallpaperCellSpanX">3</integer>
+    <integer name="customization_drawer_contents_wallpaperCellCountX">12</integer>
+    <integer name="customization_drawer_contents_widgetCellCountX">14</integer>
+    <integer name="customization_drawer_contents_cellCountX">8</integer>
+    <integer name="customization_drawer_contents_cellCountY">3</integer>
+    <dimen name="customization_drawer_contents_pageLayoutWidthGap">32dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values-large-port/dimens.xml b/res/values-large-port/dimens.xml
new file mode 100644
index 0000000..47cac78
--- /dev/null
+++ b/res/values-large-port/dimens.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<resources>
+    <!-- the area at the edge of the screen that makes the workspace go left
+         or right while you're dragging. -->
+    <dimen name="scroll_zone">40dp</dimen>
+
+    <dimen name="customization_drawer_height">800dp</dimen>
+    <dimen name="customization_drawer_content_height">420dp</dimen>
+
+    <integer name="all_apps_view_cellCountX">5</integer>
+    <integer name="all_apps_view_cellCountY">7</integer>
+    <dimen name="all_apps_view_pageLayoutWidthGap">36dp</dimen>
+    <dimen name="all_apps_view_pageLayoutHeightGap">36dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingTop">25dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingBottom">10dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingLeft">20dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingRight">20dp</dimen>
+
+    <integer name="customization_drawer_contents_wallpaperCellSpanX">3</integer>
+    <integer name="customization_drawer_contents_wallpaperCellCountX">9</integer>
+    <integer name="customization_drawer_contents_widgetCellCountX">9</integer>
+    <integer name="customization_drawer_contents_cellCountX">5</integer>
+    <integer name="customization_drawer_contents_cellCountY">3</integer>
+    <dimen name="customization_drawer_contents_pageLayoutWidthGap">36dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/res/values-large/config.xml b/res/values-large/config.xml
new file mode 100644
index 0000000..99ee1ec
--- /dev/null
+++ b/res/values-large/config.xml
@@ -0,0 +1,32 @@
+<resources>
+<!-- AllApps/Customize/AppsCustomize -->
+    <!-- Fade/zoom in/out duration & scale in the Customize transition.
+         Note: This should be less than the workspaceShrinkTime as they happen together. -->
+    <integer name="config_customizeZoomInTime">800</integer>
+    <integer name="config_customizeZoomOutTime">600</integer>
+    <integer name="config_customizeZoomScaleFactor">7</integer>
+    <integer name="config_customizeFadeInTime">800</integer>
+
+    <!-- The slope, in percent, of the drag movement needed to drag an item out of
+         Customize (y / x * 100%)  -->
+    <integer name="config_customizationDrawerDragSlopeThreshold">150</integer>
+
+    <!-- Duration in milliseconds of the animations between all apps, customize, & home.
+         NOTE: If these are changed, the toolbar animation times below should also be. -->
+    <integer name="config_customizeWorkspaceShrinkTime">800</integer>
+
+<!-- Workspace -->
+    <!-- When dragging items on the workspace, how much bigger (in pixels) the dragged view
+         should be, as compared to the original view. If 0, it will not be scaled at all.
+         Should be an even number, for pixel alignment. -->
+    <integer name="config_dragViewExtraPixels">0</integer>
+
+    <!-- When items are dropped on the mini screens in customize mode, we have a bounce animation
+         of the bright green hover outline, and then fade out the outline at the end. These are
+         the values used in that animation -->
+    <integer name="config_screenOnDropScalePercent">120</integer>
+    <integer name="config_screenOnDropScaleUpDuration">200</integer>
+    <integer name="config_screenOnDropScaleDownDuration">200</integer>
+    <integer name="config_screenOnDropAlphaFadeDelay">350</integer>
+    <integer name="config_screenOnDropAlphaFadeDuration">50</integer>
+</resources>
diff --git a/res/values-xlarge/dimens.xml b/res/values-large/dimens.xml
similarity index 61%
rename from res/values-xlarge/dimens.xml
rename to res/values-large/dimens.xml
index c4988e4..2416109 100644
--- a/res/values-xlarge/dimens.xml
+++ b/res/values-large/dimens.xml
@@ -15,12 +15,28 @@
 -->
 
 <resources>
+    <dimen name="apps_customize_cell_width">96dp</dimen>
+    <dimen name="apps_customize_cell_height">96dp</dimen>
     <dimen name="workspace_cell_width">96dip</dimen>
     <dimen name="workspace_cell_height">96dip</dimen>
 
+    <dimen name="workspace_x_axis_start_padding_land">25dip</dimen>
+    <dimen name="workspace_x_axis_end_padding_land">25dip</dimen>
+    <dimen name="workspace_y_axis_start_padding_land">15dip</dimen>
+    <dimen name="workspace_y_axis_end_padding_land">15dip</dimen>
+    <dimen name="workspace_x_axis_start_padding_port">15dip</dimen>
+    <dimen name="workspace_x_axis_end_padding_port">15dip</dimen>
+    <dimen name="workspace_y_axis_start_padding_port">25dip</dimen>
+    <dimen name="workspace_y_axis_end_padding_port">25dip</dimen>
+
     <!-- Width/height gap overrides for the workspace -->
-    <dimen name="workspace_width_gap">0dp</dimen>
-    <dimen name="workspace_height_gap">0dp</dimen>
+    <dimen name="workspace_width_gap_land">32dp</dimen>
+    <dimen name="workspace_height_gap_land">2dp</dimen>
+    <dimen name="workspace_width_gap_port">0dp</dimen>
+    <dimen name="workspace_height_gap_port">32dp</dimen>
+
+    <dimen name="workspace_page_spacing_land">50dp</dimen>
+    <dimen name="workspace_page_spacing_port">64dp</dimen>
 
     <!-- The corner radius to draw the external drop icon rounded rect -->
     <dimen name="external_drop_icon_rect_radius">10dp</dimen>
@@ -28,6 +44,9 @@
     <!-- Size of icons in workspace -->
     <dimen name="app_icon_size">72dp</dimen>
 
+    <!-- Size of content of icons in workspace, as specified by the android icon guidelines -->
+    <dimen name="app_icon_content_size">60dp</dimen>
+
     <!-- extra horizontal spacing between mini screen thumbnails ie. in all
          apps and in customization mode -->
     <dimen name="smallScreenExtraSpacing">0dip</dimen>
@@ -37,15 +56,12 @@
     <dimen name="allAppsSmallScreenVerticalMarginLandscape">30dip</dimen>
     <dimen name="allAppsSmallScreenVerticalMarginPortrait">60dip</dimen>
 
-    <!-- Vertical spacing between edge of screen and mini cell layouts when they
-         are minimized to the top when the customization drawer is showing -->
-    <dimen name="customizeSmallScreenVerticalMarginLandscape">90dip</dimen>
-    <dimen name="customizeSmallScreenVerticalMarginPortrait">180dip</dimen>
-
-    <dimen name="delete_zone_drawable_padding">8dip</dimen>
     <dimen name="all_apps_button_drawable_padding">0dip</dimen>
     <dimen name="all_apps_button_vertical_padding">4dip</dimen>
 
+    <integer name="land_all_apps_view_cellCountX">7</integer>
+    <integer name="land_all_apps_view_cellCountY">5</integer>
+
     <dimen name="toolbar_button_vertical_padding">12dip</dimen>
     <dimen name="toolbar_button_horizontal_padding">16dip</dimen>
 
@@ -53,6 +69,9 @@
     <dimen name="delete_zone_vertical_drag_padding">20dip</dimen>
     <dimen name="delete_zone_horizontal_drag_padding">20dip</dimen>
 
+    <!-- roughly a status bar (for determining how many rows of icons are in home) -->
+    <dimen name="status_bar_height">48dip</dimen>
+
     <!-- dimensions for the wallpaper picker wallpaper thumbnail width -->
     <dimen name="wallpaper_chooser_grid_width">196dp</dimen>
     <dimen name="wallpaper_chooser_grid_height">140dp</dimen>
@@ -64,4 +83,9 @@
     <!-- How much the content view of an alert dialog should be inset (currently used
         for the WallpaperChooser in XLarge mode) -->
     <dimen name="alert_dialog_content_inset">0dp</dimen>
+
+    <!-- When dragging items on the workspace, the number of dps by which the position of
+     the drag view should be offset from the position of the original view. -->
+    <dimen name="dragViewOffsetX">0dp</dimen>
+    <dimen name="dragViewOffsetY">-12dp</dimen>
 </resources>
diff --git a/res/values-xlarge/strings.xml b/res/values-large/strings.xml
similarity index 100%
rename from res/values-xlarge/strings.xml
rename to res/values-large/strings.xml
diff --git a/res/values-xlarge/styles.xml b/res/values-large/styles.xml
similarity index 78%
rename from res/values-xlarge/styles.xml
rename to res/values-large/styles.xml
index 7208d97..bcbe038 100644
--- a/res/values-xlarge/styles.xml
+++ b/res/values-large/styles.xml
@@ -41,4 +41,16 @@
         <item name="android:paddingTop">0dip</item>
         <item name="android:includeFontPadding">false</item>
     </style>
+
+    <style name="TabIndicator.Wide">
+        <item name="android:paddingLeft">40dp</item>
+        <item name="android:paddingRight">40dp</item>
+        <item name="android:paddingTop">15dp</item>
+        <item name="android:paddingBottom">20dp</item>
+        <item name="android:textSize">20sp</item>
+    </style>
+
+    <style name="config_orientation">
+        <item name="@android:screenOrientation">unspecified</item>
+    </style>
 </resources>
diff --git a/res/values-xlarge/wallpapers.xml b/res/values-large/wallpapers.xml
similarity index 100%
rename from res/values-xlarge/wallpapers.xml
rename to res/values-large/wallpapers.xml
diff --git a/res/values-lt-xlarge/strings.xml b/res/values-lt-large/strings.xml
similarity index 100%
rename from res/values-lt-xlarge/strings.xml
rename to res/values-lt-large/strings.xml
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index bb67115..e84360d 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Aplankai"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Daugiau"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Darbalaukio fonai"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Spartieji programos klavišai"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Spartieji programos klavišai"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Tai bus darbalaukio fonų skirtukas"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Visos"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Žaidimai"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Atsisiųsta"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mano programos"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Nerasta žaidimų."</string>
     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Neturite atsisiųstų programų."</string>
+    <string name="market" msgid="2652226429823445833">"Parduotuvė"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Nepavyko pašalinti elemento šiame pagr. ekrane"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Pasirinkti norimą sukurti valdiklį"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Aplanko pavadinimas"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Pagrindinis"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Pašalinti"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Pašalinti"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Ieškoti"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Balso paieška"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Programos"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Tinkinti"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Pašalinti"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Pašalinti naujinį"</string>
     <string name="menu_add" msgid="3065046628354640854">"Pridėti"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Valdyti programas"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Darbalaukio fonas"</string>
diff --git a/res/values-lv-xlarge/strings.xml b/res/values-lv-large/strings.xml
similarity index 100%
rename from res/values-lv-xlarge/strings.xml
rename to res/values-lv-large/strings.xml
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 7a016a6..963c332 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Mapes"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Vairāk"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Fona tapetes"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Lietotnes saīsnes"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Lietotņu saīsnes"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Šī būs fona tapetes cilne"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Visas"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Lietotnes"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Spēles"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Lejupielādētās"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Manas lietotnes"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Nav nevienas spēles."</string>
     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nav ielādēta neviena lietojumprogramma."</string>
+    <string name="market" msgid="2652226429823445833">"Iepirkties"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Nevarēja nomest vienumu šajā sākumekrānā."</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Atlasīt izveidojamo logrīku"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Mapes nosaukums"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Sākums"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Noņemt"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Atinstalēt"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Meklēt"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Balss meklēšana"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Lietojumprogrammas"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Pielāgot"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Noņemt"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Atinstalēt atjauninājumu"</string>
     <string name="menu_add" msgid="3065046628354640854">"Pievienot"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Lietotņu pārvaldība"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Fona tapete"</string>
diff --git a/res/values-nb-xlarge/strings.xml b/res/values-nb-large/strings.xml
similarity index 100%
rename from res/values-nb-xlarge/strings.xml
rename to res/values-nb-large/strings.xml
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index bee708c..382bac4 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Mapper"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Mer"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Bakgrunner"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Programsnarveier"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"App-snarveier"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Dette er nå bakgrunnsfanen"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Alle"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Programmer"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Spill"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Nedlastet"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mine programmer"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Finner ingen spill."</string>
     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Du har ingen nedlastede programmer."</string>
+    <string name="market" msgid="2652226429823445833">"Butikk"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Kunne ikke slippe elementet på denne startskjermen"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Velg modul for oppretting"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Mappenavn"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Startsiden"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Fjern"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Avinstaller"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Søk"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Talesøk"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Applikasjoner"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Tilpass"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Fjern"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Avinstaller oppdateringen"</string>
     <string name="menu_add" msgid="3065046628354640854">"Legg til"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Administrer programmer"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Bakgrunnsbilde"</string>
diff --git a/res/values-nl-xlarge/strings.xml b/res/values-nl-large/strings.xml
similarity index 100%
rename from res/values-nl-xlarge/strings.xml
rename to res/values-nl-large/strings.xml
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 9d7ff2f..abcf29a 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -25,20 +25,21 @@
     <string name="chooser_wallpaper" msgid="5988031014201479733">"Achtergrond selecteren in"</string>
     <string name="wallpaper_instructions" msgid="4215640646180727542">"Achtergrond instellen"</string>
     <string name="pick_wallpaper" msgid="5630222540525626723">"Achtergronden"</string>
-    <string name="activity_not_found" msgid="5591731020063337696">"De toepassing is niet geïnstalleerd."</string>
+    <string name="activity_not_found" msgid="5591731020063337696">"De app is niet geïnstalleerd."</string>
     <string name="configure_wallpaper" msgid="2820186271419674623">"Configureren..."</string>
     <string name="widgets_tab_label" msgid="9145860100000983599">"Widgets"</string>
     <string name="folders_tab_label" msgid="1145293785541489736">"Mappen"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Meer"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Achtergronden"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Toepassingssnelkoppelingen"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Toepassingssnelkoppelingen"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Dit wordt het tabblad \'Achtergronden\'"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Alle"</string>
-    <string name="all_apps_tab_apps" msgid="5468972551904071712">"Toepassingen"</string>
+    <string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Games"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Gedownload"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mijn apps"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Geen games gevonden."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Geen gedownloade toepassingen gevonden."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"U heeft geen gedownloade apps."</string>
+    <string name="market" msgid="2652226429823445833">"Winkel"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Kan item niet neerzetten op dit startscherm"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Widget selecteren om te maken"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Mapnaam"</string>
@@ -46,7 +47,7 @@
     <string name="rename_action" msgid="6016003384693240896">"OK"</string>
     <string name="cancel_action" msgid="3811860427489435048">"Annuleren"</string>
     <string name="menu_item_add_item" msgid="6233177331075781114">"Toevoegen aan startpagina"</string>
-    <string name="group_applications" msgid="4118484163419674240">"Toepassingen"</string>
+    <string name="group_applications" msgid="4118484163419674240">"Apps"</string>
     <string name="group_shortcuts" msgid="9133529424900391877">"Sneltoetsen"</string>
     <string name="group_folder" msgid="5143593791798929193">"Nieuwe map"</string>
     <string name="group_live_folders" msgid="2664945399140647217">"Mappen"</string>
@@ -60,33 +61,39 @@
     <string name="shortcut_uninstalled" msgid="2129499669449749995">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' is verwijderd."</string>
     <string name="shortcut_duplicate" msgid="4757756326465060694">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' bestaat al."</string>
     <string name="title_select_shortcut" msgid="2858897527672831763">"Snelkoppeling selecteren"</string>
-    <string name="title_select_application" msgid="8031072293115454221">"Toepassing selecteren"</string>
+    <string name="title_select_application" msgid="8031072293115454221">"App selecteren"</string>
     <string name="title_select_live_folder" msgid="3753447798805166749">"Map selecteren"</string>
-    <string name="all_apps_button_label" msgid="2578400570124163469">"Toepassingen"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Apps"</string>
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Startpagina"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Verwijderen"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Verwijderen"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Zoeken"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Spraakgestuurd zoeken"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Apps"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Aanpassen"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Verwijderen"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Update verwijderen"</string>
     <string name="menu_add" msgid="3065046628354640854">"Toevoegen"</string>
-    <string name="menu_manage_apps" msgid="2308685199463588895">"Toepassingen beheren"</string>
+    <string name="menu_manage_apps" msgid="2308685199463588895">"Apps beheren"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Achtergrond"</string>
     <string name="menu_search" msgid="4826514464423239041">"Zoeken"</string>
     <string name="menu_notifications" msgid="6424587053194766192">"Meldingen"</string>
     <string name="menu_gestures" msgid="514678675575912237">"Gebaren"</string>
     <string name="menu_settings" msgid="6233960148378443661">"Instellingen"</string>
-    <string name="cab_menu_delete_app" msgid="1242619904941293871">"Toepassing verwijderen"</string>
+    <string name="cab_menu_delete_app" msgid="1242619904941293871">"App verwijderen"</string>
     <string name="cab_menu_app_info" msgid="5180426909324882018">"Toepassingsdetails"</string>
-    <string name="cab_app_selection_text" msgid="606113924828167756">"1 toepassing geselecteerd"</string>
+    <string name="cab_app_selection_text" msgid="606113924828167756">"1 app geselecteerd"</string>
     <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget geselecteerd"</string>
     <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 map geselecteerd"</string>
     <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 snelkoppeling geselecteerd"</string>
     <string name="permlab_install_shortcut" msgid="1201690825493376489">"snelkoppelingen installeren"</string>
-    <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Een toepassing toestaan om snelkoppelingen toe te voegen zonder tussenkomst van de gebruiker."</string>
+    <string name="permdesc_install_shortcut" msgid="7429365847558984148">"Een app toestaan snelkoppelingen toe te voegen zonder tussenkomst van de gebruiker."</string>
     <string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"snelkoppelingen verwijderen"</string>
-    <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Een toepassing toestaan om snelkoppelingen te verwijderen zonder tussenkomst van de gebruiker."</string>
+    <string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Een app toestaan snelkoppelingen te verwijderen zonder tussenkomst van de gebruiker."</string>
     <string name="permlab_read_settings" msgid="3452408290738106747">"instellingen en snelkoppelingen voor de startpagina lezen"</string>
-    <string name="permdesc_read_settings" msgid="8377434937176025492">"Hiermee kan een toepassing de instellingen en snelkoppelingen op de startpagina lezen."</string>
+    <string name="permdesc_read_settings" msgid="8377434937176025492">"Hiermee kan een app de instellingen en snelkoppelingen op de startpagina lezen."</string>
     <string name="permlab_write_settings" msgid="1360567537236705628">"instellingen en snelkoppelingen voor de startpagina schrijven"</string>
-    <string name="permdesc_write_settings" msgid="1098648778383349818">"Hiermee kan een toepassing de instellingen en snelkoppelingen op de startpagina wijzigen."</string>
+    <string name="permdesc_write_settings" msgid="1098648778383349818">"Hiermee kan een app de instellingen en snelkoppelingen op de startpagina wijzigen."</string>
     <string name="gadget_error_text" msgid="8359351016167075858">"Probleem bij het laden van widget"</string>
     <string name="uninstall_system_app_text" msgid="7488523163288397451">"Dit is een systeemtoepassing die niet kan worden verwijderd."</string>
 </resources>
diff --git a/res/values-pl-xlarge/strings.xml b/res/values-pl-large/strings.xml
similarity index 100%
rename from res/values-pl-xlarge/strings.xml
rename to res/values-pl-large/strings.xml
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 50e955e..97b54af 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Foldery"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Więcej"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Tapety"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Skróty do aplikacji"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Skróty do aplikacji"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"To będzie karta tapet"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Wszystkie"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplikacje"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Gry"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Pobrane"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Moje aplikacje"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Nie znaleziono gier."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Brak pobranych aplikacji."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nie masz żadnych pobranych aplikacji."</string>
+    <string name="market" msgid="2652226429823445833">"Sklep"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Nie można upuścić elementu na ekranie głównym"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Wybierz widżet do utworzenia"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Nazwa folderu"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Ekran główny"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Usuń"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinstaluj"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Szukaj"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Wyszukiwanie głosowe"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplikacje"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Dostosuj"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Usuń"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinstaluj aktualizację"</string>
     <string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Zarządzaj aplikacjami"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Tapeta"</string>
diff --git a/res/values-port/dimens.xml b/res/values-port/dimens.xml
index 65a3fd3..7d50c1a 100644
--- a/res/values-port/dimens.xml
+++ b/res/values-port/dimens.xml
@@ -17,4 +17,22 @@
 <resources>
     <dimen name="workspace_cell_width">80dip</dimen>
     <dimen name="workspace_cell_height">100dip</dimen>
+    <dimen name="folder_cell_width">74dip</dimen>
+    <dimen name="folder_cell_height">86dip</dimen>
+
+    <integer name="all_apps_view_cellCountX">4</integer>
+    <integer name="all_apps_view_cellCountY">5</integer>
+    <dimen name="all_apps_view_pageLayoutWidthGap">3dp</dimen>
+    <dimen name="all_apps_view_pageLayoutHeightGap">12dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingTop">15dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingBottom">15dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingLeft">0dp</dimen>
+    <dimen name="all_apps_view_pageLayoutPaddingRight">0dp</dimen>
+
+    <dimen name="apps_customize_widget_cell_width_gap">20dp</dimen>
+    <dimen name="apps_customize_widget_cell_height_gap">40dp</dimen>
+    <integer name="apps_customize_widget_cell_count_x">2</integer>
+    <integer name="apps_customize_widget_cell_count_y">2</integer>
+    <integer name="apps_customize_wallpaper_cell_count_x">1</integer>
+    <integer name="apps_customize_wallpaper_cell_count_y">1</integer>
 </resources>
diff --git a/res/values-pt-xlarge/strings.xml b/res/values-pt-large/strings.xml
similarity index 100%
rename from res/values-pt-xlarge/strings.xml
rename to res/values-pt-large/strings.xml
diff --git a/res/values-pt-rPT-xlarge/strings.xml b/res/values-pt-rPT-large/strings.xml
similarity index 100%
rename from res/values-pt-rPT-xlarge/strings.xml
rename to res/values-pt-rPT-large/strings.xml
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 69f202a..71f634d 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Pastas"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Mais"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Imagens de fundo"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Atalhos de aplicações"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Atalhos de aplicações"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Isto será o separador de imagens de fundo"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Todas"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicações"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Jogos"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Transferidas"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"As minhas aplicações"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Sem jogos."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Sem aplicações transferidas."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Não existem aplicações transferidas."</string>
+    <string name="market" msgid="2652226429823445833">"Loja"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Não foi possível largar o item neste ecrã inicial"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Seleccionar widget a criar"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Nome da pasta"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Página inicial"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remover"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Pesquisar"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Pesquisa por Voz"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicações"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizar"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Remover"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar atualização"</string>
     <string name="menu_add" msgid="3065046628354640854">"Adicionar"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Gerir aplicações"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Imagem de fundo"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 9e6cdfd..2714fde 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Pastas"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Mais"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Papéis de parede"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Atalhos de aplicativo"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Atalhos de aplicativo"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Esta será a guia de papéis de parede"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Todos"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicativos"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Jogos"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Download concluído"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Meus aplicativos"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Nenhum jogo encontrado."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nenhum aplic. encontrado."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Você não tem nenhum aplicativo transferido."</string>
+    <string name="market" msgid="2652226429823445833">"Comprar"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Não foi possível soltar o item nesta tela inicial"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Selecione um widget para criar"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Nome da pasta"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Página inicial"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Remover"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Desinstalar"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Pesquisar"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Pesquisa por voz"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicativos"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizar"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Remover"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Desinstalar atualização"</string>
     <string name="menu_add" msgid="3065046628354640854">"Adicionar"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Gerenciar aplicativos"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Plano de fundo"</string>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
index 6ac87d4..a8453ed 100644
--- a/res/values-rm/strings.xml
+++ b/res/values-rm/strings.xml
@@ -51,6 +51,8 @@
     <skip />
     <!-- no translation found for all_apps_no_downloads (2284720393234453761) -->
     <skip />
+    <!-- no translation found for market (2652226429823445833) -->
+    <skip />
     <!-- no translation found for external_drop_widget_error (4976816434597126575) -->
     <skip />
     <!-- no translation found for external_drop_widget_pick_title (4481311720134376218) -->
@@ -83,6 +85,18 @@
     <skip />
     <!-- no translation found for delete_zone_label_all_apps (6664588234817475108) -->
     <skip />
+    <!-- no translation found for accessibility_search_button (816822994629942611) -->
+    <skip />
+    <!-- no translation found for accessibility_voice_search_button (3938249215065842475) -->
+    <skip />
+    <!-- no translation found for accessibility_all_apps_button (1595097919145716305) -->
+    <skip />
+    <!-- no translation found for accessibility_customize_button (585539669413531163) -->
+    <skip />
+    <!-- no translation found for accessibility_delete_button (3628162007991023603) -->
+    <skip />
+    <!-- no translation found for delete_zone_label_all_apps_system_app (3683920959591819044) -->
+    <skip />
     <string name="menu_add" msgid="3065046628354640854">"Agiuntar"</string>
     <!-- no translation found for menu_manage_apps (2308685199463588895) -->
     <skip />
diff --git a/res/values-ro-xlarge/strings.xml b/res/values-ro-large/strings.xml
similarity index 100%
rename from res/values-ro-xlarge/strings.xml
rename to res/values-ro-large/strings.xml
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index ff81c00..6bed5d0 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Dosare"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Mai multe"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Imagini de fundal"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Comenzi rapide aplicaţii"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Comenzi rapide aplicaţii"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Aceasta va fi fila pentru imagini de fundal"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Toate"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplicaţii"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Jocuri"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Descărcate"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Aplicaţiile mele"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Nu s-au găsit jocuri."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nu s-au găsit aplicaţii descărcate."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nu aveţi aplicaţii descărcate."</string>
+    <string name="market" msgid="2652226429823445833">"Cumpăraţi"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Impos. de plasat elem. pe acest ecran de pornire"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Selectaţi obiectul widget"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Nume dosar"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Domiciliu"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Eliminaţi"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Dezinstalaţi"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Căutaţi"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Căutare vocală"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplicaţii"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Personalizaţi"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Eliminaţi"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Dezinstalaţi actualizarea"</string>
     <string name="menu_add" msgid="3065046628354640854">"Adăugaţi"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Gestionaţi aplicaţii"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Imagine de fundal"</string>
diff --git a/res/values-ru-xlarge/strings.xml b/res/values-ru-large/strings.xml
similarity index 100%
rename from res/values-ru-xlarge/strings.xml
rename to res/values-ru-large/strings.xml
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index abd09f9..0456e4c 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Папки"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Ещё"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Обои"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Ярлыки приложений"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Ярлыки приложений"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Это будет вкладка обоев"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Все"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Приложения"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Игры"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Загруженные"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Мои приложения"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Игр не найдено."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Нет загруженных приложений."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"У вас нет загруженных приложений."</string>
+    <string name="market" msgid="2652226429823445833">"Маркет"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Не удается скопировать элемент на главный экран"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Выберите виджет"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Название папки"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Главная"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Удалить"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Удалить"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Поиск"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Голосовой поиск"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Приложения"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Настроить"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Удалить"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Удалить обновление"</string>
     <string name="menu_add" msgid="3065046628354640854">"Добавить"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Приложения"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Обои"</string>
diff --git a/res/values-sk-xlarge/strings.xml b/res/values-sk-large/strings.xml
similarity index 100%
rename from res/values-sk-xlarge/strings.xml
rename to res/values-sk-large/strings.xml
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 23a8476..064309d 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Priečinky"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Viac"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Tapety"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Odkazy aplikácií"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Odkazy aplikácií"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Toto bude karta Tapety"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Všetky"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Aplikácie"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Hry"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Prevzaté"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Moje aplikácie"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Nenašli sa žiadne hry."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Neboli nájdené žiadne prevzaté aplikácie."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Nemáte žiadne prevzaté aplikácie."</string>
+    <string name="market" msgid="2652226429823445833">"Obchod"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Položku sa nepodarilo pretiahnuť na túto plochu"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Vyberte miniaplikáciu"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Názov priečinka"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Domovská stránka"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odstrániť"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odinštalovať"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Hľadať"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Hlasové vyhľadávanie"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Aplikácie"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Prispôsobiť"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Odstrániť"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odinštalovať aktualizáciu"</string>
     <string name="menu_add" msgid="3065046628354640854">"Pridať"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Spravovať aplikácie"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Tapeta"</string>
diff --git a/res/values-sl-xlarge/strings.xml b/res/values-sl-large/strings.xml
similarity index 100%
rename from res/values-sl-xlarge/strings.xml
rename to res/values-sl-large/strings.xml
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index f12fd7b..78b5187 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Mape"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Več"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Ozadja"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Bližnjice do programov"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Bližnjice do programov"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"To bo zavihek ozadij"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Vse"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Programi"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Igre"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Preneseno"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Moji programi"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Ni najdenih iger."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Ni najdenih prenesenih programov."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Ni prenesenih programov."</string>
+    <string name="market" msgid="2652226429823445833">"Nakup"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Elementa ni bilo mogoče postaviti na ta začetni zaslon"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Izberite želeni pripomoček"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Ime mape"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Začetni zaslon"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Odstrani"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Odstrani"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Išči"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Glasovno iskanje"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Programi"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Prilagodi"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Odstrani"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Odstrani posodobitev"</string>
     <string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Upravljaj programe"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Slika za ozadje"</string>
diff --git a/res/values-sr-xlarge/strings.xml b/res/values-sr-large/strings.xml
similarity index 100%
rename from res/values-sr-xlarge/strings.xml
rename to res/values-sr-large/strings.xml
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 4a61abb..cbc4bf2 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Директоријуми"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Још"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Позадине"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Пречице за апликације"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Пречице за апликације"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Ово ће бити картица позадине"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Све"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Игре"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Преузето"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Моје апликације"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Нису пронађене игре."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Нису пронађене преузете апликације"</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Немате ниједну преузету апликацију."</string>
+    <string name="market" msgid="2652226429823445833">"Куповина"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Ставка није пребачена на овај почетни екран"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Изаберите виџет за креирање"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Име директоријума"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Почетна"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Уклони"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Деинсталирај"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Претражи"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Гласовна претрага"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Апликације"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Прилагоди"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Уклони"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Деинсталирај ажурирања"</string>
     <string name="menu_add" msgid="3065046628354640854">"Додај"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Управљање апликацијама"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Позадина"</string>
diff --git a/res/values-sv-xlarge/strings.xml b/res/values-sv-large/strings.xml
similarity index 100%
rename from res/values-sv-xlarge/strings.xml
rename to res/values-sv-large/strings.xml
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 5f5a5d0..68859e3 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Mappar"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Mer"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Bakgrundsbilder"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Genvägar för appar"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Genvägar för appar"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Det här kommer att vara fliken för bakgrundsbilder"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Alla"</string>
-    <string name="all_apps_tab_apps" msgid="5468972551904071712">"Program"</string>
+    <string name="all_apps_tab_apps" msgid="5468972551904071712">"Appar"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Spel"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Hämtade"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Mina appar"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Inga spel hittades."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Inga hämtade appar."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Du har inte hämtat några appar."</string>
+    <string name="market" msgid="2652226429823445833">"Butik"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Objektet kunde inte släppas på den här startsidan"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Välj en widget att skapa"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Mappnamn"</string>
@@ -46,7 +47,7 @@
     <string name="rename_action" msgid="6016003384693240896">"OK"</string>
     <string name="cancel_action" msgid="3811860427489435048">"Avbryt"</string>
     <string name="menu_item_add_item" msgid="6233177331075781114">"Lägg till på startsidan"</string>
-    <string name="group_applications" msgid="4118484163419674240">"Program"</string>
+    <string name="group_applications" msgid="4118484163419674240">"Appar"</string>
     <string name="group_shortcuts" msgid="9133529424900391877">"Genvägar"</string>
     <string name="group_folder" msgid="5143593791798929193">"Ny mapp"</string>
     <string name="group_live_folders" msgid="2664945399140647217">"Mappar"</string>
@@ -60,12 +61,18 @@
     <string name="shortcut_uninstalled" msgid="2129499669449749995">"Genvägen \"<xliff:g id="NAME">%s</xliff:g>\" har tagits bort."</string>
     <string name="shortcut_duplicate" msgid="4757756326465060694">"Genvägen \"<xliff:g id="NAME">%s</xliff:g>\" finns redan."</string>
     <string name="title_select_shortcut" msgid="2858897527672831763">"Välj genväg"</string>
-    <string name="title_select_application" msgid="8031072293115454221">"Välj program"</string>
+    <string name="title_select_application" msgid="8031072293115454221">"Välj app"</string>
     <string name="title_select_live_folder" msgid="3753447798805166749">"Välj mapp"</string>
-    <string name="all_apps_button_label" msgid="2578400570124163469">"Program"</string>
+    <string name="all_apps_button_label" msgid="2578400570124163469">"Appar"</string>
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Startsida"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Ta bort"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Avinstallera"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Sök"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Röstsökning"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Appar"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Anpassa"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Ta bort"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Avinstallera uppdatering"</string>
     <string name="menu_add" msgid="3065046628354640854">"Lägg till"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Hantera appar"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Bakgrund"</string>
@@ -73,9 +80,9 @@
     <string name="menu_notifications" msgid="6424587053194766192">"Aviseringar"</string>
     <string name="menu_gestures" msgid="514678675575912237">"Gester"</string>
     <string name="menu_settings" msgid="6233960148378443661">"Inställningar"</string>
-    <string name="cab_menu_delete_app" msgid="1242619904941293871">"Avinstallera program"</string>
+    <string name="cab_menu_delete_app" msgid="1242619904941293871">"Avinstallera app"</string>
     <string name="cab_menu_app_info" msgid="5180426909324882018">"Programinformation"</string>
-    <string name="cab_app_selection_text" msgid="606113924828167756">"1 program har valts"</string>
+    <string name="cab_app_selection_text" msgid="606113924828167756">"1 app har valts"</string>
     <string name="cab_widget_selection_text" msgid="962527270506951955">"1 widget vald"</string>
     <string name="cab_folder_selection_text" msgid="8916111874189565067">"1 mapp vald"</string>
     <string name="cab_shortcut_selection_text" msgid="8115847384500412878">"1 genväg har valts"</string>
diff --git a/res/values-th-xlarge/strings.xml b/res/values-th-large/strings.xml
similarity index 100%
rename from res/values-th-xlarge/strings.xml
rename to res/values-th-large/strings.xml
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 39dc770..1562135 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"โฟลเดอร์"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"เพิ่มเติม"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"วอลเปเปอร์"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"ทางลัดของแอปพลิเคชัน"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"ทางลัดของแอปพลิเคชัน"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"นี่จะเป็นแท็บวอลเปเปอร์"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"ทั้งหมด"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"แอปพลิเคชัน"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"เกม"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"ดาวน์โหลดแล้ว"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"แอปพลิเคชันของฉัน"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"ไม่พบเกม"</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"ไม่พบแอปพลิเคชันที่ดาวน์โหลดไว้"</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"คุณไม่ได้ดาวน์โหลดแอปพลิเคชันไว้"</string>
+    <string name="market" msgid="2652226429823445833">"ร้าน"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"ไม่สามารถวางรายการลงในหน้าจอหลักนี้ได้"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"เลือกวิดเจ็ตที่จะสร้าง"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"ชื่อโฟลเดอร์"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"บ้าน"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"นำออก"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"ถอนการติดตั้ง"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"ค้นหา"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Voice Search"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"แอปพลิเคชัน"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"กำหนดค่า"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"ลบ"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"ถอนการติดตั้งการอัปเดต"</string>
     <string name="menu_add" msgid="3065046628354640854">"เพิ่ม"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"จัดการแอปพลิเคชัน"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"วอลเปเปอร์"</string>
diff --git a/res/values-tl-xlarge/strings.xml b/res/values-tl-large/strings.xml
similarity index 100%
rename from res/values-tl-xlarge/strings.xml
rename to res/values-tl-large/strings.xml
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index cbdac66..50ed317 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Mga Folder"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Higit pa"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Mga Wallpaper"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Mga Shortcut ng App"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Mga shortcut ng app"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Ito ang magiging tab ng mga wallpaper"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Lahat"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Apps"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Mga Laro"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Na-download"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Aking mga app"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Walang nakitang mga laro."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Walang na-download na app"</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"Wala kang mga na-download na application."</string>
+    <string name="market" msgid="2652226429823445833">"Mamili"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Hindi ma-drop ang item sa homescreen na ito"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Pumili ng widget na lilikhain"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Pangalan ng folder"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Alisin"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"I-uninstall"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Maghanap"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Paghahanap gamit ang Boses"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Mga Application"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"I-customize"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Alisin"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"I-uninstall ang update"</string>
     <string name="menu_add" msgid="3065046628354640854">"Idagdag"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Pamahalaan ang apps"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Wallpaper"</string>
diff --git a/res/values-tr-xlarge/strings.xml b/res/values-tr-large/strings.xml
similarity index 100%
rename from res/values-tr-xlarge/strings.xml
rename to res/values-tr-large/strings.xml
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 3059ab4..2057828 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -31,21 +31,22 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Klasörler"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Diğer"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Duvar Kağıtları"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Uygulama Kısayolları"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Uygulama kısayolları"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Bu duvar kağıdı sekmesi olacaktır"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Tümü"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Uygulamalar"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Oyunlar"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"İndirilenler"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Uygulamalarım"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Oyun bulunamadı."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"İndirilmiş uygulama bulunamadı."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"İndirilmiş uygulamanız yok."</string>
+    <string name="market" msgid="2652226429823445833">"Alışveriş"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Öğe bu ana ekrana bırakılamadı"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Oluşturulacak widget\'i seç"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Klasör adı"</string>
     <string name="rename_folder_title" msgid="4544573104191526550">"Klasörü yeniden adlandır"</string>
     <string name="rename_action" msgid="6016003384693240896">"Tamam"</string>
     <string name="cancel_action" msgid="3811860427489435048">"İptal"</string>
-    <string name="menu_item_add_item" msgid="6233177331075781114">"Ana ekrana ekle"</string>
+    <string name="menu_item_add_item" msgid="6233177331075781114">"Ana Sayfaya ekle"</string>
     <string name="group_applications" msgid="4118484163419674240">"Uygulamalar"</string>
     <string name="group_shortcuts" msgid="9133529424900391877">"Kısayollar"</string>
     <string name="group_folder" msgid="5143593791798929193">"Yeni klasör"</string>
@@ -55,7 +56,7 @@
     <string name="add_folder" msgid="3521088587367839879">"Klasör"</string>
     <string name="add_clock" msgid="2337943840175865746">"Saat"</string>
     <string name="add_photo_frame" msgid="3154058437359487954">"Resim çerçevesi"</string>
-    <string name="out_of_space" msgid="8365249326091984698">"Bu Ana ekranda başka yer yok."</string>
+    <string name="out_of_space" msgid="8365249326091984698">"Bu Ana Sayfada yer yok."</string>
     <string name="shortcut_installed" msgid="7071557296331322355">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu oluşturuldu."</string>
     <string name="shortcut_uninstalled" msgid="2129499669449749995">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu kaldırıldı."</string>
     <string name="shortcut_duplicate" msgid="4757756326465060694">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu zaten var."</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Ana Sayfa"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Kaldır"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Yüklemeyi Kaldır"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Ara"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Sesli Arama"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Uygulamalar"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Özelleştir"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Kaldır"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Güncelleme kaldırılsın mı?"</string>
     <string name="menu_add" msgid="3065046628354640854">"Ekle"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Uyglm yönet"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Duvar Kağıdı"</string>
diff --git a/res/values-uk-xlarge/strings.xml b/res/values-uk-large/strings.xml
similarity index 100%
rename from res/values-uk-xlarge/strings.xml
rename to res/values-uk-large/strings.xml
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index caa04d8..b3f0846 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Папки"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Більше"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Фонові мал."</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Ярлики програм"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Ярлики програм"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"This will be the wallpapers tab"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Усі"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Програми"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Ігри"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Завантажені"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Мої програми"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Ігор не знайдено."</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Завантажених програм не знайдено."</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"У вас немає завантажених програм."</string>
+    <string name="market" msgid="2652226429823445833">"Магазин"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Неможливо помістити елемент на цей головний екран"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Вибрати віджет для створення"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Назва папки"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Головна"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Видалити"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Видалити"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Пошук"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Голосовий пошук"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Програми"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Налаштувати"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Видалити"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Видалити оновлення"</string>
     <string name="menu_add" msgid="3065046628354640854">"Додати"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Керув. прогр."</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Фоновий мал."</string>
diff --git a/res/values-vi-xlarge/strings.xml b/res/values-vi-large/strings.xml
similarity index 74%
rename from res/values-vi-xlarge/strings.xml
rename to res/values-vi-large/strings.xml
index 9257327..c8ce028 100644
--- a/res/values-vi-xlarge/strings.xml
+++ b/res/values-vi-large/strings.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="wallpaper_dialog_title" msgid="5764793286524787718">"Chọn hình nền"</string>
-    <string name="wallpaper_chooser_empty" msgid="7358237455389125747">"Không có sẵn hình nền nào"</string>
-    <string name="wallpaper_cancel" msgid="6502936522490675611">"Hủy"</string>
+    <string name="wallpaper_dialog_title" msgid="8362944198120933329">"Chọn hình nền"</string>
+    <string name="wallpaper_chooser_empty" msgid="6543937491391049913">"Không có sẵn hình nền nào"</string>
+    <string name="wallpaper_cancel" msgid="5942480248232268588">"Hủy"</string>
 </resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 3277c07..9238c4a 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"Thư mục"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"Khác"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"Hình nền"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"Lối tắt ứng dụng"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"Lối tắt ứng dụng"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"Đây sẽ là tab hình nền"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"Tất cả"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"Ứng dụng"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"Trò chơi"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Đã tải xuống"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"Ứng dụng của tôi"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"Không tìm thấy trò chơi."</string>
     <string name="all_apps_no_downloads" msgid="2284720393234453761">"Bạn không có ứng dụng nào được tải xuống."</string>
+    <string name="market" msgid="2652226429823445833">"Mua hàng"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"Không thể thả mục vào màn hình chính này"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"Chọn tiện ích để tạo"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"Tên thư mục"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Màn hình trang chủ"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Xóa"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"Gỡ cài đặt"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"Tìm kiếm"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"Tìm kiếm bằng giọng nói"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"Ứng dụng"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"Tùy chỉnh"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"Xóa"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"Gỡ cài đặt cập nhật"</string>
     <string name="menu_add" msgid="3065046628354640854">"Thêm"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"Quản lý ứng dụng"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"Hình nền"</string>
diff --git a/res/values-xlarge-land/dimens.xml b/res/values-xlarge-land/dimens.xml
deleted file mode 100644
index 51037f5..0000000
--- a/res/values-xlarge-land/dimens.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<resources>
-    <!-- the area at the edge of the screen that makes the workspace go left
-         or right while you're dragging. -->
-    <dimen name="scroll_zone">100dip</dimen>
-
-    <!-- Width/height gap overrides for the workspace -->
-    <dimen name="workspace_width_gap">32dp</dimen>
-    <dimen name="workspace_height_gap">2dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/res/values-xlarge-port/dimens.xml b/res/values-xlarge-port/dimens.xml
deleted file mode 100644
index baa31aa..0000000
--- a/res/values-xlarge-port/dimens.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<resources>
-    <!-- the area at the edge of the screen that makes the workspace go left
-         or right while you're dragging. -->
-    <dimen name="scroll_zone">40dp</dimen>
-
-    <!-- Width/height gap overrides for the workspace -->
-    <dimen name="workspace_width_gap">0dp</dimen>
-    <dimen name="workspace_height_gap">32dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/res/values-xlarge/config.xml b/res/values-xlarge/config.xml
deleted file mode 100644
index dc9d096..0000000
--- a/res/values-xlarge/config.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-<resources>
-    <!--  NOTE: Many of the all apps values here are also used for the customization drawer -->
-
-    <!-- Duration in milliseconds of the fade-in/out of the icons as they are being dragged
-         from the AllApps or Customization trays -->
-    <integer name="icon_allAppsCustomizeFadeInTime">150</integer>
-    <integer name="icon_allAppsCustomizeFadeOutTime">200</integer>
-    <integer name="icon_allAppsCustomizeFadeAlpha">102</integer>
-
-    <!-- Duration in milliseconds of the all apps / configuration zoom-in animation. -->
-    <!-- NB: This should be less than the workspaceShrinkTime as they happen together. -->
-    <integer name="config_allAppsZoomInTime">1450</integer>
-
-    <!-- Duration in milliseconds of the transition between tabs in the all apps/customize
-         tray -->
-    <integer name="config_tabTransitionTime">100</integer>
-
-    <!-- Duration in milliseconds of the all apps zoom-out animation -->
-    <!-- NB: This should be less than the workspaceUnshrinkTime as they happen together. -->
-    <integer name="config_allAppsZoomOutTime">1200</integer>
-
-    <!-- Scaling factor used in the all apps zooming animations -->
-    <integer name="config_allAppsZoomScaleFactor">20</integer>
-
-    <!-- Duration in milliseconds of the all apps / configuration zoom-in animation. -->
-    <!-- NB: This should be less than the workspaceShrinkTime as they happen together. -->
-    <integer name="config_customizeZoomInTime">800</integer>
-
-    <!-- Duration in milliseconds of the all apps zoom-out animation -->
-    <!-- NB: This should be less than the workspaceUnshrinkTime as they happen together. -->
-    <integer name="config_customizeZoomOutTime">600</integer>
-
-    <!-- Scaling factor used in the all apps zooming animations -->
-    <integer name="config_customizeZoomScaleFactor">7</integer>
-
-    <!-- Duration in milliseconds of the animations between all apps, customize, & home.
-         NOTE: If these are changed, the toolbar animation times below should also be. -->
-    <integer name="config_allAppsCameraPanTime">700</integer>
-    <integer name="config_allAppsFadeOutTime">500</integer>
-    <integer name="config_customizeWorkspaceShrinkTime">800</integer>
-    <integer name="config_allAppsWorkspaceShrinkTime">1450</integer>
-    <integer name="config_workspaceUnshrinkTime">650</integer>
-
-    <!-- Duration in milliseconds toolbar fade in and fade out animations.
-         NOTE: Fade in and fade out time should together be less the transition
-         animations between all apps, customize, & the workspace. -->
-    <integer name="config_toolbarButtonFadeInTime">350</integer>
-    <integer name="config_toolbarButtonFadeOutTime">200</integer>
-
-    <!-- When dragging items on the workspace, how much bigger (in pixels) the dragged view
-         should be, as compared to the original view. If 0, it will not be scaled at all.
-         Should be an even number, for pixel alignment. -->
-    <integer name="config_dragViewExtraPixels">0</integer>
-
-    <!-- When dragging items on the workspace, the number of pixels by which the position of
-         the drag view should be offset from the position of the original view. -->
-    <integer name="config_dragViewOffsetX">0</integer>
-    <integer name="config_dragViewOffsetY">-12</integer>
-
-    <!-- When items are dropped on the mini screens in customize mode, we have a bounce animation
-         of the bright green hover outline, and then fade out the outline at the end. These are
-         the values used in that animation -->
-    <integer name="config_screenOnDropScalePercent">120</integer>
-    <integer name="config_screenOnDropScaleUpDuration">200</integer>
-    <integer name="config_screenOnDropScaleDownDuration">200</integer>
-    <integer name="config_screenOnDropAlphaFadeDelay">350</integer>
-    <integer name="config_screenOnDropAlphaFadeDuration">50</integer>
-
-    <!-- Workspace screens are cached to bitmaps only when they're smaller than a certain size
-         (maxScaleForUsingWorkspaceScreenBitmapCache), since the bitmap cache itself is smaller
-         than the view itself (workspaceScreenBitmapCacheScale)  -->
-    <integer name="config_workspaceScreenBitmapCacheScale">20</integer>
-    <integer name="config_maxScaleForUsingWorkspaceScreenBitmapCache">50</integer>
-
-    <!-- The slope, in percent, of the drag movement needed to drag an item out of the customization
-         drawer (y / x * 100%)  -->
-    <integer name="config_customizationDrawerDragSlopeThreshold">150</integer>
-    <integer name="config_allAppsDrawerDragSlopeThreshold">150</integer>
-
-    <style name="config_orientation">
-        <item name="@android:screenOrientation">unspecified</item>
-    </style>
-</resources>
diff --git a/res/values-zh-rCN-xlarge/strings.xml b/res/values-zh-rCN-large/strings.xml
similarity index 100%
rename from res/values-zh-rCN-xlarge/strings.xml
rename to res/values-zh-rCN-large/strings.xml
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index b28d5a0..b2f228c 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"文件夹"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"更多"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"壁纸"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"应用程序快捷方式"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"应用程序快捷方式"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"这将会成为壁纸标签"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"全部"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"应用程序"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"游戏"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"已下载"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"我的应用程序"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"未找到游戏。"</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"未找到已下载的应用程序。"</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"您没有下载任何应用程序。"</string>
+    <string name="market" msgid="2652226429823445833">"购买"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"无法将该项放到主屏幕上"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"选择窗口小部件进行创建"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"文件夹名称"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"主屏幕"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"删除"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"卸载"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"搜索"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"语音搜索"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"应用程序"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"自定义"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"删除"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"卸载更新"</string>
     <string name="menu_add" msgid="3065046628354640854">"添加"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"管理应用程序"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"壁纸"</string>
diff --git a/res/values-zh-rTW-xlarge/strings.xml b/res/values-zh-rTW-large/strings.xml
similarity index 100%
rename from res/values-zh-rTW-xlarge/strings.xml
rename to res/values-zh-rTW-large/strings.xml
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 3b5b214..f172ef6 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -31,14 +31,15 @@
     <string name="folders_tab_label" msgid="1145293785541489736">"資料夾"</string>
     <string name="shortcuts_tab_label" msgid="8640731503933155644">"更多選項"</string>
     <string name="wallpapers_tab_label" msgid="1617804870364119879">"桌布"</string>
-    <!-- outdated translation 7756968120518062632 -->     <string name="applications_tab_label" msgid="2991364240020736760">"應用程式捷徑"</string>
+    <string name="applications_tab_label" msgid="2991364240020736760">"應用程式捷徑"</string>
     <string name="wallpapers_temp_tab_text" msgid="1660218201190495279">"桌布標籤保留位"</string>
     <string name="all_apps_tab_all" msgid="2942727589595027258">"全部"</string>
     <string name="all_apps_tab_apps" msgid="5468972551904071712">"應用程式"</string>
     <string name="all_apps_tab_games" msgid="1855736784923494918">"遊戲"</string>
-    <!-- outdated translation 7753043607780556423 -->     <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"已下載"</string>
+    <string name="all_apps_tab_downloaded" msgid="1488049110598641387">"我的應用程式"</string>
     <string name="all_apps_no_games" msgid="5293893733372793696">"找不到遊戲。"</string>
-    <!-- outdated translation 6687010155766000796 -->     <string name="all_apps_no_downloads" msgid="2284720393234453761">"找不到已下載的應用程式。"</string>
+    <string name="all_apps_no_downloads" msgid="2284720393234453761">"您沒有下載任何應用程式。"</string>
+    <string name="market" msgid="2652226429823445833">"商店"</string>
     <string name="external_drop_widget_error" msgid="4976816434597126575">"無法將項目拖放至主螢幕上"</string>
     <string name="external_drop_widget_pick_title" msgid="4481311720134376218">"選取要建立的小工具"</string>
     <string name="rename_folder_label" msgid="5646236631298452787">"資料夾名稱"</string>
@@ -66,6 +67,12 @@
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"主螢幕"</string>
     <string name="delete_zone_label_workspace" msgid="7153615831493049150">"移除"</string>
     <string name="delete_zone_label_all_apps" msgid="6664588234817475108">"解除安裝"</string>
+    <string name="accessibility_search_button" msgid="816822994629942611">"搜尋"</string>
+    <string name="accessibility_voice_search_button" msgid="3938249215065842475">"語音搜尋"</string>
+    <string name="accessibility_all_apps_button" msgid="1595097919145716305">"應用程式"</string>
+    <string name="accessibility_customize_button" msgid="585539669413531163">"自訂"</string>
+    <string name="accessibility_delete_button" msgid="3628162007991023603">"移除"</string>
+    <string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"解除安裝更新"</string>
     <string name="menu_add" msgid="3065046628354640854">"新增"</string>
     <string name="menu_manage_apps" msgid="2308685199463588895">"管理應用程式"</string>
     <string name="menu_wallpaper" msgid="5837429080911269832">"桌布"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 5e6a2ab..75b93bf 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -61,6 +61,16 @@
 
     </declare-styleable>
 
+    <!-- StrokedTextView specific attributes. -->
+    <declare-styleable name="StrokedTextView">
+        <!-- The color of the stroke outline -->
+        <attr name="strokeColor" format="color" />
+        <!-- The color of the text -->
+        <attr name="strokeTextColor" format="color" />
+        <!-- The width of the stroke -->
+        <attr name="strokeWidth" format="float" />
+    </declare-styleable>
+
     <!-- PagedViewIcon specific attributes. These attributes are used to customize
          a PagedViewIcon view in XML files. -->
     <declare-styleable name="PagedViewIcon">
@@ -94,10 +104,28 @@
         <attr name="pageLayoutPaddingBottom" format="dimension" />
         <attr name="pageLayoutPaddingLeft" format="dimension" />
         <attr name="pageLayoutPaddingRight" format="dimension" />
+        <attr name="pageLayoutMaxHeight" format="dimension" />
         <!-- The space between adjacent pages of the PagedView. -->
         <attr name="pageSpacing" format="dimension" />
     </declare-styleable>
 
+    <!-- AppsCustomizePagedView specific attributes.  These attributes are used to
+         customize an AppsCustomizePagedView in xml files. -->
+    <declare-styleable name="AppsCustomizePagedView">
+        <!-- Horizontal spacing between widgets and wallpapers -->
+        <attr name="widgetCellWidthGap" format="dimension" />
+        <!-- Vertical spacing between widgets -->
+        <attr name="widgetCellHeightGap" format="dimension" />
+        <!-- Number of widgets horizontally -->
+        <attr name="widgetCountX" format="integer" />
+        <!-- Number of widgets vertically -->
+        <attr name="widgetCountY" format="integer" />
+        <!-- Number of wallpaper pickers horizontally -->
+        <attr name="wallpaperCountX" format="integer" />
+        <!-- Number of wallpaper pickers vertically -->
+        <attr name="wallpaperCountY" format="integer" />
+    </declare-styleable>
+
     <!-- CustomizePagedView specific attributes. These attributes are used to customize
          a CustomizePagedView view in XML files. -->
     <declare-styleable name="CustomizePagedView">
diff --git a/res/values/config.xml b/res/values/config.xml
index 850c609..1cc019b 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -1,10 +1,41 @@
 <resources>
-    <integer name="config_allAppsFadeInTime">700</integer>
-    <integer name="config_allAppsFadeOutTime">700</integer>
-    <integer name="config_allAppsBatchLoadDelay">0</integer>
-    <integer name="config_allAppsBatchSize">0</integer>
+<!-- System -->
     <bool name="config_hardwareAccelerated">false</bool>
 
+<!-- AllApps/Customize/AppsCustomize -->
+    <!-- Fade in/out duration of icons being dragged from the trays -->
+    <integer name="config_dragAppsCustomizeIconFadeInDuration">150</integer>
+    <integer name="config_dragAppsCustomizeIconFadeOutDuration">200</integer>
+    <integer name="config_dragAppsCustomizeIconFadeAlpha">100</integer>
+    <integer name="config_workspaceUnshrinkTime">650</integer>
+
+    <!-- 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_appsCustomizeZoomInTime">1000</integer>
+    <integer name="config_appsCustomizeZoomOutTime">1200</integer>
+    <integer name="config_appsCustomizeZoomScaleFactor">20</integer>
+    <integer name="config_appsCustomizeFadeInTime">250</integer>
+    <integer name="config_appsCustomizeFadeOutTime">500</integer>
+    <integer name="config_appsCustomizeWorkspaceShrinkTime">1000</integer>
+
+    <!-- Tab transition animation duration -->
+    <integer name="config_tabTransitionDuration">100</integer>
+
+    <!-- The slope, in percent, of the drag movement needed to drag an item out of
+         AppsCustomize (y / x * 100%)  -->
+    <integer name="config_appsCustomizeDragSlopeThreshold">150</integer>
+
+    <!-- Fade in/out duration of toolbar/button bar icons.
+         Note: In + Out duration together should be less the duration of the transition
+               between AllApps, Customize & the Workspace. -->
+    <integer name="config_toolbarButtonFadeInTime">350</integer>
+    <integer name="config_toolbarButtonFadeOutTime">200</integer>
+
+    <!-- Batch loading for loading in LauncherModel -->
+    <integer name="config_allAppsBatchLoadDelay">0</integer>
+    <integer name="config_allAppsBatchSize">0</integer>
+
+<!-- Workspace -->
     <integer name="config_crosshairsFadeInTime">600</integer>
 
     <!--  When dragging an item on the workspace, how much bigger (in pixels) the dragged view
@@ -12,12 +43,6 @@
           Should be an even number, for pixel alignment. -->
     <integer name="config_dragViewExtraPixels">40</integer>
 
-    <!-- When dragging items on the workspace, the number of pixels by which the position of
-         the drag view should be offset from the position of the original view.
-         Setting to 1/2 of config_dragViewExtraPixels keeps it centered on its old position. -->
-    <integer name="config_dragViewOffsetX">20</integer>
-    <integer name="config_dragViewOffsetY">20</integer>
-
     <!-- The duration (in ms) of the fade animation on the object outlines, used when
          we are dragging objects around on the home screen. -->
     <integer name="config_dragOutlineFadeTime">900</integer>
@@ -25,21 +50,20 @@
     <!-- The alpha value at which to show the most recent drop visualization outline. -->
     <integer name="config_dragOutlineMaxAlpha">128</integer>
 
-    <!-- Workspace screens are cached to bitmaps only when they're smaller than a certain size
-         (maxScaleForUsingWorkspaceScreenBitmapCache), since the bitmap cache it self is smaller
-         than the view itself (workspaceScreenBitmapCacheScale)  -->
-    <integer name="config_workspaceScreenBitmapCacheScale">20</integer>
-    <integer name="config_maxScaleForUsingWorkspaceScreenBitmapCache">50</integer>
-
     <!-- Parameters controlling the animation for when an item is dropped on the home screen,
          and it animates from its old position to the new one. -->
 
     <integer name="config_dropAnimMaxDuration">400</integer>
 
+    <!-- The duration of the UserFolder opening and closing animation -->
+    <integer name="config_folderAnimDuration">100</integer>
+
     <!-- The distance at which the animation should take the max duration -->
     <integer name="config_dropAnimMaxDist">800</integer>
 
-    <style name="config_orientation">
-        <item name="@android:screenOrientation">nosensor</item>
-    </style>
+    <!-- Workspace screens are cached to bitmaps only when they're smaller than a certain size
+         (maxScaleForUsingWorkspaceScreenBitmapCache), since the bitmap cache itself is smaller
+         than the view itself (workspaceScreenBitmapCacheScale)  -->
+    <integer name="config_workspaceScreenBitmapCacheScale">20</integer>
+    <integer name="config_maxScaleForUsingWorkspaceScreenBitmapCache">50</integer>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d6cd3ee..99b1240 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -15,8 +15,16 @@
 -->
 
 <resources>
+<!-- AllApps/Customize/AppsCustomize -->
+    <!-- Size of icons in Workspace/AppsCustomize -->
+    <dimen name="app_icon_size">50dp</dimen>
+    <dimen name="apps_customize_cell_width">68dp</dimen>
+    <dimen name="apps_customize_cell_height">68dp</dimen>
     <dimen name="title_texture_width">120px</dimen>
 
+    <!-- height of the tab bar in AppsCustomize -->
+    <dimen name="apps_customize_tab_bar_height">56dp</dimen>
+
     <!-- height of the bottom row of controls -->
     <dimen name="button_bar_height">56dip</dimen>
 
@@ -24,6 +32,24 @@
          button_bar_height changes -->
     <dimen name="button_bar_height_portrait">56dip</dimen>
 
+    <!-- extra horizontal spacing between mini screen thumbnails ie. in all
+         apps and in customization mode -->
+    <dimen name="smallScreenExtraSpacing">0dip</dimen>
+
+    <!-- Vertical spacing between edge of screen and mini cell layouts when they
+         are minimized to the bottom in all apps -->
+    <dimen name="allAppsSmallScreenVerticalMarginLandscape">30dip</dimen>
+    <dimen name="allAppsSmallScreenVerticalMarginPortrait">60dip</dimen>
+
+    <!-- height & width of the drop rectangle for the trash icon -->
+    <dimen name="delete_zone_size">70dip</dimen>
+
+    <!-- delete_zone_size_full - button_bar_height_portrait -->
+    <dimen name="delete_zone_padding">14dip</dimen>
+
+    <!-- padding between the delete zone drawable and text -->
+    <dimen name="delete_zone_drawable_padding">8dip</dimen>
+
     <!-- roughly a status bar (for vertically centering the all apps
          home icon in landscape) -->
     <dimen name="status_bar_height">25dip</dimen>
@@ -32,16 +58,17 @@
          button cluster in landscape) -->
     <dimen name="half_status_bar_height">12dip</dimen>
 
-    <!-- Size of icons in workspace -->
-    <dimen name="app_icon_size">50dp</dimen>
-
-    <!-- height & width of the drop rectangle for the trash icon -->
-    <dimen name="delete_zone_size">70dip</dimen>
-    
-    <!-- delete_zone_size_full - button_bar_height_portrait -->
-    <dimen name="delete_zone_padding">14dip</dimen>
-
+<!-- Dragging -->
     <!-- the area at the edge of the screen that makes the workspace go left
          or right while you're dragging. -->
     <dimen name="scroll_zone">20dp</dimen>
+
+    <!-- When dragging items on the workspace, the number of dps by which the position of
+     the drag view should be offset from the position of the original view. -->
+    <dimen name="dragViewOffsetX">0dp</dimen>
+    <dimen name="dragViewOffsetY">-8dp</dimen>
+
+    <!-- Width/height gap overrides for the workspace -->
+    <dimen name="workspace_width_gap">-1dp</dimen>
+    <dimen name="workspace_height_gap">-1dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6dcaa57..9ad3e24 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -72,6 +72,8 @@
     <string name="all_apps_no_games">No games found.</string>
     <!-- Message to show when there are no downloaded apps [CHAR_LIMIT=50] -->
     <string name="all_apps_no_downloads">You have no downloaded applications.</string>
+    <!-- Market button text [CHAR LIMIT=32] -->
+    <string name="market">Shop</string>
 
     <!-- Customization Drawer -->
     <!-- The format string for the dimensions of a widget in the drawer -->
@@ -149,6 +151,21 @@
          device. [CHAR_LIMIT=30]-->
     <string name="delete_zone_label_all_apps">Uninstall</string>
 
+    <!-- Accessibility: Search button -->
+    <string name="accessibility_search_button">Search</string>
+    <!-- Accessibility: Voice Search button -->
+    <string name="accessibility_voice_search_button">Voice Search</string>
+    <!-- Accessibility: AllApps button -->
+    <string name="accessibility_all_apps_button">Applications</string>
+    <!-- Accessibility: Customize button -->
+    <string name="accessibility_customize_button">Customize</string>
+    <!-- Accessibility: Delete button -->
+    <string name="accessibility_delete_button">Remove</string>
+
+    <!-- Label for trash icon in All Apps, when an updated system app is selected. The update will
+         be uninstalled. [CHAR_LIMIT=30] -->
+    <string name="delete_zone_label_all_apps_system_app">Uninstall update</string>
+
     <!-- Menus items: -->
     <skip />
     <!-- Verb, menu item used to add an item on the desktop -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0c74a6a..abe6ac4 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -35,17 +35,17 @@
     </style>
     
     <style name="WorkspaceIcon">
-        <item name="android:textSize">13dip</item>
-        <item name="android:singleLine">true</item>
-        <item name="android:ellipsize">marquee</item>
-        <item name="android:shadowColor">#B0000000</item>
-        <item name="android:shadowRadius">2.0</item>
-        <item name="android:textColor">#FFF</item>
-        <item name="android:gravity">center_horizontal</item>
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">match_parent</item>
         <item name="android:paddingLeft">5dip</item>
         <item name="android:paddingRight">5dip</item>
+        <item name="android:gravity">center_horizontal</item>
+        <item name="android:singleLine">true</item>
+        <item name="android:ellipsize">marquee</item>
+        <item name="android:textSize">13dip</item>
+        <item name="android:textColor">#FFF</item>
+        <item name="android:shadowRadius">2.0</item>
+        <item name="android:shadowColor">#B0000000</item>
     </style>
 
     <style name="WorkspaceIcon.AllApps">
@@ -54,7 +54,7 @@
 
     <style name="WorkspaceIcon.Portrait">
         <item name="android:drawablePadding">5dip</item>
-        <item name="android:paddingTop">4dip</item>
+        <item name="android:paddingTop">0dip</item>
         <item name="android:layout_marginLeft">3dip</item>
         <item name="android:layout_marginRight">3dip</item>
         <item name="android:layout_marginTop">13dip</item>
@@ -72,24 +72,19 @@
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">match_parent</item>
         <item name="android:gravity">center</item>
-        <item name="android:paddingLeft">40dp</item>
-        <item name="android:paddingRight">40dp</item>
-        <item name="android:paddingTop">15dp</item>
-        <item name="android:paddingBottom">20dp</item>
-        <item name="android:textColor">@color/tab_widget_indicator_color</item>
+        <item name="android:paddingLeft">15dp</item>
+        <item name="android:paddingRight">15dp</item>
+        <item name="android:paddingTop">10dp</item>
+        <item name="android:paddingBottom">15dp</item>
         <item name="android:background">@drawable/tab_widget_indicator_selector</item>
-        <item name="android:textSize">20sp</item>
+        <item name="android:textColor">@color/tab_widget_indicator_color</item>
+        <item name="android:textSize">16sp</item>
         <item name="android:shadowColor">#393939</item>
         <item name="android:shadowDx">0.0</item>
         <item name="android:shadowDy">1.0</item>
         <item name="android:shadowRadius">1.0</item>
     </style>
 
-    <style name="TabIndicator.Portrait">
-        <item name="android:paddingLeft">20dp</item>
-        <item name="android:paddingRight">20dp</item>
-    </style>
-
     <style name="SearchButton" parent="@android:style/Widget.Button.Small">
         <item name="android:paddingTop">7dip</item>
         <item name="android:paddingBottom">9dip</item>
@@ -97,6 +92,29 @@
         <item name="android:paddingRight">10dip</item>
     </style>
 
+    <style name="MarketButton">
+        <item name="android:paddingRight">20dp</item>
+        <item name="android:text">@string/market</item>
+        <item name="android:textColor">@color/workspace_all_apps_and_delete_zone_text_color</item>
+        <item name="android:textSize">18sp</item>
+        <item name="android:shadowColor">@color/workspace_all_apps_and_delete_zone_text_shadow_color</item>
+        <item name="android:shadowDx">0.0</item>
+        <item name="android:shadowDy">0.0</item>
+        <item name="android:shadowRadius">2.0</item>
+    </style>
+
+    <style name="DeleteZone">
+        <item name="android:drawableLeft">@drawable/delete_zone_selector</item>
+        <item name="android:drawablePadding">@dimen/delete_zone_drawable_padding</item>
+        <item name="android:paddingRight">20dp</item>
+        <item name="android:textColor">@color/workspace_all_apps_and_delete_zone_text_color</item>
+        <item name="android:textSize">18sp</item>
+        <item name="android:shadowColor">@color/workspace_all_apps_and_delete_zone_text_shadow_color</item>
+        <item name="android:shadowDx">0.0</item>
+        <item name="android:shadowDy">0.0</item>
+        <item name="android:shadowRadius">2.0</item>
+    </style>
+
     <style name="HotseatButton">
         <item name="android:paddingLeft">12dip</item>
         <item name="android:paddingRight">12dip</item>
@@ -116,4 +134,7 @@
         <item name="android:background">@drawable/hotseat_bg_right</item>
     </style>
 
+    <style name="config_orientation">
+        <item name="@android:screenOrientation">nosensor</item>
+    </style>
 </resources>
diff --git a/src/com/android/launcher2/AccessibleTabView.java b/src/com/android/launcher2/AccessibleTabView.java
new file mode 100644
index 0000000..101f139
--- /dev/null
+++ b/src/com/android/launcher2/AccessibleTabView.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.widget.TextView;
+
+/**
+ * We use a custom tab view to process our own focus traversals.
+ */
+public class AccessibleTabView extends TextView {
+    public AccessibleTabView(Context context) {
+        super(context);
+    }
+
+    public AccessibleTabView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public AccessibleTabView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return FocusHelper.handleTabKeyEvent(this, keyCode, event)
+                || super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        return FocusHelper.handleTabKeyEvent(this, keyCode, event)
+                || super.onKeyUp(keyCode, event);
+    }
+}
diff --git a/src/com/android/launcher2/AddAdapter.java b/src/com/android/launcher2/AddAdapter.java
index 24c31ff..6f97d72 100644
--- a/src/com/android/launcher2/AddAdapter.java
+++ b/src/com/android/launcher2/AddAdapter.java
@@ -40,7 +40,6 @@
     
     public static final int ITEM_SHORTCUT = 0;
     public static final int ITEM_APPWIDGET = 1;
-    public static final int ITEM_LIVE_FOLDER = 2;
     public static final int ITEM_WALLPAPER = 3;
     
     /**
@@ -76,9 +75,6 @@
         mItems.add(new ListItem(res, R.string.group_widgets,
                 R.drawable.ic_launcher_appwidget, ITEM_APPWIDGET));
         
-        mItems.add(new ListItem(res, R.string.group_live_folders,
-                R.drawable.ic_launcher_folder, ITEM_LIVE_FOLDER));
-        
         mItems.add(new ListItem(res, R.string.group_wallpapers,
                 R.drawable.ic_launcher_wallpaper, ITEM_WALLPAPER));
 
diff --git a/src/com/android/launcher2/AllApps2D.java b/src/com/android/launcher2/AllApps2D.java
index 66d9395..44af7b7 100644
--- a/src/com/android/launcher2/AllApps2D.java
+++ b/src/com/android/launcher2/AllApps2D.java
@@ -143,7 +143,7 @@
                 homeButton.setOnClickListener(
                     new View.OnClickListener() {
                         public void onClick(View v) {
-                            mLauncher.closeAllApps(true);
+                            mLauncher.showWorkspace(true);
                         }
                     });
             }
@@ -158,8 +158,10 @@
         this(context, attrs);
     }
 
-    public void setLauncher(Launcher launcher) {
+    @Override
+    public void setup(Launcher launcher, DragController dragController) {
         mLauncher = launcher;
+        mDragController = dragController;
     }
 
     public boolean onKey(View v, int keyCode, KeyEvent event) {
@@ -167,7 +169,7 @@
 
         switch (keyCode) {
             case KeyEvent.KEYCODE_BACK:
-                mLauncher.closeAllApps(true);
+                mLauncher.showWorkspace(true);
                 break;
             default:
                 return false;
@@ -190,7 +192,7 @@
         app = new ApplicationInfo(app);
 
         mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
-        mLauncher.closeAllApps(true);
+        mLauncher.showWorkspace(true);
 
         return true;
     }
@@ -202,16 +204,11 @@
     }
 
     @Override
-    public void setDragController(DragController dragger) {
-        mDragController = dragger;
-    }
-
-    @Override
     public void onDragViewVisible() {
     }
 
     @Override
-    public void onDropCompleted(View target, boolean success) {
+    public void onDropCompleted(View target, Object dragInfo, boolean success) {
     }
 
     /**
@@ -313,19 +310,9 @@
         mVisibleAppsList.clear();
         if (appType == AppType.ALL) {
             mVisibleAppsList.addAll(mAllAppsList);
-        } else {
-            int searchFlags = 0;
-
-            if (appType == AppType.APP) {
-                searchFlags = ApplicationInfo.APP_FLAG;
-            } else if (appType == AppType.GAME) {
-                searchFlags = ApplicationInfo.GAME_FLAG;
-            } else if (appType == AppType.DOWNLOADED) {
-                searchFlags = ApplicationInfo.DOWNLOADED_FLAG;
-            }
-
+        } else if (appType == AppType.DOWNLOADED) {
             for (ApplicationInfo info : mAllAppsList) {
-                if ((info.flags & searchFlags) != 0) {
+                if ((info.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
                     mVisibleAppsList.add(info);
                 }
             }
@@ -351,6 +338,10 @@
     
     public void surrender() {
     }
+
+    public void reset() {
+        // Do nothing
+    }
 }
 
 
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index 2ecf761..0e512c6 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -155,13 +155,6 @@
             setRenderScriptGL(sRS);
         }
 
-        final DisplayMetrics metrics = getResources().getDisplayMetrics();
-        final boolean isPortrait = metrics.widthPixels < metrics.heightPixels;
-        mColumnsPerPage = isPortrait ? Defines.COLUMNS_PER_PAGE_PORTRAIT :
-                Defines.COLUMNS_PER_PAGE_LANDSCAPE;
-        mRowsPerPage = isPortrait ? Defines.ROWS_PER_PAGE_PORTRAIT :
-                Defines.ROWS_PER_PAGE_LANDSCAPE;
-
         if (sRollo != null) {
             sRollo.mAllApps = this;
             sRollo.mRes = getResources();
@@ -208,8 +201,10 @@
         setSoundEffectsEnabled(old);
     }
 
-    public void setLauncher(Launcher launcher) {
+    @Override
+    public void setup(Launcher launcher, DragController dragController) {
         mLauncher = launcher;
+        mDragController = dragController;
     }
 
     @Override
@@ -231,6 +226,12 @@
 
         super.surfaceChanged(holder, format, w, h);
 
+        final boolean isPortrait = w < h;
+        mColumnsPerPage = isPortrait ? Defines.COLUMNS_PER_PAGE_PORTRAIT :
+                Defines.COLUMNS_PER_PAGE_LANDSCAPE;
+        mRowsPerPage = isPortrait ? Defines.ROWS_PER_PAGE_PORTRAIT :
+                Defines.ROWS_PER_PAGE_LANDSCAPE;
+
         if (mSurrendered) return;
 
         mHaveSurface = true;
@@ -350,7 +351,7 @@
             if (mArrowNavigation) {
                 if (mLastSelection == SELECTION_HOME) {
                     reallyPlaySoundEffect(SoundEffectConstants.CLICK);
-                    mLauncher.closeAllApps(true);
+                    mLauncher.showWorkspace(true);
                 } else {
                     int whichApp = sRollo.mScript.get_gSelectedIconIndex();
                     if (whichApp >= 0) {
@@ -637,7 +638,7 @@
                     if ((isPortrait && y > mTouchYBorders[mTouchYBorders.length-1]) ||
                         (!isPortrait && x > mTouchXBorders[mTouchXBorders.length-1])) {
                         reallyPlaySoundEffect(SoundEffectConstants.CLICK);
-                        mLauncher.closeAllApps(true);
+                        mLauncher.showWorkspace(true);
                     }
                     sRollo.setHomeSelected(SELECTED_NONE);
                 }
@@ -685,18 +686,18 @@
                 && mCurrentIconIndex >= 0 && mCurrentIconIndex < mAllAppsList.size()) {
             ApplicationInfo app = mAllAppsList.get(mCurrentIconIndex);
 
-            Bitmap bmp = app.iconBitmap;
-            final int w = bmp.getWidth();
-            final int h = bmp.getHeight();
+            final Bitmap bmp = app.iconBitmap;
 
             // We don't really have an accurate location to use.  This will do.
-            int screenX = mMotionDownRawX - (w / 2);
-            int screenY = mMotionDownRawY - h;
+            int screenX = mMotionDownRawX - (bmp.getWidth() / 2);
+            int screenY = mMotionDownRawY - bmp.getHeight();
 
-            mDragController.startDrag(bmp, screenX, screenY,
-                    0, 0, w, h, this, app, DragController.DRAG_ACTION_COPY);
+            mLauncher.lockScreenOrientation();
+            mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, bmp);
+            mDragController.startDrag(
+                    bmp, screenX, screenY, this, app, DragController.DRAG_ACTION_COPY);
 
-            mLauncher.closeAllApps(true);
+            mLauncher.showWorkspace(true);
         }
         return true;
     }
@@ -739,16 +740,13 @@
     }
 
     @Override
-    public void setDragController(DragController dragger) {
-        mDragController = dragger;
-    }
-
-    @Override
     public void onDragViewVisible() {
     }
 
     @Override
-    public void onDropCompleted(View target, boolean success) {
+    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+        mLauncher.getWorkspace().onDragStopped(success);
+        mLauncher.unlockScreenOrientation();
     }
 
     /**
@@ -1047,13 +1045,16 @@
                 i.ScaleOffset.x = (2.f / 480.f);
                 i.ScaleOffset.y = 0;
                 i.ScaleOffset.z = -((float)w / 2) - 0.25f;
-                i.ScaleOffset.w = -380.25f;
-                i.BendPos.x = 120.f;
-                i.BendPos.y = 680.f;
-                if (w > h) {
-                    i.ScaleOffset.z = 40.f;
-                    i.ScaleOffset.w = h - 40.f;
-                    i.BendPos.y = 1.f;
+                if (w < h) {
+                    // portrait
+                    i.ScaleOffset.w = -380.25f;
+                    i.BendPos.x = 120.f;        // bottom of screen
+                    i.BendPos.y = h - 82.f;     // top of screen
+                } else {
+                    // landscape
+                    i.ScaleOffset.w = -206.25f;
+                    i.BendPos.x = 50.f;
+                    i.BendPos.y = h - 30.f;
                 }
                 mUniformAlloc.set(i, 0, true);
             }
@@ -1093,7 +1094,7 @@
                     "  float aDy = cos(bendAngle);\n" +
                     "  float aDz = sin(bendAngle);\n" +
 
-                    "  float scale = (2.0 / 480.0);\n" +
+                    "  float scale = (2.0 / " + mWidth + ".0);\n" +
                     "  float x = UNI_Position.x + UNI_ImgSize.x * (1.0 - ani) * (ATTRIB_position.x - 0.5);\n" +
                     "  float ys= UNI_Position.y + UNI_ImgSize.y * (1.0 - ani) * ATTRIB_position.y;\n" +
                     "  float y = 0.0;\n" +
@@ -1468,4 +1469,8 @@
             sRS.contextDump();
         }
     }
+
+    public void reset() {
+        // Do nothing
+    }
 }
diff --git a/src/com/android/launcher2/AllAppsBackground.java b/src/com/android/launcher2/AllAppsBackground.java
new file mode 100644
index 0000000..5292d0a
--- /dev/null
+++ b/src/com/android/launcher2/AllAppsBackground.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 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.launcher2;
+
+import com.android.launcher.R;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * An implementation of PagedView that populates the pages of the workspace
+ * with all of the user's applications.
+ */
+public class AllAppsBackground extends View {
+    private Drawable mBackground;
+
+    public AllAppsBackground(Context context) {
+        this(context, null);
+    }
+
+    public AllAppsBackground(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public AllAppsBackground(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mBackground = getResources().getDrawable(R.drawable.all_apps_bg_gradient);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        mBackground.setBounds(mScrollX, 0, mScrollX + getMeasuredWidth(),
+                getMeasuredHeight());
+        mBackground.draw(canvas);
+    }
+}
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index daa5d64..59ba57b 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -24,6 +24,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -63,7 +64,12 @@
     private int mAppFilter = ALL_APPS_FLAG;
 
     private final LayoutInflater mInflater;
+    private boolean mAllowHardwareLayerCreation;
 
+    private boolean mFirstMeasure = true;
+
+    private int mPageContentWidth;
+    private boolean mHasMadeSuccessfulDrop;
 
     public AllAppsPagedView(Context context) {
         this(context, null);
@@ -79,12 +85,14 @@
         mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 6);
         mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4);
         mInflater = LayoutInflater.from(context);
+        mApps = new ArrayList<ApplicationInfo>();
+        mFilteredApps = new ArrayList<ApplicationInfo>();
         a.recycle();
         setSoundEffectsEnabled(false);
 
         Resources r = context.getResources();
         setDragSlopeThreshold(
-                r.getInteger(R.integer.config_allAppsDrawerDragSlopeThreshold) / 100.0f);
+                r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold) / 100.0f);
     }
 
     @Override
@@ -94,14 +102,51 @@
     }
 
     @Override
-    public void setLauncher(Launcher launcher) {
-        mLauncher = launcher;
-        mLauncher.setAllAppsPagedView(this);
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+        if (mFirstMeasure) {
+            mFirstMeasure = false;
+
+            // TODO: actually calculate mCellCountX/mCellCountY as some function of
+            // widthSize and heightSize
+            //mCellCountX = ?;
+            //mCellCountY = ?;
+
+            // Since mCellCountX/mCellCountY changed, we need to update the pages
+            invalidatePageData();
+
+            // Create a dummy page and set it up to find out the content width (used by our parent)
+            PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
+            setupPage(layout);
+            mPageContentWidth = layout.getContentWidth();
+        }
+    }
+
+    void allowHardwareLayerCreation() {
+        // This is called after the first time we launch into All Apps. Before that point,
+        // there's no need for hardware layers here since there's a hardware layer set on the
+        // parent, AllAppsTabbed, during the AllApps transition -- creating hardware layers here
+        // before the animation is done slows down the animation
+        if (mAllowHardwareLayerCreation) {
+            return;
+        }
+        mAllowHardwareLayerCreation = true;
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            PagedViewCellLayout page = (PagedViewCellLayout) getChildAt(i);
+            page.allowHardwareLayerCreation();
+        }
     }
 
     @Override
-    public void setDragController(DragController dragger) {
-        mDragController = dragger;
+    public void setup(Launcher launcher, DragController dragController) {
+        mLauncher = launcher;
+        mLauncher.setAllAppsPagedView(this);
+        mDragController = dragController;
     }
 
     public void setAppFilter(int filterType) {
@@ -113,14 +158,16 @@
         }
     }
 
+    void resetSuccessfulDropFlag() {
+        mHasMadeSuccessfulDrop = false;
+    }
+
     @Override
     public void zoom(float zoom, boolean animate) {
         mZoom = zoom;
         cancelLongPress();
 
         if (isVisible()) {
-            getParent().bringChildToFront(this);
-            setVisibility(View.VISIBLE);
             if (animate) {
                 startAnimation(AnimationUtils.loadAnimation(getContext(),
                         R.anim.all_apps_2d_fade_in));
@@ -139,7 +186,6 @@
 
     protected void onAnimationEnd() {
         if (!isVisible()) {
-            setVisibility(View.GONE);
             mZoom = 0.0f;
 
             endChoiceMode();
@@ -201,11 +247,21 @@
         }
     }
 
-    private void setupDragMode() {
+    private void setupDragMode(ApplicationInfo info) {
         mLauncher.getWorkspace().shrink(Workspace.ShrinkState.BOTTOM_VISIBLE);
-        DeleteZone allAppsDeleteZone = (DeleteZone)
-                mLauncher.findViewById(R.id.all_apps_delete_zone);
-        allAppsDeleteZone.setDragAndDropEnabled(true);
+
+        // Only show the uninstall button if the app is uninstallable.
+        if ((info.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
+            DeleteZone allAppsDeleteZone = (DeleteZone)
+                    mLauncher.findViewById(R.id.all_apps_delete_zone);
+            allAppsDeleteZone.setDragAndDropEnabled(true);
+
+            if ((info.flags & ApplicationInfo.UPDATED_SYSTEM_APP_FLAG) != 0) {
+                allAppsDeleteZone.setText(R.string.delete_zone_label_all_apps_system_app);
+            } else {
+                allAppsDeleteZone.setText(R.string.delete_zone_label_all_apps);
+            }
+        }
 
         ApplicationInfoDropTarget allAppsInfoButton =
                 (ApplicationInfoDropTarget) mLauncher.findViewById(R.id.all_apps_info_target);
@@ -238,12 +294,12 @@
         if (!v.isInTouchMode()) return false;
         if (!super.beginDragging(v)) return false;
 
-        // Start drag mode after the item is selected
-        setupDragMode();
-
         ApplicationInfo app = (ApplicationInfo) v.getTag();
         app = new ApplicationInfo(app);
 
+        // Start drag mode after the item is selected
+        setupDragMode(app);
+
         // get icon (top compound drawable, index is 1)
         final TextView tv = (TextView) v;
         final Drawable icon = tv.getCompoundDrawables()[1];
@@ -253,6 +309,16 @@
         c.translate((v.getWidth() - icon.getIntrinsicWidth()) / 2, v.getPaddingTop());
         icon.draw(c);
 
+        Rect dragRect = null;
+        if (v instanceof TextView) {
+            int iconSize = getResources().getDimensionPixelSize(R.dimen.app_icon_size);
+            int top = v.getPaddingTop();
+            int left = (b.getWidth() - iconSize) / 2;
+            int right = left + iconSize;
+            int bottom = top + iconSize;
+            dragRect = new Rect(left, top, right, bottom);
+        }
+
         // We toggle the checked state _after_ we create the view for the drag in case toggling the
         // checked state changes the view's look
         if (v instanceof Checkable) {
@@ -272,7 +338,7 @@
         // Start the drag
         mLauncher.lockScreenOrientation();
         mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
-        mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, null);
+        mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, dragRect);
         b.recycle();
         return true;
     }
@@ -282,7 +348,7 @@
     }
 
     @Override
-    public void onDropCompleted(View target, boolean success) {
+    public void onDropCompleted(View target, Object dragInfo, boolean success) {
         // close the choice action mode if we have a proper drop
         if (target != this) {
             endChoiceMode();
@@ -290,6 +356,16 @@
         tearDownDragMode();
         mLauncher.getWorkspace().onDragStopped(success);
         mLauncher.unlockScreenOrientation();
+
+        if (!success && !mHasMadeSuccessfulDrop) {
+            mLauncher.getWorkspace().shrink(Workspace.ShrinkState.BOTTOM_HIDDEN);
+        } else {
+            mHasMadeSuccessfulDrop |= success;
+        }
+    }
+
+    int getPageContentWidth() {
+        return mPageContentWidth;
     }
 
     @Override
@@ -376,6 +452,7 @@
         }
         mFilteredApps = rebuildFilteredApps(mApps);
     }
+
     @Override
     public void removeApps(ArrayList<ApplicationInfo> list) {
         removeAppsWithoutInvalidate(list);
@@ -390,12 +467,14 @@
     }
 
     private int findAppByComponent(ArrayList<ApplicationInfo> list, ApplicationInfo item) {
-        ComponentName removeComponent = item.intent.getComponent();
-        final int length = list.size();
-        for (int i = 0; i < length; ++i) {
-            ApplicationInfo info = list.get(i);
-            if (info.intent.getComponent().equals(removeComponent)) {
-                return i;
+        if (item != null && item.intent != null) {
+            ComponentName removeComponent = item.intent.getComponent();
+            final int length = list.size();
+            for (int i = 0; i < length; ++i) {
+                ApplicationInfo info = list.get(i);
+                if (info.intent.getComponent().equals(removeComponent)) {
+                    return i;
+                }
             }
         }
         return -1;
@@ -411,8 +490,25 @@
         // do nothing?
     }
 
+    public void reset() {
+        setCurrentPage(0);
+        invalidatePageData();
+    }
+
+    private void setupPage(PagedViewCellLayout layout) {
+        layout.setCellCount(mCellCountX, mCellCountY);
+        layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop, mPageLayoutPaddingRight,
+                mPageLayoutPaddingBottom);
+        layout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
+    }
+
     @Override
     public void syncPages() {
+        if (mFirstMeasure) {
+            // We don't know our size yet, which means we haven't calculated cell count x/y;
+            // onMeasure will call us once we figure out our size
+            return;
+        }
         // ensure that we have the right number of pages (min of 1, since we have placeholders)
         int numPages = Math.max(1,
                 (int) Math.ceil((float) mFilteredApps.size() / (mCellCountX * mCellCountY)));
@@ -425,11 +521,10 @@
         // add any necessary pages
         for (int i = curNumPages; i < numPages; ++i) {
             PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
-            layout.enableHardwareLayers();
-            layout.setCellCount(mCellCountX, mCellCountY);
-            layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
-                    mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
-            layout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
+            if (mAllowHardwareLayerCreation) {
+                layout.allowHardwareLayerCreation();
+            }
+            setupPage(layout);
             addView(layout);
         }
 
@@ -440,6 +535,7 @@
     @Override
     public void syncPageItems(int page) {
         // Ensure that we have the right number of items on the pages
+        final int numPages = getPageCount();
         final int cellsPerPage = mCellCountX * mCellCountY;
         final int startIndex = page * cellsPerPage;
         final int endIndex = Math.min(startIndex + cellsPerPage, mFilteredApps.size());
@@ -448,6 +544,7 @@
         if (!mFilteredApps.isEmpty()) {
             int curNumPageItems = layout.getPageChildCount();
             int numPageItems = endIndex - startIndex;
+            boolean createHolographicOutlines = (numPages > 1);
 
             // If we were previously an empty page, then restart anew
             boolean wasEmptyPage = false;
@@ -483,12 +580,12 @@
             }
 
             // Actually reapply to the existing text views
-            final int numPages = getPageCount();
             for (int i = startIndex; i < endIndex; ++i) {
                 final int index = i - startIndex;
                 final ApplicationInfo info = mFilteredApps.get(i);
                 PagedViewIcon icon = (PagedViewIcon) layout.getChildOnPageAt(index);
-                icon.applyFromApplicationInfo(info, mPageViewIconCache, true, (numPages > 1));
+                icon.applyFromApplicationInfo(
+                        info, mPageViewIconCache, true, createHolographicOutlines);
 
                 PagedViewCellLayout.LayoutParams params =
                     (PagedViewCellLayout.LayoutParams) icon.getLayoutParams();
@@ -496,6 +593,9 @@
                 params.cellY = index / mCellCountX;
             }
 
+            // We should try and sync all the holographic icons after adding/removing new items
+            layout.reloadHolographicIcons(createHolographicOutlines);
+
             // Default to left-aligned icons
             layout.enableCenteredContent(false);
         } else {
@@ -510,11 +610,13 @@
             }
 
             // Center-align the message
+            final boolean createHolographicOutlines = (numPages > 1);
             layout.enableCenteredContent(true);
             layout.removeAllViewsOnPage();
             layout.addViewToCellLayout(icon, -1, 0,
                     new PagedViewCellLayout.LayoutParams(0, 0, 4, 1));
         }
+        layout.createHardwareLayers();
     }
 
     /*
diff --git a/src/com/android/launcher2/AllAppsTabbed.java b/src/com/android/launcher2/AllAppsTabbed.java
index 47a5bf7..a2f10f5 100644
--- a/src/com/android/launcher2/AllAppsTabbed.java
+++ b/src/com/android/launcher2/AllAppsTabbed.java
@@ -29,6 +29,7 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.TabHost;
 import android.widget.TabWidget;
 import android.widget.TextView;
@@ -38,7 +39,7 @@
 /**
  * Implements a tabbed version of AllApps2D.
  */
-public class AllAppsTabbed extends TabHost implements AllAppsView {
+public class AllAppsTabbed extends TabHost implements AllAppsView, LauncherTransitionable {
 
     private static final String TAG = "Launcher.AllAppsTabbed";
 
@@ -46,6 +47,8 @@
     private static final String TAG_DOWNLOADED = "DOWNLOADED";
 
     private AllAppsPagedView mAllApps;
+    private AllAppsBackground mBackground;
+    private Launcher mLauncher;
     private Context mContext;
     private final LayoutInflater mInflater;
     private boolean mFirstLayout = true;
@@ -64,6 +67,8 @@
         try {
             mAllApps = (AllAppsPagedView) findViewById(R.id.all_apps_paged_view);
             if (mAllApps == null) throw new Resources.NotFoundException();
+            mBackground = (AllAppsBackground) findViewById(R.id.all_apps_background);
+            if (mBackground == null) throw new Resources.NotFoundException();
         } catch (Resources.NotFoundException e) {
             Log.e(TAG, "Can't find necessary layout elements for AllAppsTabbed");
         }
@@ -75,6 +80,8 @@
             }
         };
 
+        // Create the tabs and wire them up properly
+        AllAppsTabKeyEventListener keyListener = new AllAppsTabKeyEventListener();
         TextView tabView;
         TabWidget tabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
         tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
@@ -85,11 +92,17 @@
         tabView.setText(mContext.getString(R.string.all_apps_tab_downloaded));
         addTab(newTabSpec(TAG_DOWNLOADED).setIndicator(tabView).setContent(contentFactory));
 
+        // Setup the key listener to jump between the last tab view and the market icon
+        View lastTab = tabWidget.getChildTabViewAt(tabWidget.getTabCount() - 1);
+        lastTab.setOnKeyListener(keyListener);
+        View shopButton = findViewById(R.id.market_button);
+        shopButton.setOnKeyListener(keyListener);
+
         setOnTabChangedListener(new OnTabChangeListener() {
             public void onTabChanged(String tabId) {
                 // animate the changing of the tab content by fading pages in and out
                 final Resources res = getResources();
-                final int duration = res.getInteger(R.integer.config_tabTransitionTime);
+                final int duration = res.getInteger(R.integer.config_tabTransitionDuration);
                 final float alpha = mAllApps.getAlpha();
                 ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mAllApps, "alpha", alpha, 0.0f).
                         setDuration(duration);
@@ -112,19 +125,16 @@
             }
         });
 
+
         // It needs to be INVISIBLE so that it will be measured in the layout.
         // Otherwise the animations is messed up when we show it for the first time.
         setVisibility(INVISIBLE);
     }
 
     @Override
-    public void setLauncher(Launcher launcher) {
-        mAllApps.setLauncher(launcher);
-    }
-
-    @Override
-    public void setDragController(DragController dragger) {
-        mAllApps.setDragController(dragger);
+    public void setup(Launcher launcher, DragController dragController) {
+        mLauncher = launcher;
+        mAllApps.setup(launcher, dragController);
     }
 
     @Override
@@ -154,7 +164,20 @@
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        mFirstLayout = false;
+        if (mFirstLayout) {
+            mFirstLayout = false;
+            // Set the width of the tab bar properly
+            int pageWidth = mAllApps.getPageContentWidth();
+            TabWidget tabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
+            View allAppsTabBar = (View) findViewById(R.id.all_apps_tab_bar);
+            if (allAppsTabBar == null) throw new Resources.NotFoundException();
+            int tabWidgetPadding = 0;
+            final int childCount = tabWidget.getChildCount();
+            if (childCount > 0) {
+                tabWidgetPadding += tabWidget.getChildAt(0).getPaddingLeft() * 2;
+            }
+            allAppsTabBar.getLayoutParams().width = pageWidth + tabWidgetPadding;
+        }
         super.onLayout(changed, l, t, r, b);
     }
 
@@ -164,6 +187,44 @@
     }
 
     @Override
+    public void onLauncherTransitionStart(Animator animation) {
+        if (animation != null) {
+            // Turn on hardware layers for performance
+            setLayerType(LAYER_TYPE_HARDWARE, null);
+            // Re-enable the rendering of the dimmed background in All Apps for performance reasons
+            // if we're fading it in
+            if (mLauncher.getWorkspace().getBackgroundAlpha() == 0f) {
+                mLauncher.getWorkspace().disableBackground();
+                mBackground.setVisibility(VISIBLE);
+            }
+            // just a sanity check that we don't build a layer before a call to onLayout
+            if (!mFirstLayout) {
+                // force building the layer at the beginning of the animation, so you don't get a
+                // blip early in the animation
+                buildLayer();
+            }
+        }
+    }
+
+    @Override
+    public void onLauncherTransitionEnd(Animator animation) {
+        if (animation != null) {
+            setLayerType(LAYER_TYPE_NONE, null);
+            // To improve the performance of the first time All Apps is run, we initially keep
+            // hardware layers in AllAppsPagedView disabled since AllAppsTabbed itself is drawn in a
+            // hardware layer, and creating additional hardware layers slows down the animation. We
+            // create them here, after the animation is over.
+        }
+        // Move the rendering of the dimmed background to workspace after the all apps animation
+        // is done, so that the background is not rendered *above* the mini workspace screens
+        if (mBackground.getVisibility() != GONE) {
+            mLauncher.getWorkspace().enableBackground();
+            mBackground.setVisibility(GONE);
+        }
+        mAllApps.allowHardwareLayerCreation();
+    }
+
+    @Override
     public void setApps(ArrayList<ApplicationInfo> list) {
         mAllApps.setApps(list);
     }
@@ -193,6 +254,10 @@
         mAllApps.surrender();
     }
 
+    public void reset() {
+        mAllApps.reset();
+    }
+
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         if (ev.getY() > mAllApps.getBottom()) {
@@ -200,4 +265,12 @@
         }
         return true;
     }
+
+    @Override
+    public int getDescendantFocusability() {
+        if (getVisibility() != View.VISIBLE) {
+            return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+        }
+        return super.getDescendantFocusability();
+    }
 }
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index 007ecf8..e8ca61f 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -23,9 +23,7 @@
         public void zoomed(float zoom);
     }
 
-    public void setLauncher(Launcher launcher);
-
-    public void setDragController(DragController dragger);
+    public void setup(Launcher launcher, DragController dragController);
 
     public void zoom(float zoom, boolean animate);
 
@@ -41,6 +39,9 @@
 
     public void updateApps(ArrayList<ApplicationInfo> list);
     
+    // Resets the AllApps page to the front
+    public void reset();
+
     public void dumpState();
 
     public void surrender();
diff --git a/src/com/android/launcher2/AppWidgetResizeFrame.java b/src/com/android/launcher2/AppWidgetResizeFrame.java
new file mode 100644
index 0000000..4390c59
--- /dev/null
+++ b/src/com/android/launcher2/AppWidgetResizeFrame.java
@@ -0,0 +1,350 @@
+package com.android.launcher2;
+
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+import android.view.Gravity;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.android.launcher.R;
+
+public class AppWidgetResizeFrame extends FrameLayout {
+
+    private ItemInfo mItemInfo;
+    private LauncherAppWidgetHostView mWidgetView;
+    private CellLayout mCellLayout;
+    private DragLayer mDragLayer;
+    private Workspace mWorkspace;
+    private ImageView mLeftHandle;
+    private ImageView mRightHandle;
+    private ImageView mTopHandle;
+    private ImageView mBottomHandle;
+
+    private boolean mLeftBorderActive;
+    private boolean mRightBorderActive;
+    private boolean mTopBorderActive;
+    private boolean mBottomBorderActive;
+
+    private int mBaselineWidth;
+    private int mBaselineHeight;
+    private int mBaselineX;
+    private int mBaselineY;
+    private int mResizeMode;
+
+    private int mRunningHInc;
+    private int mRunningVInc;
+    private int mMinHSpan;
+    private int mMinVSpan;
+    private int mDeltaX;
+    private int mDeltaY;
+
+    private int mBackgroundPadding;
+    private int mTouchTargetWidth;
+
+    private int mExpandability[] = new int[4];
+
+    final int SNAP_DURATION = 150;
+    final int BACKGROUND_PADDING = 24;
+    final float DIMMED_HANDLE_ALPHA = 0f;
+    final float RESIZE_THRESHOLD = 0.66f;
+
+    public static final int LEFT = 0;
+    public static final int TOP = 1;
+    public static final int RIGHT = 2;
+    public static final int BOTTOM = 3;
+
+    public AppWidgetResizeFrame(Context context, ItemInfo itemInfo, 
+            LauncherAppWidgetHostView widgetView, CellLayout cellLayout, DragLayer dragLayer) {
+
+        super(context);
+        mContext = context;
+        mItemInfo = itemInfo;
+        mCellLayout = cellLayout;
+        mWidgetView = widgetView;
+        mResizeMode = widgetView.getAppWidgetInfo().resizeMode;
+        mDragLayer = dragLayer;
+        mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
+
+        final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
+        int[] result = mCellLayout.rectToCell(info.minWidth, info.minHeight, null);
+        mMinHSpan = result[0];
+        mMinVSpan = result[1];
+
+        setBackgroundResource(R.drawable.widget_resize_frame_holo);
+        setPadding(0, 0, 0, 0);
+
+        LayoutParams lp;
+        mLeftHandle = new ImageView(context);
+        mLeftHandle.setImageResource(R.drawable.widget_resize_handle_left);
+        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 
+                Gravity.LEFT | Gravity.CENTER_VERTICAL);
+        addView(mLeftHandle, lp);
+
+        mRightHandle = new ImageView(context);
+        mRightHandle.setImageResource(R.drawable.widget_resize_handle_right);
+        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 
+                Gravity.RIGHT | Gravity.CENTER_VERTICAL);
+        addView(mRightHandle, lp);
+
+        mTopHandle = new ImageView(context);
+        mTopHandle.setImageResource(R.drawable.widget_resize_handle_top);
+        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 
+                Gravity.CENTER_HORIZONTAL | Gravity.TOP);
+        addView(mTopHandle, lp);
+
+        mBottomHandle = new ImageView(context);
+        mBottomHandle.setImageResource(R.drawable.widget_resize_handle_bottom);
+        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 
+                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+        addView(mBottomHandle, lp);
+
+        if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
+            mTopHandle.setVisibility(GONE);
+            mBottomHandle.setVisibility(GONE);
+        } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) {
+            mLeftHandle.setVisibility(GONE);
+            mRightHandle.setVisibility(GONE);
+        }
+
+        final float density = mContext.getResources().getDisplayMetrics().density;
+        mBackgroundPadding = (int) Math.ceil(density * BACKGROUND_PADDING);
+        mTouchTargetWidth = 2 * mBackgroundPadding;
+    }
+
+    public boolean beginResizeIfPointInRegion(int x, int y) {
+        boolean horizontalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0;
+        boolean verticalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0;
+        mLeftBorderActive = (x < mTouchTargetWidth) && horizontalActive;
+        mRightBorderActive = (x > getWidth() - mTouchTargetWidth) && horizontalActive;
+        mTopBorderActive = (y < mTouchTargetWidth) && verticalActive;
+        mBottomBorderActive = (y > getHeight() - mTouchTargetWidth) && verticalActive;
+
+        boolean anyBordersActive = mLeftBorderActive || mRightBorderActive
+                || mTopBorderActive || mBottomBorderActive;
+
+        mBaselineWidth = getMeasuredWidth();
+        mBaselineHeight = getMeasuredHeight();
+        mBaselineX = getLeft();
+        mBaselineY = getTop();
+        mRunningHInc = 0;
+        mRunningVInc = 0;
+
+        if (anyBordersActive) {
+            mLeftHandle.setAlpha(mLeftBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
+            mRightHandle.setAlpha(mRightBorderActive ? 1.0f :DIMMED_HANDLE_ALPHA);
+            mTopHandle.setAlpha(mTopBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
+            mBottomHandle.setAlpha(mBottomBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
+        }
+        mCellLayout.getExpandabilityArrayForView(mWidgetView, mExpandability);
+
+        return anyBordersActive;
+    }
+
+    /**
+     *  Here we bound the deltas such that the frame cannot be stretched beyond the extents
+     *  of the CellLayout, and such that the frame's borders can't cross.
+     */
+    public void updateDeltas(int deltaX, int deltaY) {
+        if (mLeftBorderActive) {
+            mDeltaX = Math.max(-mBaselineX, deltaX); 
+            mDeltaX = Math.min(mBaselineWidth - 2 * mTouchTargetWidth, mDeltaX);
+        } else if (mRightBorderActive) {
+            mDeltaX = Math.min(mDragLayer.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
+            mDeltaX = Math.max(-mBaselineWidth + 2 * mTouchTargetWidth, mDeltaX);
+        }
+
+        if (mTopBorderActive) {
+            mDeltaY = Math.max(-mBaselineY, deltaY);
+            mDeltaY = Math.min(mBaselineHeight - 2 * mTouchTargetWidth, mDeltaY);
+        } else if (mBottomBorderActive) {
+            mDeltaY = Math.min(mDragLayer.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
+            mDeltaY = Math.max(-mBaselineHeight + 2 * mTouchTargetWidth, mDeltaY);
+        }
+    }
+
+    /**
+     *  Based on the deltas, we resize the frame, and, if needed, we resize the widget.
+     */
+    public void visualizeResizeForDelta(int deltaX, int deltaY) {
+        updateDeltas(deltaX, deltaY);
+        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+
+        if (mLeftBorderActive) {
+            lp.x = mBaselineX + mDeltaX;
+            lp.width = mBaselineWidth - mDeltaX;
+        } else if (mRightBorderActive) {
+            lp.width = mBaselineWidth + mDeltaX;
+        }
+
+        if (mTopBorderActive) {
+            lp.y = mBaselineY + mDeltaY;
+            lp.height = mBaselineHeight - mDeltaY;
+        } else if (mBottomBorderActive) {
+            lp.height = mBaselineHeight + mDeltaY;
+        }
+
+        resizeWidgetIfNeeded();
+        requestLayout();
+    }
+
+    /**
+     *  Based on the current deltas, we determine if and how to resize the widget.
+     */
+    private void resizeWidgetIfNeeded() {
+        int xThreshold = mCellLayout.getCellWidth() + mCellLayout.getWidthGap();
+        int yThreshold = mCellLayout.getCellHeight() + mCellLayout.getHeightGap();
+
+        float hSpanIncF = 1.0f * mDeltaX / xThreshold - mRunningHInc;
+        float vSpanIncF = 1.0f * mDeltaY / yThreshold - mRunningVInc;
+
+        int hSpanInc = 0;
+        int vSpanInc = 0;
+        int cellXInc = 0;
+        int cellYInc = 0;
+
+        if (Math.abs(hSpanIncF) > RESIZE_THRESHOLD) {
+            hSpanInc = Math.round(hSpanIncF);
+        }
+        if (Math.abs(vSpanIncF) > RESIZE_THRESHOLD) {
+            vSpanInc = Math.round(vSpanIncF);
+        }
+
+        if (hSpanInc == 0 && vSpanInc == 0) return;
+
+        // Before we change the widget, we clear the occupied cells associated with it.
+        // The new set of occupied cells is marked below, once the layout params are updated.
+        mCellLayout.markCellsAsUnoccupiedForView(mWidgetView);
+
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams();
+
+        // For each border, we bound the resizing based on the minimum width, and the maximum
+        // expandability.
+        if (mLeftBorderActive) {
+            cellXInc = Math.max(-mExpandability[LEFT], hSpanInc);
+            cellXInc = Math.min(lp.cellHSpan - mMinHSpan, cellXInc);
+            hSpanInc *= -1;
+            hSpanInc = Math.min(mExpandability[LEFT], hSpanInc);
+            hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc);
+            mRunningHInc -= hSpanInc;
+        } else if (mRightBorderActive) {
+            hSpanInc = Math.min(mExpandability[RIGHT], hSpanInc);
+            hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc);
+            mRunningHInc += hSpanInc;
+        }
+
+        if (mTopBorderActive) {
+            cellYInc = Math.max(-mExpandability[TOP], vSpanInc);
+            cellYInc = Math.min(lp.cellVSpan - mMinVSpan, cellYInc);
+            vSpanInc *= -1;
+            vSpanInc = Math.min(mExpandability[TOP], vSpanInc);
+            vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc);
+            mRunningVInc -= vSpanInc;
+        } else if (mBottomBorderActive) {
+            vSpanInc = Math.min(mExpandability[BOTTOM], vSpanInc);
+            vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc);
+            mRunningVInc += vSpanInc;
+        }
+
+        // Update the widget's dimensions and position according to the deltas computed above
+        if (mLeftBorderActive || mRightBorderActive) {
+            lp.cellHSpan += hSpanInc;
+            lp.cellX += cellXInc;
+        }
+
+        if (mTopBorderActive || mBottomBorderActive) {
+            lp.cellVSpan += vSpanInc;
+            lp.cellY += cellYInc;
+        }
+
+        // Update the expandability array, as we have changed the widget's size.
+        mCellLayout.getExpandabilityArrayForView(mWidgetView, mExpandability);
+
+        // Update the cells occupied by this widget
+        mCellLayout.markCellsAsOccupiedForView(mWidgetView);
+        mWidgetView.requestLayout();
+    }
+
+    /**
+     * This is the final step of the resize. Here we save the new widget size and position
+     * to LauncherModel and animate the resize frame.
+     */
+    public void commitResizeForDelta(int deltaX, int deltaY) {
+        visualizeResizeForDelta(deltaX, deltaY);
+
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams();
+        LauncherModel.resizeItemInDatabase(getContext(), mItemInfo, lp.cellX, lp.cellY,
+                lp.cellHSpan, lp.cellVSpan);
+        mWidgetView.requestLayout();
+
+        // Once our widget resizes (hence the post), we want to snap the resize frame to it
+        post(new Runnable() {
+            public void run() {
+                snapToWidget(true);
+            }
+        });
+    }
+
+    public void snapToWidget(boolean animate) {
+        final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+        int xOffset = mCellLayout.getLeft() + mCellLayout.getLeftPadding() - mWorkspace.getScrollX();
+        int yOffset = mCellLayout.getTop() + mCellLayout.getTopPadding() - mWorkspace.getScrollY();
+
+        int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding;
+        int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding;
+        int newX = mWidgetView.getLeft() - mBackgroundPadding + xOffset;
+        int newY = mWidgetView.getTop() - mBackgroundPadding + yOffset;
+
+        // We need to make sure the frame stays within the bounds of the CellLayout
+        if (newY < 0) {
+            newHeight -= -newY;
+            newY = 0;
+        }
+        if (newY + newHeight > mDragLayer.getHeight()) {
+            newHeight -= newY + newHeight - mDragLayer.getHeight();
+        }
+
+        if (!animate) {
+            lp.width = newWidth;
+            lp.height = newHeight;
+            lp.x = newX;
+            lp.y = newY;
+            mLeftHandle.setAlpha(1.0f);
+            mRightHandle.setAlpha(1.0f);
+            mTopHandle.setAlpha(1.0f);
+            mBottomHandle.setAlpha(1.0f);
+            requestLayout();
+        } else {
+            PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", lp.width, newWidth);
+            PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", lp.height,
+                    newHeight);
+            PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", lp.x, newX);
+            PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", lp.y, newY);
+            ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
+            ObjectAnimator leftOa = ObjectAnimator.ofFloat(mLeftHandle, "alpha", 1.0f);
+            ObjectAnimator rightOa = ObjectAnimator.ofFloat(mRightHandle, "alpha", 1.0f);
+            ObjectAnimator topOa = ObjectAnimator.ofFloat(mTopHandle, "alpha", 1.0f);
+            ObjectAnimator bottomOa = ObjectAnimator.ofFloat(mBottomHandle, "alpha", 1.0f);
+            oa.addUpdateListener(new AnimatorUpdateListener() {
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    requestLayout();
+                }
+            });
+            AnimatorSet set = new AnimatorSet();
+            if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) {
+                set.playTogether(oa, topOa, bottomOa);
+            } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
+                set.playTogether(oa, leftOa, rightOa);
+            } else {
+                set.playTogether(oa, leftOa, rightOa, topOa, bottomOa);
+            }
+
+            set.setDuration(SNAP_DURATION);
+            set.start();
+        }
+    }
+}
diff --git a/src/com/android/launcher2/ApplicationInfo.java b/src/com/android/launcher2/ApplicationInfo.java
index 3adea37..1d948b7 100644
--- a/src/com/android/launcher2/ApplicationInfo.java
+++ b/src/com/android/launcher2/ApplicationInfo.java
@@ -59,9 +59,9 @@
 
     ComponentName componentName;
 
-    static final int APP_FLAG = 1;
-    static final int GAME_FLAG = 2;
-    static final int DOWNLOADED_FLAG = 4;
+    static final int DOWNLOADED_FLAG = 1;
+    static final int UPDATED_SYSTEM_APP_FLAG = 2;
+
     int flags = 0;
 
     ApplicationInfo() {
@@ -83,17 +83,12 @@
             int appFlags = pm.getApplicationInfo(packageName, 0).flags;
             if ((appFlags & android.content.pm.ApplicationInfo.FLAG_SYSTEM) == 0) {
                 flags |= DOWNLOADED_FLAG;
-            }
-            if ((appFlags & android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
-                flags |= DOWNLOADED_FLAG;
+
+                if ((appFlags & android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+                    flags |= UPDATED_SYSTEM_APP_FLAG;
+                }
             }
             firstInstallTime = pm.getPackageInfo(packageName, 0).firstInstallTime;
-            // TODO: Figure out how to determine what is a game
-
-            // If it's not a game, it's an app
-            if ((flags & GAME_FLAG) == 0) {
-                flags |= APP_FLAG;
-            }
         } catch (NameNotFoundException e) {
             Log.d(TAG, "PackageManager.getApplicationInfo failed for " + packageName);
         }
diff --git a/src/com/android/launcher2/ApplicationInfoDropTarget.java b/src/com/android/launcher2/ApplicationInfoDropTarget.java
index 78a9d2d..f42aaf5 100644
--- a/src/com/android/launcher2/ApplicationInfoDropTarget.java
+++ b/src/com/android/launcher2/ApplicationInfoDropTarget.java
@@ -50,7 +50,7 @@
         int colour = getContext().getResources().getColor(R.color.app_info_filter);
         mHoverPaint.setColorFilter(new PorterDuffColorFilter(colour, PorterDuff.Mode.SRC_ATOP));
 
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
             // For the application info drop target, we just ignore the left padding since we don't want
             // to overlap with the delete zone padding
             int tb = getResources().getDimensionPixelSize(
@@ -162,10 +162,13 @@
         // Fade in the overlapping views
         if (mOverlappingViews != null) {
             for (View view : mOverlappingViews) {
-                ObjectAnimator oa = ObjectAnimator.ofFloat(view, "alpha", 1.0f);
-                oa.setDuration(sFadeInAnimationDuration);
-                mFadeAnimator.play(oa);
-                view.setVisibility(VISIBLE);
+                // Check whether the views are enabled first, before trying to fade them in
+                if (view.isEnabled()) {
+                    ObjectAnimator oa = ObjectAnimator.ofFloat(view, "alpha", 1.0f);
+                    oa.setDuration(sFadeInAnimationDuration);
+                    mFadeAnimator.play(oa);
+                    view.setVisibility(VISIBLE);
+                }
             }
         }
         mFadeAnimator.start();
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
new file mode 100644
index 0000000..87be63e
--- /dev/null
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -0,0 +1,1084 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.app.WallpaperManager;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.LruCache;
+import android.util.Slog;
+import android.util.TypedValue;
+import android.util.Xml;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.launcher.R;
+
+public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
+        AllAppsView, View.OnClickListener, DragSource {
+    static final String LOG_TAG = "AppsCustomizePagedView";
+
+    /**
+     * The different content types that this paged view can show.
+     */
+    public enum ContentType {
+        Applications,
+        Widgets,
+        Wallpapers
+    }
+
+    // Refs
+    private Launcher mLauncher;
+    private DragController mDragController;
+    private final LayoutInflater mLayoutInflater;
+    private final PackageManager mPackageManager;
+
+    // Content
+    private ContentType mContentType;
+    private ArrayList<ApplicationInfo> mApps;
+    private List<Object> mWidgets;
+    private List<ResolveInfo> mWallpapers;
+
+    // Caching
+    private Drawable mDefaultWidgetBackground;
+    private final int sWidgetPreviewCacheSize = 1 * 1024 * 1024; // 1 MiB
+    private LruCache<Object, Bitmap> mWidgetPreviewCache;
+    private IconCache mIconCache;
+
+    // Dimens
+    private int mContentWidth;
+    private int mMaxWidgetSpan, mMinWidgetSpan;
+    private int mCellWidthGap, mCellHeightGap;
+    private int mWidgetCountX, mWidgetCountY;
+    private int mWallpaperCountX, mWallpaperCountY;
+    private final int mWidgetPreviewIconPaddedDimension;
+    private final float sWidgetPreviewIconPaddingPercentage = 0.25f;
+    private PagedViewCellLayout mWidgetSpacingLayout;
+
+    // Animations
+    private final float ANIMATION_SCALE = 0.5f;
+    private final int TRANSLATE_ANIM_DURATION = 400;
+    private final int DROP_ANIM_DURATION = 200;
+
+    public AppsCustomizePagedView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mLayoutInflater = LayoutInflater.from(context);
+        mPackageManager = context.getPackageManager();
+        mContentType = ContentType.Applications;
+        mApps = new ArrayList<ApplicationInfo>();
+        mWidgets = new ArrayList<Object>();
+        mWallpapers = new ArrayList<ResolveInfo>();
+        mIconCache = ((LauncherApplication) context.getApplicationContext()).getIconCache();
+        mWidgetPreviewCache = new LruCache<Object, Bitmap>(sWidgetPreviewCacheSize) {
+            protected int sizeOf(Object key, Bitmap value) {
+                return value.getByteCount();
+            }
+        };
+
+        // Save the default widget preview background
+        Resources resources = context.getResources();
+        mDefaultWidgetBackground = resources.getDrawable(R.drawable.default_widget_preview);
+
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, 0, 0);
+        mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 6);
+        mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4);
+        a.recycle();
+        a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0);
+        mCellWidthGap =
+            a.getDimensionPixelSize(R.styleable.AppsCustomizePagedView_widgetCellWidthGap, 10);
+        mCellHeightGap =
+            a.getDimensionPixelSize(R.styleable.AppsCustomizePagedView_widgetCellHeightGap, 10);
+        mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2);
+        mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2);
+        mWallpaperCountX = a.getInt(R.styleable.AppsCustomizePagedView_wallpaperCountX, 2);
+        mWallpaperCountY = a.getInt(R.styleable.AppsCustomizePagedView_wallpaperCountY, 2);
+        a.recycle();
+
+        // Create a dummy page that we can use to approximate the cell dimensions of widgets and
+        // the content width (to be used by our parent)
+        mWidgetSpacingLayout = new PagedViewCellLayout(context);
+        setupPage(mWidgetSpacingLayout);
+        mContentWidth = mWidgetSpacingLayout.getContentWidth();
+
+        // The max widget span is the length N, such that NxN is the largest bounds that the widget
+        // preview can be before applying the widget scaling
+        mMinWidgetSpan = 1;
+        mMaxWidgetSpan = 3;
+
+        // The padding on the non-matched dimension for the default widget preview icons
+        // (top + bottom)
+        int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size);
+        mWidgetPreviewIconPaddedDimension =
+            (int) (iconSize * (1 + (2 * sWidgetPreviewIconPaddingPercentage)));
+    }
+
+    @Override
+    protected void init() {
+        super.init();
+        mCenterPagesVertically = false;
+
+        Context context = getContext();
+        Resources r = context.getResources();
+        setDragSlopeThreshold(r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold)/100f);
+    }
+
+    public void onPackagesUpdated() {
+        // Get the list of widgets and shortcuts
+        mWidgets.clear();
+        mWidgets.addAll(AppWidgetManager.getInstance(mLauncher).getInstalledProviders());
+        Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
+        mWidgets.addAll(mPackageManager.queryIntentActivities(shortcutsIntent, 0));
+        Collections.sort(mWidgets,
+                new LauncherModel.WidgetAndShortcutNameComparator(mPackageManager));
+
+        // Get the list of wallpapers
+        Intent wallpapersIntent = new Intent(Intent.ACTION_SET_WALLPAPER);
+        mWallpapers = mPackageManager.queryIntentActivities(wallpapersIntent,
+                PackageManager.GET_META_DATA);
+        Collections.sort(mWallpapers,
+                new LauncherModel.ShortcutNameComparator(mPackageManager));
+    }
+
+    /**
+     * Animates the given item onto the center of a home screen, and then scales the item to
+     * look as though it's disappearing onto that screen.
+     */
+    private void animateItemOntoScreen(View dragView,
+            final CellLayout layout, final ItemInfo info) {
+        // On the phone, we only want to fade the widget preview out
+        float[] position = new float[2];
+        position[0] = layout.getWidth() / 2;
+        position[1] = layout.getHeight() / 2;
+
+        mLauncher.getWorkspace().mapPointFromChildToSelf(layout, position);
+
+        int dragViewWidth = dragView.getMeasuredWidth();
+        int dragViewHeight = dragView.getMeasuredHeight();
+        float heightOffset = 0;
+        float widthOffset = 0;
+
+        if (dragView instanceof ImageView) {
+            Drawable d = ((ImageView) dragView).getDrawable();
+            int width = d.getIntrinsicWidth();
+            int height = d.getIntrinsicHeight();
+
+            if ((1.0 * width / height) >= (1.0f * dragViewWidth) / dragViewHeight) {
+                float f = (dragViewWidth / (width * 1.0f));
+                heightOffset = ANIMATION_SCALE * (dragViewHeight - f * height) / 2;
+            } else {
+                float f = (dragViewHeight / (height * 1.0f));
+                widthOffset = ANIMATION_SCALE * (dragViewWidth - f * width) / 2;
+            }
+        }
+        final float toX = position[0] - dragView.getMeasuredWidth() / 2 + widthOffset;
+        final float toY = position[1] - dragView.getMeasuredHeight() / 2 + heightOffset;
+
+        final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+        final View dragCopy = dragLayer.createDragView(dragView);
+        dragCopy.setAlpha(1.0f);
+
+        // Translate the item to the center of the appropriate home screen
+        animateIntoPosition(dragCopy, toX, toY, null);
+
+        // The drop-onto-screen animation begins a bit later, but ends at the same time.
+        final int startDelay = TRANSLATE_ANIM_DURATION - DROP_ANIM_DURATION;
+
+        // Scale down the icon and fade out the alpha
+        animateDropOntoScreen(dragCopy, info, DROP_ANIM_DURATION, startDelay);
+    }
+
+    /**
+     * Animation which scales the view down and animates its alpha, making it appear to disappear
+     * onto a home screen.
+     */
+    private void animateDropOntoScreen(
+            final View view, final ItemInfo info, int duration, int delay) {
+        final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+        final CellLayout layout = mLauncher.getWorkspace().getCurrentDropLayout();
+
+        ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(view,
+                PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.0f),
+                PropertyValuesHolder.ofFloat("scaleX", ANIMATION_SCALE),
+                PropertyValuesHolder.ofFloat("scaleY", ANIMATION_SCALE));
+        anim.setInterpolator(new LinearInterpolator());
+        if (delay > 0) {
+            anim.setStartDelay(delay);
+        }
+        anim.setDuration(duration);
+        anim.addListener(new AnimatorListenerAdapter() {
+            public void onAnimationEnd(Animator animation) {
+                dragLayer.removeView(view);
+                mLauncher.addExternalItemToScreen(info, layout);
+                info.dropPos = null;
+            }
+        });
+        anim.start();
+    }
+
+    /**
+     * Animates the x,y position of the view, and optionally execute a Runnable on animation end.
+     */
+    private void animateIntoPosition(
+            View view, float toX, float toY, final Runnable endRunnable) {
+        ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(view,
+                PropertyValuesHolder.ofFloat("x", toX),
+                PropertyValuesHolder.ofFloat("y", toY));
+        anim.setInterpolator(new DecelerateInterpolator(2.5f));
+        anim.setDuration(TRANSLATE_ANIM_DURATION);
+        if (endRunnable != null) {
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    endRunnable.run();
+                }
+            });
+        }
+        anim.start();
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v instanceof PagedViewIcon) {
+            // Animate some feedback to the click
+            final ApplicationInfo appInfo = (ApplicationInfo) v.getTag();
+            animateClickFeedback(v, new Runnable() {
+                @Override
+                public void run() {
+                    mLauncher.startActivitySafely(appInfo.intent, appInfo);
+                }
+            });
+        } else if (v instanceof PagedViewWidget) {
+            final ResolveInfo info = (ResolveInfo) v.getTag();
+            if (mWallpapers.contains(info)) {
+                // Start the wallpaper picker
+                animateClickFeedback(v, new Runnable() {
+                    @Override
+                    public void run() {
+                        // add the shortcut
+                        Intent createWallpapersIntent = new Intent(Intent.ACTION_SET_WALLPAPER);
+                        ComponentName name = new ComponentName(info.activityInfo.packageName,
+                                info.activityInfo.name);
+                        createWallpapersIntent.setComponent(name);
+                        mLauncher.processWallpaper(createWallpapersIntent);
+                    }
+                });
+            } else {
+                // Add the widget to the current workspace screen
+                Workspace w = mLauncher.getWorkspace();
+                int currentWorkspaceScreen = mLauncher.getCurrentWorkspaceScreen();
+                final CellLayout cl = (CellLayout) w.getChildAt(currentWorkspaceScreen);
+                final View dragView = v.findViewById(R.id.widget_preview);
+                final ItemInfo itemInfo = (ItemInfo) v.getTag();
+                animateClickFeedback(v, new Runnable() {
+                    @Override
+                    public void run() {
+                        cl.calculateSpans(itemInfo);
+                        if (cl.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY)) {
+                            if (LauncherApplication.isScreenLarge()) {
+                                animateItemOntoScreen(dragView, cl, itemInfo);
+                            } else {
+                                mLauncher.addExternalItemToScreen(itemInfo, cl);
+                                itemInfo.dropPos = null;
+                            }
+
+                            // Hide the pane so we can see the workspace we dropped on
+                            mLauncher.showWorkspace(true);
+                        } else {
+                            mLauncher.showOutOfSpaceMessage();
+                        }
+                    }
+                });
+            }
+        }
+    }
+
+    /*
+     * PagedViewWithDraggableItems implementation
+     */
+    @Override
+    protected void determineDraggingStart(android.view.MotionEvent ev) {
+        // Disable dragging by pulling an app down for now.
+    }
+    private void beginDraggingApplication(View v) {
+        // Make a copy of the ApplicationInfo
+        ApplicationInfo appInfo = new ApplicationInfo((ApplicationInfo) v.getTag());
+
+        // Show the uninstall button if the app is uninstallable.
+        if ((appInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
+            DeleteZone allAppsDeleteZone = (DeleteZone)
+                    mLauncher.findViewById(R.id.all_apps_delete_zone);
+            allAppsDeleteZone.setDragAndDropEnabled(true);
+
+            if ((appInfo.flags & ApplicationInfo.UPDATED_SYSTEM_APP_FLAG) != 0) {
+                allAppsDeleteZone.setText(R.string.delete_zone_label_all_apps_system_app);
+            } else {
+                allAppsDeleteZone.setText(R.string.delete_zone_label_all_apps);
+            }
+        }
+
+        // Show the info button
+        ApplicationInfoDropTarget allAppsInfoButton =
+            (ApplicationInfoDropTarget) mLauncher.findViewById(R.id.all_apps_info_target);
+        allAppsInfoButton.setDragAndDropEnabled(true);
+
+        // Compose the drag image (top compound drawable, index is 1)
+        final TextView tv = (TextView) v;
+        final Drawable icon = tv.getCompoundDrawables()[1];
+        Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(),
+                Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas(b);
+        c.translate((v.getWidth() - icon.getIntrinsicWidth()) / 2, v.getPaddingTop());
+        icon.draw(c);
+
+        // Compose the visible rect of the drag image
+        Rect dragRect = null;
+        if (v instanceof TextView) {
+            int iconSize = getResources().getDimensionPixelSize(R.dimen.app_icon_size);
+            int top = v.getPaddingTop();
+            int left = (b.getWidth() - iconSize) / 2;
+            int right = left + iconSize;
+            int bottom = top + iconSize;
+            dragRect = new Rect(left, top, right, bottom);
+        }
+
+        // Start the drag
+        mLauncher.lockScreenOrientation();
+        mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
+        mDragController.startDrag(v, b, this, appInfo, DragController.DRAG_ACTION_COPY, dragRect);
+        b.recycle();
+    }
+    private void beginDraggingWidget(View v) {
+        // Get the widget preview as the drag representation
+        ImageView image = (ImageView) v.findViewById(R.id.widget_preview);
+        PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
+
+        // Compose the drag image
+        Bitmap b;
+        Drawable preview = image.getDrawable();
+        int w = preview.getIntrinsicWidth();
+        int h = preview.getIntrinsicHeight();
+        if (createItemInfo instanceof PendingAddWidgetInfo) {
+            PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) createItemInfo;
+            int[] spanXY = CellLayout.rectToCell(getResources(),
+                    createWidgetInfo.minWidth, createWidgetInfo.minHeight, null);
+            createItemInfo.spanX = spanXY[0];
+            createItemInfo.spanY = spanXY[1];
+
+            b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+            renderDrawableToBitmap(preview, b, 0, 0, w, h, 1, 1);
+        } else {
+            // Workaround for the fact that we don't keep the original ResolveInfo associated with
+            // the shortcut around.  To get the icon, we just render the preview image (which has
+            // the shortcut icon) to a new drag bitmap that clips the non-icon space.
+            b = Bitmap.createBitmap(mWidgetPreviewIconPaddedDimension,
+                    mWidgetPreviewIconPaddedDimension, Bitmap.Config.ARGB_8888);
+            Canvas c = new Canvas(b);
+            preview.draw(c);
+            createItemInfo.spanX = createItemInfo.spanY = 1;
+        }
+
+        // Start the drag
+        mLauncher.lockScreenOrientation();
+        mLauncher.getWorkspace().onDragStartedWithItemSpans(createItemInfo.spanX,
+                createItemInfo.spanY, b);
+        mDragController.startDrag(image, b, this, createItemInfo,
+                DragController.DRAG_ACTION_COPY, null);
+        b.recycle();
+    }
+    @Override
+    protected boolean beginDragging(View v) {
+        if (!super.beginDragging(v)) return false;
+
+        // Hide the pane so that the user can drop onto the workspace, we must do this first,
+        // due to how the drop target layout is computed when we start dragging to the workspace.
+        mLauncher.showWorkspace(true);
+
+        if (v instanceof PagedViewIcon) {
+            beginDraggingApplication(v);
+        } else if (v instanceof PagedViewWidget) {
+            beginDraggingWidget(v);
+        }
+
+        return true;
+    }
+    private void endDragging(boolean success) {
+        post(new Runnable() {
+            // Once the drag operation has fully completed, hence the post, we want to disable the
+            // deleteZone and the appInfoButton in all apps, and re-enable the instance which
+            // live in the workspace
+            public void run() {
+                // if onDestroy was called on Launcher, we might have already deleted the
+                // all apps delete zone / info button, so check if they are null
+                DeleteZone allAppsDeleteZone =
+                        (DeleteZone) mLauncher.findViewById(R.id.all_apps_delete_zone);
+                ApplicationInfoDropTarget allAppsInfoButton =
+                    (ApplicationInfoDropTarget) mLauncher.findViewById(R.id.all_apps_info_target);
+
+                if (allAppsDeleteZone != null) allAppsDeleteZone.setDragAndDropEnabled(false);
+                if (allAppsInfoButton != null) allAppsInfoButton.setDragAndDropEnabled(false);
+            }
+        });
+        mLauncher.getWorkspace().onDragStopped(success);
+        mLauncher.unlockScreenOrientation();
+    }
+
+    /*
+     * DragSource implementation
+     */
+    @Override
+    public void onDragViewVisible() {}
+    @Override
+    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+        endDragging(success);
+
+        // Display an error message if the drag failed due to there not being enough space on the
+        // target layout we were dropping on.
+        if (!success) {
+            boolean showOutOfSpaceMessage = false;
+            if (target instanceof Workspace) {
+                int currentScreen = mLauncher.getCurrentWorkspaceScreen();
+                Workspace workspace = (Workspace) target;
+                CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen);
+                ItemInfo itemInfo = (ItemInfo) dragInfo;
+                if (layout != null) {
+                    layout.calculateSpans(itemInfo);
+                    showOutOfSpaceMessage =
+                            !layout.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY);
+                }
+            }
+            // TODO-APPS_CUSTOMIZE: We need to handle this for folders as well later.
+            if (showOutOfSpaceMessage) {
+                mLauncher.showOutOfSpaceMessage();
+            }
+        }
+    }
+
+    public void setContentType(ContentType type) {
+        mContentType = type;
+        setCurrentPage(0);
+        invalidatePageData();
+    }
+
+    /*
+     * Apps PagedView implementation
+     */
+    private void setVisibilityOnChildren(ViewGroup layout, int visibility) {
+        int childCount = layout.getChildCount();
+        for (int i = 0; i < childCount; ++i) {
+            layout.getChildAt(i).setVisibility(visibility);
+        }
+    }
+    private void setupPage(PagedViewCellLayout layout) {
+        layout.setCellCount(mCellCountX, mCellCountY);
+        layout.setGap(mPageLayoutWidthGap, mPageLayoutHeightGap);
+        layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
+                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
+
+        // Note: We force a measure here to get around the fact that when we do layout calculations
+        // immediately after syncing, we don't have a proper width.  That said, we already know the
+        // expected page width, so we can actually optimize by hiding all the TextView-based
+        // children that are expensive to measure, and let that happen naturally later.
+        setVisibilityOnChildren(layout, View.GONE);
+        int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
+        int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
+        layout.setMinimumWidth(getPageContentWidth());
+        layout.measure(widthSpec, heightSpec);
+        setVisibilityOnChildren(layout, View.VISIBLE);
+    }
+    public void syncAppsPages() {
+        // Ensure that we have the right number of pages
+        Context context = getContext();
+        int numPages = (int) Math.ceil((float) mApps.size() / (mCellCountX * mCellCountY));
+        for (int i = 0; i < numPages; ++i) {
+            PagedViewCellLayout layout = new PagedViewCellLayout(context);
+            setupPage(layout);
+            addView(layout);
+        }
+    }
+    public void syncAppsPageItems(int page) {
+        // ensure that we have the right number of items on the pages
+        int numPages = getPageCount();
+        int numCells = mCellCountX * mCellCountY;
+        int startIndex = page * numCells;
+        int endIndex = Math.min(startIndex + numCells, mApps.size());
+        PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page);
+        layout.removeAllViewsOnPage();
+        for (int i = startIndex; i < endIndex; ++i) {
+            ApplicationInfo info = mApps.get(i);
+            PagedViewIcon icon = (PagedViewIcon) mLayoutInflater.inflate(
+                    R.layout.apps_customize_application, layout, false);
+            icon.applyFromApplicationInfo(
+                    info, mPageViewIconCache, true, isHardwareAccelerated() && (numPages > 1));
+            icon.setOnClickListener(this);
+            icon.setOnLongClickListener(this);
+            icon.setOnTouchListener(this);
+
+            int index = i - startIndex;
+            int x = index % mCellCountX;
+            int y = index / mCellCountX;
+            layout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x,y, 1,1));
+        }
+    }
+    /*
+     * Widgets PagedView implementation
+     */
+    private void setupPage(PagedViewGridLayout layout) {
+        layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
+                mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
+
+        // Note: We force a measure here to get around the fact that when we do layout calculations
+        // immediately after syncing, we don't have a proper width.  That said, we already know the
+        // expected page width, so we can actually optimize by hiding all the TextView-based
+        // children that are expensive to measure, and let that happen naturally later.
+        setVisibilityOnChildren(layout, View.GONE);
+        int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
+        int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
+        layout.setMinimumWidth(getPageContentWidth());
+        layout.measure(widthSpec, heightSpec);
+        setVisibilityOnChildren(layout, View.VISIBLE);
+    }
+    private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h,
+            float scaleX, float scaleY) {
+        Canvas c = new Canvas();
+        if (bitmap != null) c.setBitmap(bitmap);
+        c.save();
+        c.scale(scaleX, scaleY);
+        Rect oldBounds = d.copyBounds();
+        d.setBounds(x, y, x + w, y + h);
+        d.draw(c);
+        d.setBounds(oldBounds); // Restore the bounds
+        c.restore();
+    }
+    private FastBitmapDrawable getShortcutPreview(ResolveInfo info, int cellWidth, int cellHeight) {
+        // Return the cached version if necessary
+        Bitmap cachedBitmap = mWidgetPreviewCache.get(info);
+        if (cachedBitmap != null) {
+            return new FastBitmapDrawable(cachedBitmap);
+        }
+
+        Resources resources = mLauncher.getResources();
+        int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size);
+        // We only need to make it wide enough so as not allow the preview to be scaled
+        int expectedWidth = cellWidth;
+        int expectedHeight = mWidgetPreviewIconPaddedDimension;
+        int offset = (int) (iconSize * sWidgetPreviewIconPaddingPercentage);
+
+        // Render the icon
+        Bitmap preview = Bitmap.createBitmap(expectedWidth, expectedHeight, Config.ARGB_8888);
+        Drawable icon = mIconCache.getFullResIcon(info, mPackageManager);
+        renderDrawableToBitmap(mDefaultWidgetBackground, preview, 0, 0,
+                mWidgetPreviewIconPaddedDimension, mWidgetPreviewIconPaddedDimension, 1f, 1f);
+        renderDrawableToBitmap(icon, preview, offset, offset, iconSize, iconSize, 1f, 1f);
+        FastBitmapDrawable iconDrawable = new FastBitmapDrawable(preview);
+        iconDrawable.setBounds(0, 0, expectedWidth, expectedHeight);
+        mWidgetPreviewCache.put(info, preview);
+        return iconDrawable;
+    }
+    private FastBitmapDrawable getWidgetPreview(AppWidgetProviderInfo info, int cellHSpan,
+            int cellVSpan, int cellWidth, int cellHeight) {
+        // Return the cached version if necessary
+        Bitmap cachedBitmap = mWidgetPreviewCache.get(info);
+        if (cachedBitmap != null) {
+            return new FastBitmapDrawable(cachedBitmap);
+        }
+
+        // Calculate the size of the drawable
+        cellHSpan = Math.max(mMinWidgetSpan, Math.min(mMaxWidgetSpan, cellHSpan));
+        cellVSpan = Math.max(mMinWidgetSpan, Math.min(mMaxWidgetSpan, cellVSpan));
+        int expectedWidth = mWidgetSpacingLayout.estimateCellWidth(cellHSpan);
+        int expectedHeight = mWidgetSpacingLayout.estimateCellHeight(cellVSpan);
+
+        // Scale down the bitmap to fit the space
+        float widgetPreviewScale = (float) cellWidth / expectedWidth;
+        expectedWidth = (int) (widgetPreviewScale * expectedWidth);
+        expectedHeight = (int) (widgetPreviewScale * expectedHeight);
+
+        // Load the preview image if possible
+        String packageName = info.provider.getPackageName();
+        Drawable drawable = null;
+        FastBitmapDrawable newDrawable = null;
+        if (info.previewImage != 0) {
+            drawable = mPackageManager.getDrawable(packageName, info.previewImage, null);
+            if (drawable == null) {
+                Log.w(LOG_TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon)
+                        + " for provider: " + info.provider);
+            } else {
+                // Scale down the preview to the dimensions we want
+                int imageWidth = drawable.getIntrinsicWidth();
+                int imageHeight = drawable.getIntrinsicHeight();
+                float aspect = (float) imageWidth / imageHeight;
+                int newWidth = imageWidth;
+                int newHeight = imageHeight;
+                if (aspect > 1f) {
+                    newWidth = expectedWidth;
+                    newHeight = (int) (imageHeight * ((float) expectedWidth / imageWidth));
+                } else {
+                    newHeight = expectedHeight;
+                    newWidth = (int) (imageWidth * ((float) expectedHeight / imageHeight));
+                }
+
+                Bitmap preview = Bitmap.createBitmap(newWidth, newHeight, Config.ARGB_8888);
+                renderDrawableToBitmap(drawable, preview, 0, 0, newWidth, newHeight, 1f, 1f);
+                newDrawable = new FastBitmapDrawable(preview);
+                newDrawable.setBounds(0, 0, newWidth, newHeight);
+                mWidgetPreviewCache.put(info, preview);
+            }
+        }
+
+        // Generate a preview image if we couldn't load one
+        if (drawable == null) {
+            Resources resources = mLauncher.getResources();
+            int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size);
+
+            // Specify the dimensions of the bitmap
+            if (info.minWidth >= info.minHeight) {
+                expectedWidth = cellWidth;
+                expectedHeight = mWidgetPreviewIconPaddedDimension;
+            } else {
+                // Note that in vertical widgets, we might not have enough space due to the text
+                // label, so be conservative and use the width as a height bound
+                expectedWidth = mWidgetPreviewIconPaddedDimension;
+                expectedHeight = cellWidth;
+            }
+
+            Bitmap preview = Bitmap.createBitmap(expectedWidth, expectedHeight, Config.ARGB_8888);
+            renderDrawableToBitmap(mDefaultWidgetBackground, preview, 0, 0, expectedWidth,
+                    expectedHeight, 1f,1f);
+
+            // Draw the icon in the top left corner
+            try {
+                Drawable icon = null;
+                if (info.icon > 0) icon = mPackageManager.getDrawable(packageName, info.icon, null);
+                if (icon == null) icon = resources.getDrawable(R.drawable.ic_launcher_application);
+
+                int offset = (int) (iconSize * sWidgetPreviewIconPaddingPercentage);
+                renderDrawableToBitmap(icon, preview, offset, offset, iconSize, iconSize, 1f, 1f);
+            } catch (Resources.NotFoundException e) {}
+
+            newDrawable = new FastBitmapDrawable(preview);
+            newDrawable.setBounds(0, 0, expectedWidth, expectedHeight);
+            mWidgetPreviewCache.put(info, preview);
+        }
+        return newDrawable;
+    }
+    public void syncWidgetPages() {
+        // Ensure that we have the right number of pages
+        Context context = getContext();
+        int numWidgetsPerPage = mWidgetCountX * mWidgetCountY;
+        int numPages = (int) Math.ceil(mWidgets.size() / (float) numWidgetsPerPage);
+        for (int i = 0; i < numPages; ++i) {
+            PagedViewGridLayout layout = new PagedViewGridLayout(context, mWidgetCountX,
+                    mWidgetCountY);
+            setupPage(layout);
+            addView(layout);
+        }
+    }
+    public void syncWidgetPageItems(int page) {
+        PagedViewGridLayout layout = (PagedViewGridLayout) getChildAt(page);
+        layout.removeAllViews();
+
+        // Calculate the dimensions of each cell we are giving to each widget
+        int numWidgetsPerPage = mWidgetCountX * mWidgetCountY;
+        int offset = page * numWidgetsPerPage;
+        int cellWidth = ((mWidgetSpacingLayout.getContentWidth() - mPageLayoutWidthGap
+                - ((mWidgetCountX - 1) * mCellWidthGap)) / mWidgetCountX);
+        int cellHeight = ((mWidgetSpacingLayout.getContentHeight() - mPageLayoutHeightGap
+                - ((mWidgetCountY - 1) * mCellHeightGap)) / mWidgetCountY);
+        for (int i = 0; i < Math.min(numWidgetsPerPage, mWidgets.size() - offset); ++i) {
+            Object rawInfo = mWidgets.get(offset + i);
+            PendingAddItemInfo createItemInfo = null;
+            PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate(
+                    R.layout.apps_customize_widget, layout, false);
+            if (rawInfo instanceof AppWidgetProviderInfo) {
+                // Fill in the widget information
+                AppWidgetProviderInfo info = (AppWidgetProviderInfo) rawInfo;
+                createItemInfo = new PendingAddWidgetInfo(info, null, null);
+                final int[] cellSpans = CellLayout.rectToCell(getResources(), info.minWidth,
+                        info.minHeight, null);
+                FastBitmapDrawable preview = getWidgetPreview(info, cellSpans[0], cellSpans[1],
+                        cellWidth, cellHeight);
+                widget.applyFromAppWidgetProviderInfo(info, preview, -1, cellSpans, null, false);
+                widget.setTag(createItemInfo);
+            } else if (rawInfo instanceof ResolveInfo) {
+                // Fill in the shortcuts information
+                ResolveInfo info = (ResolveInfo) rawInfo;
+                createItemInfo = new PendingAddItemInfo();
+                createItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+                createItemInfo.componentName = new ComponentName(info.activityInfo.packageName,
+                        info.activityInfo.name);
+                FastBitmapDrawable preview = getShortcutPreview(info, cellWidth, cellHeight);
+                widget.applyFromResolveInfo(mPackageManager, info, preview, null, false);
+                widget.setTag(createItemInfo);
+            }
+            widget.setOnClickListener(this);
+            widget.setOnLongClickListener(this);
+            widget.setOnTouchListener(this);
+
+            // Layout each widget
+            int ix = i % mWidgetCountX;
+            int iy = i / mWidgetCountX;
+            PagedViewGridLayout.LayoutParams lp = new PagedViewGridLayout.LayoutParams(cellWidth,
+                    cellHeight);
+            lp.leftMargin = (ix * cellWidth) + (ix * mCellWidthGap);
+            lp.topMargin = (iy * cellHeight) + (iy * mCellHeightGap);
+            layout.addView(widget, lp);
+        }
+    }
+
+    /*
+     * This method fetches an xml file specified in the manifest identified by
+     * WallpaperManager.WALLPAPER_PREVIEW_META_DATA). The xml file specifies
+     * an image which will be used as the wallpaper preview for an activity
+     * which responds to ACTION_SET_WALLPAPER. This image is returned and used
+     * in the customize drawer.
+     */
+    private Drawable parseWallpaperPreviewXml(ResolveInfo ri) {
+        ActivityInfo activityInfo = ri.activityInfo;
+        XmlResourceParser parser = null;
+        ComponentName component = new ComponentName(ri.activityInfo.packageName,
+                ri.activityInfo.name);
+        try {
+            parser = activityInfo.loadXmlMetaData(mPackageManager,
+                    WallpaperManager.WALLPAPER_PREVIEW_META_DATA);
+            if (parser == null) {
+                Slog.w(LOG_TAG, "No " + WallpaperManager.WALLPAPER_PREVIEW_META_DATA
+                        + " meta-data for " + "wallpaper provider '" + component + '\'');
+                return null;
+            }
+
+            AttributeSet attrs = Xml.asAttributeSet(parser);
+
+            int type;
+            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+                    && type != XmlPullParser.START_TAG) {
+                // drain whitespace, comments, etc.
+            }
+
+            String nodeName = parser.getName();
+            if (!"wallpaper-preview".equals(nodeName)) {
+                Slog.w(LOG_TAG, "Meta-data does not start with wallpaper-preview tag for "
+                        + "wallpaper provider '" + component + '\'');
+                return null;
+            }
+
+            // If metaData was null, we would have returned earlier when getting
+            // the parser No need to do the check here
+            Resources res = mPackageManager.getResourcesForApplication(
+                    activityInfo.applicationInfo);
+
+            TypedArray sa = res.obtainAttributes(attrs,
+                    com.android.internal.R.styleable.WallpaperPreviewInfo);
+
+            TypedValue value = sa.peekValue(
+                    com.android.internal.R.styleable.WallpaperPreviewInfo_staticWallpaperPreview);
+            if (value == null) return null;
+
+            return res.getDrawable(value.resourceId);
+        } catch (Exception e) {
+            Slog.w(LOG_TAG, "XML parsing failed for wallpaper provider '" + component + '\'', e);
+            return null;
+        } finally {
+            if (parser != null) parser.close();
+        }
+    }
+    private FastBitmapDrawable getWallpaperPreview(ResolveInfo info, int cellWidth, int cellHeight){
+        // Return the cached version if necessary
+        Bitmap cachedBitmap = mWidgetPreviewCache.get(info);
+        if (cachedBitmap != null) {
+            return new FastBitmapDrawable(cachedBitmap);
+        }
+
+        // Get the preview
+        Resources resources = getContext().getResources();
+        Drawable wallpaperPreview = parseWallpaperPreviewXml(info);
+        Drawable wallpaperIcon = null;
+        int expectedWidth;
+        int expectedHeight;
+        if (wallpaperPreview != null) {
+            expectedWidth = wallpaperPreview.getIntrinsicWidth();
+            expectedHeight = wallpaperPreview.getIntrinsicHeight();
+        } else {
+            wallpaperPreview = mDefaultWidgetBackground;
+            expectedWidth = expectedHeight = Math.min(cellWidth, cellHeight);
+
+            // Draw the icon in the top left corner
+            String packageName = info.activityInfo.packageName;
+            try {
+                if (info.icon > 0) {
+                    wallpaperIcon = mPackageManager.getDrawable(packageName, info.icon, null);
+                }
+                if (wallpaperIcon == null) {
+                    wallpaperIcon = resources.getDrawable(R.drawable.ic_launcher_application);
+                }
+            } catch (Resources.NotFoundException e) {}
+        }
+
+        // Create the bitmap
+        Bitmap preview = Bitmap.createBitmap(expectedWidth, expectedHeight, Config.ARGB_8888);
+        renderDrawableToBitmap(wallpaperPreview, preview, 0, 0, expectedWidth, expectedHeight,
+                1f, 1f);
+        if (wallpaperIcon != null) {
+            int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size);
+            int offset = (int) (iconSize * sWidgetPreviewIconPaddingPercentage);
+            renderDrawableToBitmap(wallpaperIcon, preview, offset, offset, iconSize, iconSize,
+                    1f, 1f);
+        }
+
+        FastBitmapDrawable previewDrawable = new FastBitmapDrawable(preview);
+        previewDrawable.setBounds(0, 0, expectedWidth, expectedHeight);
+        mWidgetPreviewCache.put(info, preview);
+        return previewDrawable;
+    }
+    /*
+     * Wallpapers PagedView implementation
+     */
+    public void syncWallpaperPages() {
+        // Ensure that we have the right number of pages
+        Context context = getContext();
+        int numWidgetsPerPage = mWallpaperCountX * mWallpaperCountY;
+        int numPages = (int) Math.ceil(mWallpapers.size() / (float) numWidgetsPerPage);
+        for (int i = 0; i < numPages; ++i) {
+            PagedViewGridLayout layout = new PagedViewGridLayout(context, mWallpaperCountX,
+                    mWallpaperCountY);
+            setupPage(layout);
+            addView(layout);
+        }
+    }
+    public void syncWallpaperPageItems(int page) {
+        PagedViewGridLayout layout = (PagedViewGridLayout) getChildAt(page);
+        layout.removeAllViews();
+
+        // Calculate the dimensions of each cell we are giving to each widget
+        int numWidgetsPerPage = mWallpaperCountX * mWallpaperCountY;
+        int offset = page * numWidgetsPerPage;
+        int cellWidth = ((mWidgetSpacingLayout.getContentWidth() - mPageLayoutWidthGap
+                - ((mWallpaperCountX - 1) * mCellWidthGap)) / mWallpaperCountX);
+        int cellHeight = ((mWidgetSpacingLayout.getContentHeight() - mPageLayoutHeightGap
+                - ((mWallpaperCountY - 1) * mCellHeightGap)) / mWallpaperCountY);
+        for (int i = 0; i < Math.min(numWidgetsPerPage, mWallpapers.size() - offset); ++i) {
+            ResolveInfo info = mWallpapers.get(offset + i);
+            PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate(
+                    R.layout.apps_customize_wallpaper, layout, false);
+
+            // Fill in the shortcuts information
+            FastBitmapDrawable preview = getWallpaperPreview(info, cellWidth, cellHeight);
+            widget.applyFromResolveInfo(mPackageManager, info, preview, null, false);
+            widget.setTag(info);
+            widget.setOnClickListener(this);
+            widget.setOnLongClickListener(this);
+            widget.setOnTouchListener(this);
+
+            // Layout each widget
+            int ix = i % mWallpaperCountX;
+            int iy = i / mWallpaperCountX;
+            PagedViewGridLayout.LayoutParams lp = new PagedViewGridLayout.LayoutParams(cellWidth,
+                    cellHeight);
+            lp.leftMargin = (ix * cellWidth) + (ix * mCellWidthGap);
+            lp.topMargin = (iy * cellHeight) + (iy * mCellHeightGap);
+            layout.addView(widget, lp);
+        }
+    }
+
+    @Override
+    public void syncPages() {
+        removeAllViews();
+        switch (mContentType) {
+        case Applications:
+            syncAppsPages();
+            break;
+        case Widgets:
+            syncWidgetPages();
+            break;
+        case Wallpapers:
+            syncWallpaperPages();
+            break;
+        }
+    }
+    @Override
+    public void syncPageItems(int page) {
+        switch (mContentType) {
+        case Applications:
+            syncAppsPageItems(page);
+            break;
+        case Widgets:
+            syncWidgetPageItems(page);
+            break;
+        case Wallpapers:
+            syncWallpaperPageItems(page);
+            break;
+        }
+    }
+
+    /**
+     * Used by the parent to get the content width to set the tab bar to
+     * @return
+     */
+    public int getPageContentWidth() {
+        return mContentWidth;
+    }
+
+    /*
+     * AllAppsView implementation
+     */
+    @Override
+    public void setup(Launcher launcher, DragController dragController) {
+        mLauncher = launcher;
+        mDragController = dragController;
+    }
+    @Override
+    public void zoom(float zoom, boolean animate) {
+        // TODO-APPS_CUSTOMIZE: Call back to mLauncher.zoomed()
+    }
+    @Override
+    public boolean isVisible() {
+        return (getVisibility() == VISIBLE);
+    }
+    @Override
+    public boolean isAnimating() {
+        return false;
+    }
+    @Override
+    public void setApps(ArrayList<ApplicationInfo> list) {
+        mApps = list;
+        Collections.sort(mApps, LauncherModel.APP_NAME_COMPARATOR);
+        invalidatePageData();
+    }
+    private void addAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
+        // We add it in place, in alphabetical order
+        int count = list.size();
+        for (int i = 0; i < count; ++i) {
+            ApplicationInfo info = list.get(i);
+            int index = Collections.binarySearch(mApps, info, LauncherModel.APP_NAME_COMPARATOR);
+            if (index < 0) {
+                mApps.add(-(index + 1), info);
+            }
+        }
+    }
+    @Override
+    public void addApps(ArrayList<ApplicationInfo> list) {
+        addAppsWithoutInvalidate(list);
+        invalidatePageData();
+    }
+    private int findAppByComponent(List<ApplicationInfo> list, ApplicationInfo item) {
+        ComponentName removeComponent = item.intent.getComponent();
+        int length = list.size();
+        for (int i = 0; i < length; ++i) {
+            ApplicationInfo info = list.get(i);
+            if (info.intent.getComponent().equals(removeComponent)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+    private void removeAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
+        // loop through all the apps and remove apps that have the same component
+        int length = list.size();
+        for (int i = 0; i < length; ++i) {
+            ApplicationInfo info = list.get(i);
+            int removeIndex = findAppByComponent(mApps, info);
+            if (removeIndex > -1) {
+                mApps.remove(removeIndex);
+                mPageViewIconCache.removeOutline(new PagedViewIconCache.Key(info));
+            }
+        }
+    }
+    @Override
+    public void removeApps(ArrayList<ApplicationInfo> list) {
+        removeAppsWithoutInvalidate(list);
+        invalidatePageData();
+    }
+    @Override
+    public void updateApps(ArrayList<ApplicationInfo> list) {
+        // We remove and re-add the updated applications list because it's properties may have
+        // changed (ie. the title), and this will ensure that the items will be in their proper
+        // place in the list.
+        removeAppsWithoutInvalidate(list);
+        addAppsWithoutInvalidate(list);
+        invalidatePageData();
+    }
+    @Override
+    public void reset() {
+        if (mContentType != ContentType.Applications) {
+            // Reset to the first page of the Apps pane
+            AppsCustomizeTabHost tabs = (AppsCustomizeTabHost)
+                    mLauncher.findViewById(R.id.apps_customize_pane);
+            tabs.setCurrentTabByTag(tabs.getTabTagForContentType(ContentType.Applications));
+        } else {
+            setCurrentPage(0);
+            invalidatePageData();
+        }
+    }
+    @Override
+    public void dumpState() {
+        // TODO: Dump information related to current list of Applications, Widgets, etc.
+        ApplicationInfo.dumpApplicationInfoList(LOG_TAG, "mApps", mApps);
+        dumpAppWidgetProviderInfoList(LOG_TAG, "mWidgets", mWidgets);
+    }
+    private void dumpAppWidgetProviderInfoList(String tag, String label,
+            List<Object> list) {
+        Log.d(tag, label + " size=" + list.size());
+        for (Object i: list) {
+            if (i instanceof AppWidgetProviderInfo) {
+                AppWidgetProviderInfo info = (AppWidgetProviderInfo) i;
+                Log.d(tag, "   label=\"" + info.label + "\" previewImage=" + info.previewImage
+                        + " resizeMode=" + info.resizeMode + " configure=" + info.configure
+                        + " initialLayout=" + info.initialLayout
+                        + " minWidth=" + info.minWidth + " minHeight=" + info.minHeight);
+            } else if (i instanceof ResolveInfo) {
+                ResolveInfo info = (ResolveInfo) i;
+                Log.d(tag, "   label=\"" + info.loadLabel(mPackageManager) + "\" icon="
+                        + info.icon);
+            }
+        }
+    }
+    @Override
+    public void surrender() {
+        // TODO: If we are in the middle of any process (ie. for holographic outlines, etc) we
+        // should stop this now.
+    }
+}
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
new file mode 100644
index 0000000..e2d21b6
--- /dev/null
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TabHost;
+import android.widget.TextView;
+
+import com.android.launcher.R;
+
+public class AppsCustomizeTabHost extends TabHost implements LauncherTransitionable,
+        TabHost.OnTabChangeListener  {
+    static final String LOG_TAG = "AppsCustomizeTabHost";
+
+    private static final String APPS_TAB_TAG = "APPS";
+    private static final String WIDGETS_TAB_TAG = "WIDGETS";
+    private static final String WALLPAPERS_TAB_TAG = "WALLPAPERS";
+
+    private final LayoutInflater mLayoutInflater;
+
+    public AppsCustomizeTabHost(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mLayoutInflater = LayoutInflater.from(context);
+    }
+
+    /**
+     * Setup the tab host and create all necessary tabs.
+     */
+    @Override
+    protected void onFinishInflate() {
+        // Setup the tab host
+        setup();
+
+        final ViewGroup tabs = (ViewGroup) findViewById(com.android.internal.R.id.tabs);
+        final AppsCustomizePagedView content = (AppsCustomizePagedView)
+                findViewById(R.id.apps_customize_pane_content);
+        if (tabs == null || content == null) throw new Resources.NotFoundException();
+
+        // Configure the tabs content factory to return the same paged view (that we change the
+        // content filter on)
+        TabContentFactory contentFactory = new TabContentFactory() {
+            public View createTabContent(String tag) {
+                return content;
+            }
+        };
+
+        // Create the tabs
+        TextView tabView;
+        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
+        tabView.setText(mContext.getString(R.string.all_apps_button_label));
+        addTab(newTabSpec(APPS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
+        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
+        tabView.setText(mContext.getString(R.string.widgets_tab_label));
+        addTab(newTabSpec(WIDGETS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
+        tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false);
+        tabView.setText(mContext.getString(R.string.wallpapers_tab_label));
+        addTab(newTabSpec(WALLPAPERS_TAB_TAG).setIndicator(tabView).setContent(contentFactory));
+        setOnTabChangedListener(this);
+
+        // Set the width of the tab bar to match the content (for now)
+        tabs.getLayoutParams().width = content.getPageContentWidth();
+    }
+
+    @Override
+    public void onTabChanged(String tabId) {
+        final AppsCustomizePagedView content = (AppsCustomizePagedView)
+                findViewById(R.id.apps_customize_pane_content);
+        content.setContentType(getContentTypeForTabTag(tabId));
+    }
+
+    /**
+     * Returns the content type for the specified tab tag.
+     */
+    public AppsCustomizePagedView.ContentType getContentTypeForTabTag(String tag) {
+        if (tag.equals(APPS_TAB_TAG)) {
+            return AppsCustomizePagedView.ContentType.Applications;
+        } else if (tag.equals(WIDGETS_TAB_TAG)) {
+            return AppsCustomizePagedView.ContentType.Widgets;
+        } else if (tag.equals(WALLPAPERS_TAB_TAG)) {
+            return AppsCustomizePagedView.ContentType.Wallpapers;
+        }
+        return AppsCustomizePagedView.ContentType.Applications;
+    }
+
+    /**
+     * Returns the tab tag for a given content type.
+     */
+    public String getTabTagForContentType(AppsCustomizePagedView.ContentType type) {
+        if (type == AppsCustomizePagedView.ContentType.Applications) {
+            return APPS_TAB_TAG;
+        } else if (type == AppsCustomizePagedView.ContentType.Widgets) {
+            return WIDGETS_TAB_TAG;
+        } else if (type == AppsCustomizePagedView.ContentType.Wallpapers) {
+            return WALLPAPERS_TAB_TAG;
+        }
+        return APPS_TAB_TAG;
+    }
+
+    /**
+     * Disable focus on anything under this view in the hierarchy if we are not visible.
+     */
+    @Override
+    public int getDescendantFocusability() {
+        if (getVisibility() != View.VISIBLE) {
+            return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+        }
+        return super.getDescendantFocusability();
+    }
+
+    /* LauncherTransitionable overrides */
+    @Override
+    public void onLauncherTransitionStart(android.animation.Animator animation) {
+        // TODO-APPS_CUSTOMIZE: see AllAppsTabbed.onLauncherTransitionStart();
+    }
+    @Override
+    public void onLauncherTransitionEnd(android.animation.Animator animation) {
+        // TODO-APPS_CUSTOMIZE: see AllAppsTabbed.onLauncherTransitionEnd();
+    }
+}
diff --git a/src/com/android/launcher2/BubbleTextView.java b/src/com/android/launcher2/BubbleTextView.java
index ad01fac..703b3a8 100644
--- a/src/com/android/launcher2/BubbleTextView.java
+++ b/src/com/android/launcher2/BubbleTextView.java
@@ -29,6 +29,7 @@
 import android.graphics.Region.Op;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.TextView;
@@ -66,6 +67,8 @@
     private boolean mBackgroundSizeChanged;
     private Drawable mBackground;
 
+    private boolean mStayPressed;
+
     private VisibilityChangedListener mOnVisibilityChangedListener;
 
     public BubbleTextView(Context context) {
@@ -85,8 +88,6 @@
 
     private void init() {
         mBackground = getBackground();
-        setFocusable(true);
-        setBackgroundDrawable(null);
 
         final Resources res = getContext().getResources();
         int bubbleColor = res.getColor(R.color.bubble_dark_background);
@@ -130,21 +131,30 @@
             // In this case, we have already created the pressed outline on ACTION_DOWN,
             // so we just need to do an invalidate to trigger draw
             if (!mDidInvalidateForPressedState) {
-                invalidate();
+                setCellLayoutPressedOrFocusedIcon();
             }
         } else {
             // Otherwise, either clear the pressed/focused background, or create a background
             // for the focused state
             final boolean backgroundEmptyBefore = mPressedOrFocusedBackground == null;
-            mPressedOrFocusedBackground = null;
+            if (!mStayPressed) {
+                mPressedOrFocusedBackground = null;
+            }
             if (isFocused()) {
-                mPressedOrFocusedBackground = createGlowingOutline(
-                        mTempCanvas, mFocusedGlowColor, mFocusedOutlineColor);
-                invalidate();
+                if (mLayout == null) {
+                    // In some cases, we get focus before we have been layed out. Set the
+                    // background to null so that it will get created when the view is drawn.
+                    mPressedOrFocusedBackground = null;
+                } else {
+                    mPressedOrFocusedBackground = createGlowingOutline(
+                            mTempCanvas, mFocusedGlowColor, mFocusedOutlineColor);
+                }
+                mStayPressed = false;
+                setCellLayoutPressedOrFocusedIcon();
             }
             final boolean backgroundEmptyNow = mPressedOrFocusedBackground == null;
             if (!backgroundEmptyBefore && backgroundEmptyNow) {
-                invalidate();
+                setCellLayoutPressedOrFocusedIcon();
             }
         }
 
@@ -156,9 +166,8 @@
     }
 
     /**
-     * Draw the View v into the given Canvas.
+     * Draw this BubbleTextView into the given Canvas.
      *
-     * @param v the view to draw
      * @param destCanvas the canvas to draw on
      * @param padding the horizontal and vertical padding to use when drawing
      */
@@ -244,22 +253,32 @@
         super.onVisibilityChanged(changedView, visibility);
     }
 
+    void setStayPressed(boolean stayPressed) {
+        mStayPressed = stayPressed;
+        if (!stayPressed) {
+            mPressedOrFocusedBackground = null;
+        }
+        setCellLayoutPressedOrFocusedIcon();
+    }
+
+    void setCellLayoutPressedOrFocusedIcon() {
+        CellLayoutChildren parent = (CellLayoutChildren) getParent();
+        if (parent != null) {
+            CellLayout layout = (CellLayout) parent.getParent();
+            layout.setPressedOrFocusedIcon((mPressedOrFocusedBackground != null) ? this : null);
+        }
+    }
+
+    Bitmap getPressedOrFocusedBackground() {
+        return mPressedOrFocusedBackground;
+    }
+
+    int getPressedOrFocusedBackgroundPadding() {
+        return HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS / 2;
+    }
+
     @Override
     public void draw(Canvas canvas) {
-        if (mPressedOrFocusedBackground != null && (isPressed() || isFocused())) {
-            // The blue glow can extend outside of our clip region, so we first temporarily expand
-            // the canvas's clip region
-            canvas.save(Canvas.CLIP_SAVE_FLAG);
-            int padding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS / 2;
-            canvas.clipRect(-padding + mScrollX, -padding + mScrollY,
-                    getWidth() + padding + mScrollX, getHeight() + padding + mScrollY,
-                    Region.Op.REPLACE);
-            // draw blue glow
-            canvas.drawBitmap(mPressedOrFocusedBackground,
-                    mScrollX - padding, mScrollY - padding, mTempPaint);
-            canvas.restore();
-        }
-
         final Drawable background = mBackground;
         if (background != null) {
             final int scrollX = mScrollX;
@@ -310,4 +329,16 @@
         }
         return true;
     }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return FocusHelper.handleBubbleTextViewKeyEvent(this, keyCode, event)
+                || super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        return FocusHelper.handleBubbleTextViewKeyEvent(this, keyCode, event)
+                || super.onKeyUp(keyCode, event);
+    }
 }
diff --git a/src/com/android/launcher2/CachedTextView.java b/src/com/android/launcher2/CachedTextView.java
index 403d856..d0f6dd8 100644
--- a/src/com/android/launcher2/CachedTextView.java
+++ b/src/com/android/launcher2/CachedTextView.java
@@ -18,10 +18,11 @@
 
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
 import android.graphics.Canvas;
 import android.graphics.Paint;
-import android.graphics.Bitmap.Config;
 import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.Drawable;
 import android.text.Layout;
 import android.util.AttributeSet;
 import android.widget.TextView;
@@ -163,6 +164,16 @@
         if (mPrevAlpha != alpha) {
             mPrevAlpha = alpha;
             mCachePaint.setAlpha(alpha);
+
+            // We manually update the drawables alpha since the default TextView implementation may
+            // not do this if there is a background set (which we may due to the focus bg)
+            final Drawable[] dr = getCompoundDrawables();
+            for (int i = 0; i < dr.length; ++i) {
+                if (dr[i] != null) {
+                    dr[i].mutate().setAlpha(alpha);
+                }
+            }
+
             super.onSetAlpha(alpha);
         }
         return true;
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 6691e64..5f848a8 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher2;
 
-import com.android.launcher.R;
+import java.util.Arrays;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -39,7 +39,6 @@
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.ContextMenu;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewDebug;
@@ -48,7 +47,7 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.LayoutAnimationController;
 
-import java.util.Arrays;
+import com.android.launcher.R;
 
 public class CellLayout extends ViewGroup {
     static final String TAG = "CellLayout";
@@ -95,7 +94,7 @@
     private float mGlowBackgroundScale;
     private float mGlowBackgroundAlpha;
 
-    private boolean mAcceptsDrops = false;
+    private boolean mAcceptsDrops = true;
     // If we're actively dragging something over this screen, mIsDragOverlapping is true
     private boolean mIsDragOverlapping = false;
     private boolean mIsDragOccuring = false;
@@ -104,7 +103,7 @@
 
     // These arrays are used to implement the drag visualization on x-large screens.
     // They are used as circular arrays, indexed by mDragOutlineCurrent.
-    private Point[] mDragOutlines = new Point[8];
+    private Point[] mDragOutlines = new Point[4];
     private float[] mDragOutlineAlphas = new float[mDragOutlines.length];
     private InterruptibleInOutAnimator[] mDragOutlineAnims =
             new InterruptibleInOutAnimator[mDragOutlines.length];
@@ -113,6 +112,8 @@
     private int mDragOutlineCurrent = 0;
     private final Paint mDragOutlinePaint = new Paint();
 
+    private BubbleTextView mPressedOrFocusedIcon;
+
     private Drawable mCrosshairsDrawable = null;
     private InterruptibleInOutAnimator mCrosshairsAnimator = null;
     private float mCrosshairsVisibility = 0.0f;
@@ -166,7 +167,7 @@
 
         final Resources res = getResources();
 
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
             mNormalBackground = res.getDrawable(R.drawable.homescreen_large_blue);
             mActiveBackground = res.getDrawable(R.drawable.homescreen_large_green);
             mActiveGlowBackground = res.getDrawable(R.drawable.homescreen_large_green_strong);
@@ -262,11 +263,95 @@
         setHoverAlpha(1.0f);
 
         mChildren = new CellLayoutChildren(context);
-        mChildren.setCellDimensions(
-                mCellWidth, mCellHeight, mLeftPadding, mTopPadding, mWidthGap, mHeightGap);
+        mChildren.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap);
         addView(mChildren);
     }
 
+    static int widthInPortrait(Resources r, int numCells) {
+        // We use this method from Workspace to figure out how many rows/columns Launcher should
+        // have. We ignore the left/right padding on CellLayout because it turns out in our design
+        // the padding extends outside the visible screen size, but it looked fine anyway.
+        // However, we make sure there's at least enough space for the crosshairs at either
+        // edge to be rendered (half the crosshair is sticking out on either side)
+        int cellWidth = r.getDimensionPixelSize(R.dimen.workspace_cell_width);
+        int widthGap = r.getDimensionPixelSize(R.dimen.workspace_width_gap_port);
+        int crosshairsSize = r.getDrawable(R.drawable.gardening_crosshairs).getIntrinsicWidth();
+
+        return  widthGap * (numCells - 1) + cellWidth * numCells + crosshairsSize;
+    }
+
+    static int widthInLandscape(Resources r, int numCells) {
+        // We use this method from Workspace to figure out how many rows/columns Launcher should
+        // have. We ignore the left/right padding on CellLayout because it turns out in our design
+        // the padding extends outside the visible screen size, but it looked fine anyway.
+        // However, we make sure there's at least enough space for the crosshairs at either
+        // edge to be rendered (half the crosshair is sticking out on either side)
+        int cellWidth = r.getDimensionPixelSize(R.dimen.workspace_cell_width);
+        int widthGap = r.getDimensionPixelSize(R.dimen.workspace_width_gap_land);
+        int crosshairsSize = r.getDrawable(R.drawable.gardening_crosshairs).getIntrinsicWidth();
+
+        return widthGap * (numCells - 1) + cellWidth * numCells + crosshairsSize;
+    }
+
+    static int heightInPortrait(Resources r, int numCells) {
+        // We use this method from Workspace to figure out how many rows/columns Launcher should
+        // have. We ignore the left/right padding on CellLayout because it turns out in our design
+        // the padding extends outside the visible screen size, but it looked fine anyway.
+        // However, we make sure there's at least enough space for the crosshairs at the bottom
+        // to be rendered (half the crosshair is sticking out); we don't worry about the top
+        // crosshair since it can bleed into the action bar space
+        int cellHeight = r.getDimensionPixelSize(R.dimen.workspace_cell_height);
+        int heightGap = r.getDimensionPixelSize(R.dimen.workspace_height_gap_port);
+        int crosshairsSize = r.getDrawable(R.drawable.gardening_crosshairs).getIntrinsicHeight();
+
+        return heightGap * (numCells - 1) + cellHeight * numCells + (crosshairsSize + 1) / 2;
+    }
+
+    static int heightInLandscape(Resources r, int numCells) {
+        // We use this method from Workspace to figure out how many rows/columns Launcher should
+        // have. We ignore the left/right padding on CellLayout because it turns out in our design
+        // the padding extends outside the visible screen size, but it looked fine anyway.
+        // However, we make sure there's at least enough space for the crosshairs at the bottom
+        // to be rendered (half the crosshair is sticking out); we don't worry about the top
+        // crosshair since it can bleed into the action bar space
+        int cellHeight = r.getDimensionPixelSize(R.dimen.workspace_cell_height);
+        int heightGap = r.getDimensionPixelSize(R.dimen.workspace_height_gap_land);
+        int crosshairsSize = r.getDrawable(R.drawable.gardening_crosshairs).getIntrinsicHeight();
+
+        return heightGap * (numCells - 1) + cellHeight * numCells + (crosshairsSize + 1) / 2;
+    }
+
+    public void enableHardwareLayers() {
+        mChildren.enableHardwareLayers();
+    }
+
+    public void setGridSize(int x, int y) {
+        mCountX = x;
+        mCountY = y;
+        mOccupied = new boolean[mCountX][mCountY];
+    }
+
+    private void invalidateBubbleTextView(BubbleTextView icon) {
+        final int padding = icon.getPressedOrFocusedBackgroundPadding();
+        invalidate(icon.getLeft() + getLeftPadding() - padding,
+                icon.getTop() + getTopPadding() - padding,
+                icon.getRight() + getLeftPadding() + padding,
+                icon.getBottom() + getTopPadding() + padding);
+    }
+
+    void setPressedOrFocusedIcon(BubbleTextView icon) {
+        // We draw the pressed or focused BubbleTextView's background in CellLayout because it
+        // requires an expanded clip rect (due to the glow's blur radius)
+        BubbleTextView oldIcon = mPressedOrFocusedIcon;
+        mPressedOrFocusedIcon = icon;
+        if (oldIcon != null) {
+            invalidateBubbleTextView(oldIcon);
+        }
+        if (mPressedOrFocusedIcon != null) {
+            invalidateBubbleTextView(mPressedOrFocusedIcon);
+        }
+    }
+
     public CellLayoutChildren getChildrenLayout() {
         if (getChildCount() > 0) {
             return (CellLayoutChildren) getChildAt(0);
@@ -332,7 +417,7 @@
     }
 
     void animateDrop() {
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
             Resources res = getResources();
             float onDropScale = res.getInteger(R.integer.config_screenOnDropScalePercent) / 100.0f;
             ObjectAnimator scaleUp = ObjectAnimator.ofFloat(this, "hoverScale", onDropScale);
@@ -370,7 +455,7 @@
         // When we're small, we are either drawn normally or in the "accepts drops" state (during
         // a drag). However, we also drag the mini hover background *over* one of those two
         // backgrounds
-        if (LauncherApplication.isScreenXLarge() && mBackgroundAlpha > 0.0f) {
+        if (LauncherApplication.isScreenLarge() && mBackgroundAlpha > 0.0f) {
             Drawable bg;
             boolean mini = getScaleX() < 0.5f;
 
@@ -457,6 +542,19 @@
                 canvas.drawBitmap(b, p.x, p.y, paint);
             }
         }
+
+        // We draw the pressed or focused BubbleTextView's background in CellLayout because it
+        // requires an expanded clip rect (due to the glow's blur radius)
+        if (mPressedOrFocusedIcon != null) {
+            final int padding = mPressedOrFocusedIcon.getPressedOrFocusedBackgroundPadding();
+            final Bitmap b = mPressedOrFocusedIcon.getPressedOrFocusedBackground();
+            if (b != null) {
+                canvas.drawBitmap(b,
+                        mPressedOrFocusedIcon.getLeft() + getLeftPadding() - padding,
+                        mPressedOrFocusedIcon.getTop() + getTopPadding() - padding,
+                        null);
+            }
+        }
     }
 
     @Override
@@ -571,6 +669,10 @@
         mChildren.draw(canvas);
     }
 
+    void buildChildrenLayer() {
+        mChildren.buildLayer();
+    }
+
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
@@ -587,11 +689,12 @@
         boolean found = false;
         for (int i = count - 1; i >= 0; i--) {
             final View child = mChildren.getChildAt(i);
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
 
-            if ((child.getVisibility()) == VISIBLE || child.getAnimation() != null) {
+            if ((child.getVisibility() == VISIBLE || child.getAnimation() != null) &&
+                    lp.isLockedToGrid) {
                 child.getHitRect(frame);
                 if (frame.contains(x, y)) {
-                    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                     cellInfo.cell = child;
                     cellInfo.cellX = lp.cellX;
                     cellInfo.cellY = lp.cellY;
@@ -695,6 +798,22 @@
         result[1] = vStartPadding + cellY * (mCellHeight + mHeightGap);
     }
 
+    /**
+     * Given a cell coordinate, return the point that represents the upper left corner of that cell
+     *
+     * @param cellX X coordinate of the cell
+     * @param cellY Y coordinate of the cell
+     *
+     * @param result Array of 2 ints to hold the x and y coordinate of the point
+     */
+    void cellToCenterPoint(int cellX, int cellY, int[] result) {
+        final int hStartPadding = getLeftPadding();
+        final int vStartPadding = getTopPadding();
+
+        result[0] = hStartPadding + cellX * (mCellWidth + mWidthGap) + mCellWidth / 2;
+        result[1] = vStartPadding + cellY * (mCellHeight + mHeightGap) + mCellHeight / 2;
+    }
+
     int getCellWidth() {
         return mCellWidth;
     }
@@ -703,6 +822,14 @@
         return mCellHeight;
     }
 
+    int getWidthGap() {
+        return mWidthGap;
+    }
+
+    int getHeightGap() {
+        return mHeightGap;
+    }
+
     int getLeftPadding() {
         return mLeftPadding;
     }
@@ -719,6 +846,18 @@
         return mBottomPadding;
     }
 
+    Rect getContentRect(Rect r) {
+        if (r == null) {
+            r = new Rect();
+        }
+        int left = getPaddingLeft();
+        int top = getPaddingTop();
+        int right = left + getWidth() - mLeftPadding - mRightPadding;
+        int bottom = top + getHeight() - mTopPadding - mBottomPadding;
+        r.set(left, top, right, bottom);
+        return r;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         // TODO: currently ignoring padding
@@ -741,10 +880,10 @@
 
         if (mWidthGap < 0 || mHeightGap < 0) {
             int vSpaceLeft = heightSpecSize - mTopPadding - mBottomPadding - (cellHeight * mCountY);
-            mHeightGap = vSpaceLeft / numHeightGaps;
+            mHeightGap = numHeightGaps > 0 ? vSpaceLeft / numHeightGaps : 0;
 
             int hSpaceLeft = widthSpecSize - mLeftPadding - mRightPadding - (cellWidth * mCountX);
-            mWidthGap = hSpaceLeft / numWidthGaps;
+            mWidthGap = numWidthGaps > 0 ? hSpaceLeft / numWidthGaps : 0;
 
             // center it around the min gaps
             int minGap = Math.min(mWidthGap, mHeightGap);
@@ -765,9 +904,10 @@
         int count = getChildCount();
         for (int i = 0; i < count; i++) {
             View child = getChildAt(i);
-            int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY);
-            int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight,
-                    MeasureSpec.EXACTLY);
+            int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth - mLeftPadding -
+                    mRightPadding, MeasureSpec.EXACTLY);
+            int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight - mTopPadding -
+                    mBottomPadding, MeasureSpec.EXACTLY);
             child.measure(childWidthMeasureSpec, childheightMeasureSpec);
         }
         setMeasuredDimension(newWidth, newHeight);
@@ -778,7 +918,7 @@
         int count = getChildCount();
         for (int i = 0; i < count; i++) {
             View child = getChildAt(i);
-            child.layout(0, 0, r - l, b - t);
+            child.layout(mLeftPadding, mTopPadding, r - l - mRightPadding , b - t - mBottomPadding);
         }
     }
 
@@ -898,6 +1038,13 @@
             mDragCenter.set(originX, originY);
         }
 
+        if (dragOutline == null && v == null) {
+            if (mCrosshairsDrawable != null) {
+                invalidate();
+            }
+            return;
+        }
+
         if (nearest != null && (nearest[0] != oldDragCellX || nearest[1] != oldDragCellY)) {
             // Find the top left corner of the rect the object will occupy
             final int[] topLeft = mTmpPoint;
@@ -907,15 +1054,23 @@
             int top = topLeft[1];
 
             if (v != null) {
-                if (v.getParent() instanceof CellLayout) {
-                    LayoutParams lp = (LayoutParams) v.getLayoutParams();
-                    left += lp.leftMargin;
-                    top += lp.topMargin;
-                }
+                // When drawing the drag outline, it did not account for margin offsets
+                // added by the view's parent.
+                MarginLayoutParams lp = (MarginLayoutParams) v.getLayoutParams();
+                left += lp.leftMargin;
+                top += lp.topMargin;
 
-                // Offsets due to the size difference between the View and the dragOutline
+                // Offsets due to the size difference between the View and the dragOutline.
+                // There is a size difference to account for the outer blur, which may lie
+                // outside the bounds of the view.
                 left += (v.getWidth() - dragOutline.getWidth()) / 2;
                 top += (v.getHeight() - dragOutline.getHeight()) / 2;
+            } else {
+                // Center the drag outline in the cell
+                left += ((mCellWidth * spanX) + ((spanX - 1) * mWidthGap)
+                        - dragOutline.getWidth()) / 2;
+                top += ((mCellHeight * spanY) + ((spanY - 1) * mHeightGap)
+                        - dragOutline.getHeight()) / 2;
             }
 
             final int oldIndex = mDragOutlineCurrent;
@@ -933,6 +1088,13 @@
         }
     }
 
+    public void clearDragOutlines() {
+        final int oldIndex = mDragOutlineCurrent;
+        mDragOutlineAnims[oldIndex].animateOut();
+        mDragCell[0] = -1;
+        mDragCell[1] = -1;
+    }
+
     /**
      * Find a vacant area that will fit the given bounds nearest the requested
      * cell location. Uses Euclidean distance to score multiple vacant areas.
@@ -959,16 +1121,23 @@
      * @param pixelY The Y location at which you want to search for a vacant area.
      * @param spanX Horizontal span of the object.
      * @param spanY Vertical span of the object.
-     * @param ignoreView Considers space occupied by this view as unoccupied
-     * @param result Previously returned value to possibly recycle.
+     * @param ignoreOccupied If true, the result can be an occupied cell
+     * @param result Array in which to place the result, or null (in which case a new array will
+     *        be allocated)
      * @return The X, Y cell of a vacant area that can contain this object,
      *         nearest the requested location.
      */
-    int[] findNearestVacantArea(
-            int pixelX, int pixelY, int spanX, int spanY, View ignoreView, int[] result) {
+    int[] findNearestArea(int pixelX, int pixelY, int spanX, int spanY, View ignoreView,
+            boolean ignoreOccupied, int[] result) {
         // mark space take by ignoreView as available (method checks if ignoreView is null)
         markCellsAsUnoccupiedForView(ignoreView);
 
+        // For items with a spanX / spanY > 1, the passed in point (pixelX, pixelY) corresponds
+        // to the center of the item, but we are searching based on the top-left cell, so
+        // we translate the point over to correspond to the top-left.
+        pixelX -= (mCellWidth + mWidthGap) * (spanX - 1) / 2f;
+        pixelY -= (mCellHeight + mHeightGap) * (spanY - 1) / 2f;
+
         // Keep track of best-scoring drop area
         final int[] bestXY = result != null ? result : new int[2];
         double bestDistance = Double.MAX_VALUE;
@@ -980,18 +1149,20 @@
         for (int y = 0; y < countY - (spanY - 1); y++) {
             inner:
             for (int x = 0; x < countX - (spanX - 1); x++) {
-                for (int i = 0; i < spanX; i++) {
-                    for (int j = 0; j < spanY; j++) {
-                        if (occupied[x + i][y + j]) {
-                            // small optimization: we can skip to after the column we just found
-                            // an occupied cell
-                            x += i;
-                            continue inner;
+                if (ignoreOccupied) {
+                    for (int i = 0; i < spanX; i++) {
+                        for (int j = 0; j < spanY; j++) {
+                            if (occupied[x + i][y + j]) {
+                                // small optimization: we can skip to after the column we
+                                // just found an occupied cell
+                                x += i;
+                                continue inner;
+                            }
                         }
                     }
                 }
                 final int[] cellXY = mTmpCellXY;
-                cellToPoint(x, y, cellXY);
+                cellToCenterPoint(x, y, cellXY);
 
                 double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2)
                         + Math.pow(cellXY[1] - pixelY, 2));
@@ -1013,6 +1184,42 @@
         }
     }
 
+    /**
+     * Find a vacant area that will fit the given bounds nearest the requested
+     * cell location. Uses Euclidean distance to score multiple vacant areas.
+     *
+     * @param pixelX The X location at which you want to search for a vacant area.
+     * @param pixelY The Y location at which you want to search for a vacant area.
+     * @param spanX Horizontal span of the object.
+     * @param spanY Vertical span of the object.
+     * @param ignoreView Considers space occupied by this view as unoccupied
+     * @param result Previously returned value to possibly recycle.
+     * @return The X, Y cell of a vacant area that can contain this object,
+     *         nearest the requested location.
+     */
+    int[] findNearestVacantArea(
+            int pixelX, int pixelY, int spanX, int spanY, View ignoreView, int[] result) {
+        return findNearestArea(pixelX, pixelY, spanX, spanY, ignoreView, true, result);
+    }
+
+    /**
+     * Find a starting cell position that will fit the given bounds nearest the requested
+     * cell location. Uses Euclidean distance to score multiple vacant areas.
+     *
+     * @param pixelX The X location at which you want to search for a vacant area.
+     * @param pixelY The Y location at which you want to search for a vacant area.
+     * @param spanX Horizontal span of the object.
+     * @param spanY Vertical span of the object.
+     * @param ignoreView Considers space occupied by this view as unoccupied
+     * @param result Previously returned value to possibly recycle.
+     * @return The X, Y cell of a vacant area that can contain this object,
+     *         nearest the requested location.
+     */
+    int[] findNearestArea(
+            int pixelX, int pixelY, int spanX, int spanY, int[] result) {
+        return findNearestArea(pixelX, pixelY, spanX, spanY, null, false, result);
+    }
+
     boolean existsEmptyCell() {
         return findCellForSpan(null, 1, 1);
     }
@@ -1303,8 +1510,8 @@
     static boolean findVacantCell(int[] vacant, int spanX, int spanY,
             int xCount, int yCount, boolean[][] occupied) {
 
-        for (int x = 0; x < xCount; x++) {
-            for (int y = 0; y < yCount; y++) {
+        for (int y = 0; y < yCount; y++) {
+            for (int x = 0; x < 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++) {
@@ -1332,19 +1539,69 @@
         }
     }
 
+    /**
+     * Given a view, determines how much that view can be expanded in all directions, in terms of
+     * whether or not there are other items occupying adjacent cells. Used by the
+     * AppWidgetResizeFrame to determine how the widget can be resized.
+     */
+    public void getExpandabilityArrayForView(View view, int[] expandability) {
+        final LayoutParams lp = (LayoutParams) view.getLayoutParams();
+        boolean flag;
+
+        expandability[AppWidgetResizeFrame.LEFT] = 0;
+        for (int x = lp.cellX - 1; x >= 0; x--) {
+            flag = false;
+            for (int y = lp.cellY; y < lp.cellY + lp.cellVSpan; y++) {
+                if (mOccupied[x][y]) flag = true;
+            }
+            if (flag) break;
+            expandability[AppWidgetResizeFrame.LEFT]++;
+        }
+
+        expandability[AppWidgetResizeFrame.TOP] = 0;
+        for (int y = lp.cellY - 1; y >= 0; y--) {
+            flag = false;
+            for (int x = lp.cellX; x < lp.cellX + lp.cellHSpan; x++) {
+                if (mOccupied[x][y]) flag = true;
+            }
+            if (flag) break;
+            expandability[AppWidgetResizeFrame.TOP]++;
+        }
+
+        expandability[AppWidgetResizeFrame.RIGHT] = 0;
+        for (int x = lp.cellX + lp.cellHSpan; x < mCountX; x++) {
+            flag = false;
+            for (int y = lp.cellY; y < lp.cellY + lp.cellVSpan; y++) {
+                if (mOccupied[x][y]) flag = true;
+            }
+            if (flag) break;
+            expandability[AppWidgetResizeFrame.RIGHT]++;
+        }
+
+        expandability[AppWidgetResizeFrame.BOTTOM] = 0;
+        for (int y = lp.cellY + lp.cellVSpan; y < mCountY; y++) {
+            flag = false;
+            for (int x = lp.cellX; x < lp.cellX + lp.cellHSpan; x++) {
+                if (mOccupied[x][y]) flag = true;
+            }
+            if (flag) break;
+            expandability[AppWidgetResizeFrame.BOTTOM]++;
+        }
+    }
+
     public void onMove(View view, int newCellX, int newCellY) {
         LayoutParams lp = (LayoutParams) view.getLayoutParams();
         markCellsAsUnoccupiedForView(view);
         markCellsForView(newCellX, newCellY, lp.cellHSpan, lp.cellVSpan, true);
     }
 
-    private void markCellsAsOccupiedForView(View view) {
+    public void markCellsAsOccupiedForView(View view) {
         if (view == null || view.getParent() != mChildren) return;
         LayoutParams lp = (LayoutParams) view.getLayoutParams();
         markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, true);
     }
 
-    private void markCellsAsUnoccupiedForView(View view) {
+    public void markCellsAsUnoccupiedForView(View view) {
         if (view == null || view.getParent() != mChildren) return;
         LayoutParams lp = (LayoutParams) view.getLayoutParams();
         markCellsForView(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false);
@@ -1358,6 +1615,24 @@
         }
     }
 
+    public int getDesiredWidth() {
+        return mLeftPadding + mRightPadding + (mCountX * mCellWidth) +
+                (Math.max((mCountX - 1), 0) * mWidthGap);
+    }
+
+    public int getDesiredHeight()  {
+        return mTopPadding + mBottomPadding + (mCountY * mCellHeight) +
+                (Math.max((mCountY - 1), 0) * mHeightGap);
+    }
+
+    public boolean isOccupied(int x, int y) {
+        if (x < mCountX && y < mCountY) {
+            return mOccupied[x][y];
+        } else {
+            throw new RuntimeException("Position exceeds the bound of this CellLayout");
+        }
+    }
+
     @Override
     public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
         return new CellLayout.LayoutParams(getContext(), attrs);
@@ -1410,6 +1685,12 @@
         public int cellVSpan;
 
         /**
+         * Indicates whether the item will set its x, y, width and height parameters freely,
+         * or whether these will be computed based on cellX, cellY, cellHSpan and cellVSpan.
+         */
+        public boolean isLockedToGrid = true;
+
+        /**
          * Is this item currently being dragged
          */
         public boolean isDragging;
@@ -1465,26 +1746,57 @@
             this.cellVSpan = cellVSpan;
         }
 
-        public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap,
-                int hStartPadding, int vStartPadding) {
+        public void setup(int cellWidth, int cellHeight, int widthGap, int heightGap) {
+            if (isLockedToGrid) {
+                final int myCellHSpan = cellHSpan;
+                final int myCellVSpan = cellVSpan;
+                final int myCellX = cellX;
+                final int myCellY = cellY;
 
-            final int myCellHSpan = cellHSpan;
-            final int myCellVSpan = cellVSpan;
-            final int myCellX = cellX;
-            final int myCellY = cellY;
-
-            width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) -
-                    leftMargin - rightMargin;
-            height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
-                    topMargin - bottomMargin;
-
-            x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
-            y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
+                width = myCellHSpan * cellWidth + ((myCellHSpan - 1) * widthGap) -
+                        leftMargin - rightMargin;
+                height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
+                        topMargin - bottomMargin;
+                x = myCellX * (cellWidth + widthGap) + leftMargin;
+                y = myCellY * (cellHeight + heightGap) + topMargin;
+            }
         }
 
         public String toString() {
             return "(" + this.cellX + ", " + this.cellY + ")";
         }
+
+        public void setWidth(int width) {
+            this.width = width;
+        }
+
+        public int getWidth() {
+            return width;
+        }
+
+        public void setHeight(int height) {
+            this.height = height;
+        }
+
+        public int getHeight() {
+            return height;
+        }
+
+        public void setX(int x) {
+            this.x = x;
+        }
+
+        public int getX() {
+            return x;
+        }
+
+        public void setY(int y) {
+            this.y = y;
+        }
+
+        public int getY() {
+            return y;
+        }
     }
 
     // This class stores info for two purposes:
@@ -1493,7 +1805,7 @@
     // 2. When long clicking on an empty cell in a CellLayout, we save information about the
     //    cellX and cellY coordinates and which page was clicked. We then set this as a tag on
     //    the CellLayout that was long clicked
-    static final class CellInfo implements ContextMenu.ContextMenuInfo {
+    static final class CellInfo {
         View cell;
         int cellX = -1;
         int cellY = -1;
diff --git a/src/com/android/launcher2/CellLayoutChildren.java b/src/com/android/launcher2/CellLayoutChildren.java
index 0d0a339..59db9c9 100644
--- a/src/com/android/launcher2/CellLayoutChildren.java
+++ b/src/com/android/launcher2/CellLayoutChildren.java
@@ -21,7 +21,6 @@
 import android.graphics.Rect;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.View.MeasureSpec;
 
 public class CellLayoutChildren extends ViewGroup {
     static final String TAG = "CellLayoutChildren";
@@ -35,27 +34,21 @@
     private int mCellWidth;
     private int mCellHeight;
 
-    private int mLeftPadding;
-    private int mTopPadding;
-
     private int mWidthGap;
     private int mHeightGap;
 
     public CellLayoutChildren(Context context) {
         super(context);
         mWallpaperManager = WallpaperManager.getInstance(context);
-        setLayerType(LAYER_TYPE_HARDWARE, null);
-
-        // Disable multitouch for the workspace
-        setMotionEventSplittingEnabled(false);
     }
 
-    public void setCellDimensions(int cellWidth, int cellHeight,
-            int leftPadding, int topPadding, int widthGap, int heightGap ) {
+    public void enableHardwareLayers() {
+        setLayerType(LAYER_TYPE_HARDWARE, null);
+    }
+
+    public void setCellDimensions(int cellWidth, int cellHeight, int widthGap, int heightGap ) {
         mCellWidth = cellWidth;
         mCellHeight = cellHeight;
-        mLeftPadding = leftPadding;
-        mTopPadding = topPadding;
         mWidthGap = widthGap;
         mHeightGap = heightGap;
     }
@@ -67,7 +60,7 @@
             CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
 
             if ((lp.cellX <= x) && (x < lp.cellX + lp.cellHSpan) &&
-                    (lp.cellY <= y) && (y < lp.cellY + lp.cellHSpan)) {
+                    (lp.cellY <= y) && (y < lp.cellY + lp.cellVSpan)) {
                 return child;
             }
         }
@@ -76,27 +69,29 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int cellWidth = mCellWidth;
-        final int cellHeight = mCellHeight;
         int count = getChildCount();
         for (int i = 0; i < count; i++) {
             View child = getChildAt(i);
-            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
-
-            lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap,
-                    mLeftPadding, mTopPadding);
-
-            int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
-            int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
-                    MeasureSpec.EXACTLY);
-
-            child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+            measureChild(child);
         }
         int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
         int heightSpecSize =  MeasureSpec.getSize(heightMeasureSpec);
         setMeasuredDimension(widthSpecSize, heightSpecSize);
     }
 
+    public void measureChild(View child) {
+        final int cellWidth = mCellWidth;
+        final int cellHeight = mCellHeight;
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
+
+        lp.setup(cellWidth, cellHeight, mWidthGap, mHeightGap);
+        int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
+        int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height,
+                MeasureSpec.EXACTLY);
+
+        child.measure(childWidthMeasureSpec, childheightMeasureSpec);
+    }
+
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         int count = getChildCount();
@@ -171,4 +166,4 @@
     protected void setChildrenDrawnWithCacheEnabled(boolean enabled) {
         super.setChildrenDrawnWithCacheEnabled(enabled);
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index d08bf54..68ec535 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -38,8 +38,10 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
 import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Bitmap.Config;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -52,8 +54,9 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.View.MeasureSpec;
 import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
 import android.widget.Checkable;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -89,6 +92,10 @@
     // The mapping between the pages and the widgets that will be laid out on them
     private ArrayList<ArrayList<AppWidgetProviderInfo>> mWidgetPages;
 
+    // This is used if we want to set a min width on pages so that things inside them left align to
+    // a fixed size
+    private int mMinPageWidth;
+
     // The max dimensions for the ImageView we use for displaying a widget
     private int mMaxWidgetWidth;
 
@@ -118,11 +125,25 @@
     private final Canvas mCanvas = new Canvas();
     private final LayoutInflater mInflater;
 
+    private boolean mFirstMeasure = true;
+
     private final float mTmpFloatPos[] = new float[2];
     private final float ANIMATION_SCALE = 0.5f;
-    private final int ANIMATION_DURATION = 400;
+
+    // The duration of the translation animation that occurs during you drag and drop
+    private final int TRANSLATE_ANIM_DURATION = 400;
+
+    // The duration of the scale & alpha animation that occurs during drag and drop
+    private final int DROP_ANIM_DURATION = 200;
+
     private TimeInterpolator mQuintEaseOutInterpolator = new DecelerateInterpolator(2.5f);
-    private ScaleAlphaInterpolator mScaleAlphaInterpolator = new ScaleAlphaInterpolator();
+
+    // The Bitmap used to generate the drag view
+    private Bitmap mDragBitmap;
+
+    private int[] mDragViewOrigin = new int[2];
+
+    private int mPageContentWidth;
 
     public CustomizePagedView(Context context) {
         this(context, null, 0);
@@ -166,6 +187,32 @@
         mCenterPagesVertically = false;
     }
 
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+
+        if (mFirstMeasure) {
+            mFirstMeasure = false;
+
+            // TODO: actually calculate mCellCountX/mCellCountY as some function of
+            // widthSize and heightSize
+            //mCellCountX = ?
+            //mCellCountY = ?
+
+            // Since mCellCountX/mCellCountY changed, we need to update the pages
+            invalidatePageData();
+
+            // Create a dummy page and set it up to find out the content width (used by our parent)
+            PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
+            setupPage(layout);
+            mPageContentWidth = layout.getContentWidth();
+            mMinPageWidth = layout.getWidthBeforeFirstLayout();
+        }
+    }
+
     public void setLauncher(Launcher launcher) {
         Context context = getContext();
         mLauncher = launcher;
@@ -277,13 +324,8 @@
             }
         });
 
-        Comparator<ResolveInfo> resolveInfoComparator = new Comparator<ResolveInfo>() {
-            @Override
-            public int compare(ResolveInfo object1, ResolveInfo object2) {
-                return object1.loadLabel(mPackageManager).toString().compareTo(
-                        object2.loadLabel(mPackageManager).toString());
-            }
-        };
+        LauncherModel.ShortcutNameComparator resolveInfoComparator =
+                new LauncherModel.ShortcutNameComparator(mPackageManager);
 
         // get the list of shortcuts
         Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
@@ -324,38 +366,60 @@
         return mCustomizationType;
     }
 
-    @Override
-    public void onDropCompleted(View target, boolean success) {
-        resetCheckedGrandchildren();
+    /**
+     * Similar to resetCheckedGrandchildren, but allows us to specify that it's not animated.
+     */
+    private void resetCheckedItem(boolean animated) {
+        final Checkable checkable = getSingleCheckedGrandchild();
+        if (checkable != null) {
+            if (checkable instanceof PagedViewWidget) {
+                ((PagedViewWidget) checkable).setChecked(false, animated);
+            } else {
+                ((PagedViewIcon) checkable).setChecked(false, animated);
+            }
+        }
+    }
+
+    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+        final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+
+        // Create a view, identical to the drag view, that is only used for animating the
+        // item onto the home screen (or back to its original position, if the drop failed).
+        final int[] pos = mDragController.getDragView().getPosition(null);
+        final View animView = dragLayer.createDragView(mDragBitmap, pos[0], pos[1]);
+        animView.setVisibility(View.VISIBLE);
+
+        if (success) {
+            resetCheckedItem(true);
+            animateDropOntoScreen(animView, (ItemInfo) dragInfo, DROP_ANIM_DURATION, 0);
+        } else {
+            // Animate the icon/widget back to its original position
+            animateIntoPosition(animView, mDragViewOrigin[0], mDragViewOrigin[1], new Runnable() {
+                public void run() {
+                   resetCheckedItem(false);
+                   dragLayer.removeView(animView);
+                }
+            });
+        }
         mLauncher.getWorkspace().onDragStopped(success);
         mLauncher.unlockScreenOrientation();
+        mDragBitmap = null;
     }
 
     @Override
     public void onDragViewVisible() {
     }
 
-    class ScaleAlphaInterpolator implements Interpolator {
-        public float getInterpolation(float input) {
-            float pivot = 0.5f;
-            if (input < pivot) {
-                return 0;
-            } else {
-                return (input - pivot)/(1 - pivot);
-            }
-        }
-    }
-
+    /**
+     * Animates the given item onto the center of a home screen, and then scales the item to
+     * look as though it's disappearing onto that screen.
+     */
     private void animateItemOntoScreen(View dragView,
             final CellLayout layout, final ItemInfo info) {
         mTmpFloatPos[0] = layout.getWidth() / 2;
         mTmpFloatPos[1] = layout.getHeight() / 2;
         mLauncher.getWorkspace().mapPointFromChildToSelf(layout, mTmpFloatPos);
 
-        final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
-        final View dragCopy = dragLayer.createDragView(dragView);
-        dragCopy.setAlpha(1.0f);
-
         int dragViewWidth = dragView.getMeasuredWidth();
         int dragViewHeight = dragView.getMeasuredHeight();
         float heightOffset = 0;
@@ -374,43 +438,74 @@
                 widthOffset = ANIMATION_SCALE * (dragViewWidth - f * width) / 2;
             }
         }
+        final float toX = mTmpFloatPos[0] - dragView.getMeasuredWidth() / 2 + widthOffset;
+        final float toY = mTmpFloatPos[1] - dragView.getMeasuredHeight() / 2 + heightOffset;
 
-        float toX = mTmpFloatPos[0] - dragView.getMeasuredWidth() / 2 + widthOffset;
-        float toY = mTmpFloatPos[1] - dragView.getMeasuredHeight() / 2 + heightOffset;
+        final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+        final View dragCopy = dragLayer.createDragView(dragView);
+        dragCopy.setAlpha(1.0f);
 
-        ObjectAnimator posAnim = ObjectAnimator.ofPropertyValuesHolder(dragCopy,
-                PropertyValuesHolder.ofFloat("x", toX),
-                PropertyValuesHolder.ofFloat("y", toY));
-        posAnim.setInterpolator(mQuintEaseOutInterpolator);
-        posAnim.setDuration(ANIMATION_DURATION);
+        // Translate the item to the center of the appropriate home screen
+        animateIntoPosition(dragCopy, toX, toY, null);
 
-        posAnim.addListener(new AnimatorListenerAdapter() {
-            public void onAnimationEnd(Animator animation) {
-                dragLayer.removeView(dragCopy);
-                mLauncher.addExternalItemToScreen(info, layout);
-                post(new Runnable() {
-                    public void run() {
-                        layout.animateDrop();
-                    }
-                });
-            }
-        });
+        // The drop-onto-screen animation begins a bit later, but ends at the same time.
+        final int startDelay = TRANSLATE_ANIM_DURATION - DROP_ANIM_DURATION;
+        
+        // Scale down the icon and fade out the alpha
+        animateDropOntoScreen(dragCopy, info, DROP_ANIM_DURATION, startDelay);
+    }
 
-        ObjectAnimator scaleAlphaAnim = ObjectAnimator.ofPropertyValuesHolder(dragCopy,
+    /**
+     * Animation which scales the view down and animates its alpha, making it appear to disappear
+     * onto a home screen.
+     */
+    private void animateDropOntoScreen(
+            final View view, final ItemInfo info, int duration, int delay) {
+        final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+        final CellLayout layout = mLauncher.getWorkspace().getCurrentDropLayout();
+
+        ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(view,
                 PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.0f),
                 PropertyValuesHolder.ofFloat("scaleX", ANIMATION_SCALE),
                 PropertyValuesHolder.ofFloat("scaleY", ANIMATION_SCALE));
-        scaleAlphaAnim.setInterpolator(mScaleAlphaInterpolator);
-        scaleAlphaAnim.setDuration(ANIMATION_DURATION);
+        anim.setInterpolator(new LinearInterpolator());
+        if (delay > 0) {
+            anim.setStartDelay(delay);
+        }
+        anim.setDuration(duration);
+        anim.addListener(new AnimatorListenerAdapter() {
+            public void onAnimationEnd(Animator animation) {
+                dragLayer.removeView(view);
+                mLauncher.addExternalItemToScreen(info, layout);
+                info.dropPos = null;
+            }
+        });
+        anim.start();
+    }
 
-        posAnim.start();
-        scaleAlphaAnim.start();
+    /**
+     * Animates the x,y position of the view, and optionally execute a Runnable on animation end.
+     */
+    private void animateIntoPosition(
+            View view, float toX, float toY, final Runnable endRunnable) {
+        ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(view,
+                PropertyValuesHolder.ofFloat("x", toX),
+                PropertyValuesHolder.ofFloat("y", toY));
+        anim.setInterpolator(mQuintEaseOutInterpolator);
+        anim.setDuration(TRANSLATE_ANIM_DURATION);
+        if (endRunnable != null) {
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    endRunnable.run();
+                }
+            });
+        }
+        anim.start();
     }
 
     @Override
     public void onClick(final View v) {
-        // Return early if this is not initiated from a touch
-        if (!v.isInTouchMode()) return;
         // Return early if we are still animating the pages
         if (mNextPage != INVALID_PAGE) return;
 
@@ -479,12 +574,12 @@
         }
     }
 
-    Bitmap drawableToBitmap(Drawable d, View v, boolean clipHeight) {
-        int height = clipHeight ? v.getPaddingTop() + d.getIntrinsicHeight() : v.getHeight();
-        Bitmap b = Bitmap.createBitmap(v.getWidth(), height, Bitmap.Config.ARGB_8888);
-        Canvas c = new Canvas(b);
-        c.translate((v.getWidth() - d.getIntrinsicWidth()) / 2, v.getPaddingTop());
-        d.draw(c);
+    private Bitmap drawableToBitmap(Drawable d, float scaleX, float scaleY) {
+        final Rect bounds = d.getBounds();
+        final int w = bounds.width();
+        final int h = bounds.height();
+        Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        renderDrawableToBitmap(d, b, 0, 0, w, h, scaleX, scaleY);
         return b;
     }
 
@@ -501,6 +596,7 @@
         if (isChoiceMode(CHOICE_MODE_SINGLE)) {
             endChoiceMode();
         }
+        final Workspace workspace = mLauncher.getWorkspace();
         boolean result = false;
         mLauncher.lockScreenOrientation();
         switch (mCustomizationType) {
@@ -509,50 +605,50 @@
                 // Get the widget preview as the drag representation
                 final LinearLayout l = (LinearLayout) v;
                 final ImageView i = (ImageView) l.findViewById(R.id.widget_preview);
-                Bitmap b = drawableToBitmap(i.getDrawable(), i, true);
+
+                // Calculate how much to scale the drag preview
+                RectF tmpScaleRect = new RectF(0,0,1,1);
+                i.getImageMatrix().mapRect(tmpScaleRect);
+
+                mDragBitmap = drawableToBitmap(i.getDrawable(), tmpScaleRect.right,
+                        tmpScaleRect.bottom);
+                i.getLocationOnScreen(mDragViewOrigin);
                 PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) v.getTag();
 
-                int[] spanXY = CellLayout.rectToCell(
-                        getResources(), createWidgetInfo.minWidth, createWidgetInfo.minHeight, null);
+                int[] spanXY = CellLayout.rectToCell(getResources(),
+                        createWidgetInfo.minWidth, createWidgetInfo.minHeight, null);
                 createWidgetInfo.spanX = spanXY[0];
                 createWidgetInfo.spanY = spanXY[1];
-                mLauncher.getWorkspace().onDragStartedWithItemSpans(spanXY[0], spanXY[1], b);
-                mDragController.startDrag(
-                        i, b, this, createWidgetInfo, DragController.DRAG_ACTION_COPY, null);
-                b.recycle();
+                workspace.onDragStartedWithItemSpans(spanXY[0], spanXY[1], mDragBitmap);
+                mDragController.startDrag(i, mDragBitmap, this, createWidgetInfo,
+                        DragController.DRAG_ACTION_COPY, null);
                 result = true;
             }
             break;
         }
-        case ShortcutCustomization: {
-            if (v instanceof PagedViewIcon) {
-                // get icon (top compound drawable, index is 1)
-                final TextView tv = (TextView) v;
-                final Drawable icon = tv.getCompoundDrawables()[1];
-                Bitmap b = drawableToBitmap(icon, tv, false);
-                PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
-
-                mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
-                mDragController.startDrag(v, b, this, createItemInfo, DragController.DRAG_ACTION_COPY,
-                        null);
-                b.recycle();
-                result = true;
-            }
-            break;
-        }
+        case ShortcutCustomization:
         case ApplicationCustomization: {
             if (v instanceof PagedViewIcon) {
-                // Pick up the application for dropping
                 // get icon (top compound drawable, index is 1)
                 final TextView tv = (TextView) v;
                 final Drawable icon = tv.getCompoundDrawables()[1];
-                Bitmap b = drawableToBitmap(icon, tv, false);
-                ApplicationInfo app = (ApplicationInfo) v.getTag();
-                app = new ApplicationInfo(app);
+                mDragBitmap = drawableToBitmap(icon, 1.0f, 1.0f);
 
-                mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
-                mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, null);
-                b.recycle();
+                Object dragInfo = v.getTag();
+                if (mCustomizationType == CustomizationType.ApplicationCustomization) {
+                    // TODO: Not sure why we have to copy this
+                    dragInfo = new ApplicationInfo((ApplicationInfo) dragInfo);
+                }
+                workspace.onDragStartedWithItemSpans(1, 1, mDragBitmap);
+
+                // Calculate where to place the drag view in order to align the icon pixels with
+                // the original view.
+                v.getLocationOnScreen(mDragViewOrigin);
+                mDragViewOrigin[0] += (v.getWidth() - icon.getIntrinsicWidth()) / 2;
+                mDragViewOrigin[1] += v.getPaddingTop();
+
+                mDragController.startDrag(mDragBitmap, mDragViewOrigin[0], mDragViewOrigin[1],
+                        this, dragInfo, DragController.DRAG_ACTION_COPY);
                 result = true;
             }
             break;
@@ -619,11 +715,15 @@
     /**
      * Helper function to draw a drawable to the specified canvas with the specified bounds.
      */
-    private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
+    private void renderDrawableToBitmap(Drawable d, Bitmap bitmap, int x, int y, int w, int h,
+            float scaleX, float scaleY) {
         if (bitmap != null) mCanvas.setBitmap(bitmap);
         mCanvas.save();
-        d.setBounds(x, y, x+w, y+h);
+        mCanvas.scale(scaleX, scaleY);
+        final Rect oldBounds = d.copyBounds();
+        d.setBounds(x, y, x + w, y + h);
         d.draw(mCanvas);
+        d.setBounds(oldBounds); // Restore the bounds
         mCanvas.restore();
     }
 
@@ -706,7 +806,7 @@
             background = resources.getDrawable(R.drawable.default_widget_preview);
         }
 
-        renderDrawableToBitmap(background, bitmap, 0, 0, width, height);
+        renderDrawableToBitmap(background, bitmap, 0, 0, width, height, 1.0f, 1.0f);
 
         // If we don't have a custom icon, we use the app icon on the default background
         if (!foundCustomDrawable) {
@@ -718,7 +818,7 @@
 
                 final int iconSize = minDim / 2;
                 final int offset = iconSize / 4;
-                renderDrawableToBitmap(icon, null, offset, offset, iconSize, iconSize);
+                renderDrawableToBitmap(icon, null, offset, offset, iconSize, iconSize, 1.0f, 1.0f);
             } catch (Resources.NotFoundException e) {
                 // if we can't find the icon, then just don't draw it
             }
@@ -758,7 +858,7 @@
             int height = (int) (Math.max(minDim, Math.min(maxDim, info.minHeight)) * sScaleFactor);
             final Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
             final Drawable background = resources.getDrawable(R.drawable.default_widget_preview);
-            renderDrawableToBitmap(background, bitmap, 0, 0, width, height);
+            renderDrawableToBitmap(background, bitmap, 0, 0, width, height, 1.0f, 1.0f);
 
             // Draw the icon flush left
             try {
@@ -772,7 +872,7 @@
 
                 final int iconSize = minDim / 2;
                 final int offset = iconSize / 4;
-                renderDrawableToBitmap(icon, null, offset, offset, iconSize, iconSize);
+                renderDrawableToBitmap(icon, null, offset, offset, iconSize, iconSize, 1.0f, 1.0f);
             } catch (Resources.NotFoundException e) {
                 // if we can't find the icon, then just don't draw it
             }
@@ -798,7 +898,7 @@
             }
 
             final Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
-            renderDrawableToBitmap(drawable, bitmap, 0, 0, width, height);
+            renderDrawableToBitmap(drawable, bitmap, 0, 0, width, height, 1.0f, 1.0f);
 
             newDrawable = new FastBitmapDrawable(bitmap);
         }
@@ -852,11 +952,13 @@
             final int[] cellSpans = CellLayout.rectToCell(getResources(), info.minWidth,
                     info.minHeight, null);
             final FastBitmapDrawable icon = getWidgetPreview(info);
+            final boolean createHolographicOutlines = (numPages > 1);
 
             PagedViewWidget l = (PagedViewWidget) mInflater.inflate(
                     R.layout.customize_paged_view_widget, layout, false);
+
             l.applyFromAppWidgetProviderInfo(info, icon, mMaxWidgetWidth, cellSpans,
-                    mPageViewIconCache, (numPages > 1));
+                    mPageViewIconCache, createHolographicOutlines);
             l.setTag(createItemInfo);
             l.setOnClickListener(this);
             l.setOnTouchListener(this);
@@ -897,11 +999,12 @@
         for (int i = startIndex; i < endIndex; ++i) {
             final ResolveInfo info = mWallpaperList.get(i);
             final FastBitmapDrawable icon = getWallpaperPreview(info);
+            final boolean createHolographicOutlines = (numPages > 1);
 
             PagedViewWidget l = (PagedViewWidget) mInflater.inflate(
                     R.layout.customize_paged_view_wallpaper, layout, false);
             l.applyFromWallpaperInfo(info, mPackageManager, icon, mMaxWidgetWidth,
-                    mPageViewIconCache, (numPages > 1));
+                    mPageViewIconCache, createHolographicOutlines);
             l.setTag(info);
             l.setOnClickListener(this);
 
@@ -934,12 +1037,13 @@
         for (int i = startIndex; i < endIndex; ++i) {
             ResolveInfo info = list.get(i);
             PendingAddItemInfo createItemInfo = new PendingAddItemInfo();
+            final boolean createHolographicOutlines = (numPages > 1);
 
             PagedViewIcon icon = (PagedViewIcon) mInflater.inflate(
                     R.layout.customize_paged_view_item, layout, false);
             icon.applyFromResolveInfo(info, mPackageManager, mPageViewIconCache,
                     ((LauncherApplication) mLauncher.getApplication()).getIconCache(),
-                    (numPages > 1));
+                    createHolographicOutlines);
             switch (mCustomizationType) {
             case WallpaperCustomization:
                 icon.setOnClickListener(this);
@@ -993,9 +1097,11 @@
         layout.removeAllViewsOnPage();
         for (int i = startIndex; i < endIndex; ++i) {
             final ApplicationInfo info = mApps.get(i);
+            final boolean createHolographicOutlines = (numPages > 1);
             PagedViewIcon icon = (PagedViewIcon) mInflater.inflate(
                     R.layout.all_apps_paged_view_application, layout, false);
-            icon.applyFromApplicationInfo(info, mPageViewIconCache, true, (numPages > 1));
+            icon.applyFromApplicationInfo(
+                    info, mPageViewIconCache, true, createHolographicOutlines);
             icon.setOnClickListener(this);
             icon.setOnTouchListener(this);
             icon.setOnLongClickListener(this);
@@ -1010,10 +1116,17 @@
 
     @Override
     public void syncPages() {
+        if (mFirstMeasure) {
+            // We don't know our size yet, which means we haven't calculated cell count x/y;
+            // onMeasure will call us once we figure out our size
+            return;
+        }
+        boolean enforceMinimumPagedWidths = false;
         boolean centerPagedViewCellLayouts = false;
         switch (mCustomizationType) {
         case WidgetCustomization:
             syncWidgetPages();
+            enforceMinimumPagedWidths = true;
             break;
         case ShortcutCustomization:
             syncListPages(mShortcutList);
@@ -1021,6 +1134,7 @@
             break;
         case WallpaperCustomization:
             syncWallpaperPages();
+            enforceMinimumPagedWidths = true;
             break;
         case ApplicationCustomization:
             syncAppPages();
@@ -1046,8 +1160,22 @@
             }
         }
 
-        // bound the current page
-        setCurrentPage(Math.max(0, Math.min(childCount - 1, getCurrentPage())));
+        // Set a min page width for PagedView layout if we have more than a single page
+        if (enforceMinimumPagedWidths && childCount > 1) {
+            setMinimumWidthOverride(mMinPageWidth);
+        } else {
+            resetMinimumWidthOverride();
+        }
+
+        // Bound the current page index
+        requestLayout();
+        post(new Runnable() {
+            @Override
+            public void run() {
+                setCurrentPage(Math.max(0, Math.min(childCount - 1, getCurrentPage())));
+                forceUpdateAdjacentPagesAlpha();
+            }
+        });
     }
 
     @Override
@@ -1068,6 +1196,10 @@
         }
     }
 
+    int getPageContentWidth() {
+        return mPageContentWidth;
+    }
+
     @Override
     protected int getAssociatedLowerPageBound(int page) {
         return 0;
diff --git a/src/com/android/launcher2/CustomizeTrayTabHost.java b/src/com/android/launcher2/CustomizeTrayTabHost.java
new file mode 100644
index 0000000..ab50cf1
--- /dev/null
+++ b/src/com/android/launcher2/CustomizeTrayTabHost.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import java.util.Random;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+import android.widget.TextView;
+
+import com.android.launcher.R;
+import com.android.launcher2.CustomizePagedView.CustomizationType;
+
+public class CustomizeTrayTabHost extends TabHost implements LauncherTransitionable  {
+    // tags for the customization tabs
+    private static final String WIDGETS_TAG = "widgets";
+    private static final String APPLICATIONS_TAG = "applications";
+    private static final String SHORTCUTS_TAG = "shortcuts";
+    private static final String WALLPAPERS_TAG = "wallpapers";
+
+    private boolean mFirstLayout = true;
+
+    private final LayoutInflater mInflater;
+    private Context mContext;
+
+    public CustomizeTrayTabHost(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+        mInflater = LayoutInflater.from(context);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        setup();
+
+        final CustomizePagedView customizePagedView =
+            (CustomizePagedView) findViewById(R.id.customization_drawer_tab_contents);
+
+        // Configure tabs
+        TabContentFactory contentFactory = new TabContentFactory() {
+            public View createTabContent(String tag) {
+                return customizePagedView;
+            }
+        };
+
+        TextView tabView;
+        TabWidget tabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
+
+        tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+        tabView.setText(mContext.getString(R.string.widgets_tab_label));
+        addTab(newTabSpec(WIDGETS_TAG)
+                .setIndicator(tabView).setContent(contentFactory));
+        tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+        tabView.setText(mContext.getString(R.string.applications_tab_label));
+        addTab(newTabSpec(APPLICATIONS_TAG)
+                .setIndicator(tabView).setContent(contentFactory));
+        tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+        tabView.setText(mContext.getString(R.string.wallpapers_tab_label));
+        addTab(newTabSpec(WALLPAPERS_TAG)
+                .setIndicator(tabView).setContent(contentFactory));
+        tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
+        tabView.setText(mContext.getString(R.string.shortcuts_tab_label));
+        addTab(newTabSpec(SHORTCUTS_TAG)
+                .setIndicator(tabView).setContent(contentFactory));
+
+        setOnTabChangedListener(new OnTabChangeListener() {
+            public void onTabChanged(String tabId) {
+                final CustomizePagedView.CustomizationType newType =
+                    getCustomizeFilterForTabTag(tabId);
+                if (newType != customizePagedView.getCustomizationFilter()) {
+                    // animate the changing of the tab content by fading pages in and out
+                    final Resources res = getResources();
+                    final int duration = res.getInteger(R.integer.config_tabTransitionDuration);
+                    final float alpha = customizePagedView.getAlpha();
+                    ValueAnimator alphaAnim = ObjectAnimator.ofFloat(customizePagedView,
+                            "alpha", alpha, 0.0f);
+                    alphaAnim.setDuration(duration);
+                    alphaAnim.addListener(new AnimatorListenerAdapter() {
+                        @Override
+                        public void onAnimationEnd(Animator animation) {
+                            customizePagedView.setCustomizationFilter(newType);
+
+                            final float alpha = customizePagedView.getAlpha();
+                            ValueAnimator alphaAnim = ObjectAnimator.ofFloat(
+                                    customizePagedView, "alpha", alpha, 1.0f);
+                            alphaAnim.setDuration(duration);
+                            alphaAnim.start();
+                        }
+                    });
+                    alphaAnim.start();
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onLauncherTransitionStart(Animator animation) {
+        if (animation != null) {
+            setLayerType(LAYER_TYPE_HARDWARE, null);
+            // just a sanity check that we don't build a layer before a call to onLayout
+            if (!mFirstLayout) {
+                // force building the layer at the beginning of the animation, so you don't get a
+                // blip early in the animation
+                buildLayer();
+            }
+        }
+    }
+
+    @Override
+    public void onLauncherTransitionEnd(Animator animation) {
+        if (animation != null) {
+            setLayerType(LAYER_TYPE_NONE, null);
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        if (mFirstLayout) {
+            mFirstLayout = false;
+
+            final CustomizePagedView customizePagedView =
+                (CustomizePagedView) findViewById(R.id.customization_drawer_tab_contents);
+            TabWidget tabWidget = (TabWidget) findViewById(com.android.internal.R.id.tabs);
+            // Set the width of the tab bar properly
+            int pageWidth = customizePagedView.getPageContentWidth();
+            TabWidget customizeTabBar = (TabWidget) findViewById(com.android.internal.R.id.tabs);
+            if (customizeTabBar == null) throw new Resources.NotFoundException();
+            int tabWidgetPadding = 0;
+            final int childCount = tabWidget.getChildCount();
+            if (childCount > 0) {
+                tabWidgetPadding += tabWidget.getChildAt(0).getPaddingLeft() * 2;
+            }
+            customizeTabBar.getLayoutParams().width = pageWidth + tabWidgetPadding;
+        }
+        super.onLayout(changed, l, t, r, b);
+    }
+
+    @Override
+    public int getDescendantFocusability() {
+        if (getVisibility() != View.VISIBLE) {
+            return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+        }
+        return super.getDescendantFocusability();
+    }
+
+    CustomizationType getCustomizeFilterForTabTag(String tag) {
+        if (tag.equals(WIDGETS_TAG)) {
+            return CustomizationType.WidgetCustomization;
+        } else if (tag.equals(APPLICATIONS_TAG)) {
+            return CustomizationType.ApplicationCustomization;
+        } else if (tag.equals(WALLPAPERS_TAG)) {
+            return CustomizePagedView.CustomizationType.WallpaperCustomization;
+        } else if (tag.equals(SHORTCUTS_TAG)) {
+            return CustomizePagedView.CustomizationType.ShortcutCustomization;
+        }
+        return CustomizationType.WidgetCustomization;
+    }
+}
diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java
index 98d2b83..5d9b5db 100644
--- a/src/com/android/launcher2/DeleteZone.java
+++ b/src/com/android/launcher2/DeleteZone.java
@@ -16,8 +16,10 @@
 
 package com.android.launcher2;
 
-import com.android.launcher.R;
-
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -29,10 +31,8 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.animation.AccelerateInterpolator;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.view.animation.AnimationSet;
-import android.view.animation.TranslateAnimation;
+
+import com.android.launcher.R;
 
 public class DeleteZone extends IconDropTarget {
     private static final int ORIENTATION_HORIZONTAL = 1;
@@ -42,10 +42,8 @@
     private static final int XLARGE_ANIMATION_DURATION = 200;
     private static final int LEFT_DRAWABLE = 0;
 
-    private AnimationSet mInAnimation;
-    private AnimationSet mOutAnimation;
-    private Animation mHandleInAnimation;
-    private Animation mHandleOutAnimation;
+    private AnimatorSet mInAnimation;
+    private AnimatorSet mOutAnimation;
 
     private int mOrientation;
     private DragController mDragController;
@@ -70,7 +68,7 @@
         mOrientation = a.getInt(R.styleable.DeleteZone_direction, ORIENTATION_HORIZONTAL);
         a.recycle();
 
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
             int tb = getResources().getDimensionPixelSize(
                     R.dimen.delete_zone_vertical_drag_padding);
             int lr = getResources().getDimensionPixelSize(
@@ -83,7 +81,7 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mTransition = (TransitionDrawable) getCompoundDrawables()[LEFT_DRAWABLE];
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
             mTransition.setCrossFadeEnabled(false);
         }
 
@@ -104,7 +102,7 @@
         final ItemInfo item = (ItemInfo) dragInfo;
 
         // On x-large screens, you can uninstall an app by dragging from all apps
-        if (item instanceof ApplicationInfo && LauncherApplication.isScreenXLarge()) {
+        if (item instanceof ApplicationInfo && LauncherApplication.isScreenLarge()) {
             mLauncher.startApplicationUninstallActivity((ApplicationInfo) item);
         }
 
@@ -114,18 +112,12 @@
             if (item instanceof LauncherAppWidgetInfo) {
                 mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
             }
-        } else if (source instanceof UserFolder) {
-            final UserFolder userFolder = (UserFolder) source;
-            final UserFolderInfo userFolderInfo = (UserFolderInfo) userFolder.getInfo();
-            // Item must be a ShortcutInfo otherwise it couldn't have been in the folder
-            // in the first place.
-            userFolderInfo.remove((ShortcutInfo)item);
         }
 
-        if (item instanceof UserFolderInfo) {
-            final UserFolderInfo userFolderInfo = (UserFolderInfo)item;
-            LauncherModel.deleteUserFolderContentsFromDatabase(mLauncher, userFolderInfo);
-            mLauncher.removeFolder(userFolderInfo);
+        if (item instanceof FolderInfo) {
+            final FolderInfo folderInfo = (FolderInfo)item;
+            LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo);
+            mLauncher.removeFolder(folderInfo);
         } else if (item instanceof LauncherAppWidgetInfo) {
             final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
             final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
@@ -168,7 +160,7 @@
             getHitRect(mRegion);
             mRegionF.set(mRegion);
 
-            if (LauncherApplication.isScreenXLarge()) {
+            if (LauncherApplication.isScreenLarge()) {
                 // This region will be a "dead zone" for scrolling; make it extend to the edge of
                 // the screen so users don't accidentally trigger a scroll while deleting items
                 mRegionF.top = mLauncher.getWorkspace().getTop();
@@ -181,10 +173,10 @@
             mTransition.resetTransition();
 
             createAnimations();
-            startAnimation(mInAnimation);
+            mInAnimation.start();
             if (mOverlappingViews != null) {
                 for (View view : mOverlappingViews) {
-                    view.startAnimation(mHandleOutAnimation);
+                    createOutAlphaAnim(view).start();
                 }
             }
             setVisibility(VISIBLE);
@@ -196,68 +188,72 @@
             mActive = false;
             mDragController.setDeleteRegion(null);
 
-            if (mOutAnimation != null) startAnimation(mOutAnimation);
-            if (mHandleInAnimation != null && mOverlappingViews != null) {
+            mOutAnimation.start();
+            if (mOverlappingViews != null) {
                 for (View view : mOverlappingViews) {
-                    view.startAnimation(mHandleInAnimation);
+                    createInAlphaAnim(view).start();
                 }
             }
-            setVisibility(GONE);
         }
     }
 
+    private Animator createAlphaAnim(View v, float start, float end) {
+        Animator anim = ObjectAnimator.ofFloat(v, "alpha", start, end);
+        anim.setDuration(getAnimationDuration());
+        return anim;
+    }
+    private Animator createInAlphaAnim(View v) {
+        return createAlphaAnim(v, 0f, 1f);
+    }
+    private Animator createOutAlphaAnim(View v) {
+        return createAlphaAnim(v, 1f, 0f);
+    }
+
     private void createAnimations() {
         int duration = getAnimationDuration();
-        if (mHandleInAnimation == null) {
-            mHandleInAnimation = new AlphaAnimation(0.0f, 1.0f);
-            mHandleInAnimation.setDuration(duration);
-        }
 
+        Animator inAlphaAnim = createInAlphaAnim(this);
         if (mInAnimation == null) {
-            mInAnimation = new FastAnimationSet();
-            if (!LauncherApplication.isScreenXLarge()) {
-                final AnimationSet animationSet = mInAnimation;
-                animationSet.setInterpolator(new AccelerateInterpolator());
-                animationSet.addAnimation(new AlphaAnimation(0.0f, 1.0f));
+            mInAnimation = new AnimatorSet();
+            mInAnimation.setInterpolator(new AccelerateInterpolator());
+            mInAnimation.setDuration(duration);
+            if (!LauncherApplication.isScreenLarge()) {
+                Animator translateAnim;
                 if (mOrientation == ORIENTATION_HORIZONTAL) {
-                    animationSet.addAnimation(new TranslateAnimation(Animation.ABSOLUTE, 0.0f,
-                            Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f,
-                            Animation.RELATIVE_TO_SELF, 0.0f));
+                    translateAnim = ObjectAnimator.ofFloat(this, "translationY", 
+                            getMeasuredWidth(), 0f);
                 } else {
-                    animationSet.addAnimation(new TranslateAnimation(Animation.RELATIVE_TO_SELF,
-                            1.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.ABSOLUTE, 0.0f,
-                            Animation.ABSOLUTE, 0.0f));
+                    translateAnim = ObjectAnimator.ofFloat(this, "translationX", 
+                            getMeasuredHeight(), 0f);
                 }
-                animationSet.setDuration(duration);
+                mInAnimation.playTogether(translateAnim, inAlphaAnim);
             } else {
-                mInAnimation.addAnimation(mHandleInAnimation);
+                mInAnimation.play(inAlphaAnim);
             }
         }
 
-        if (mHandleOutAnimation == null) {
-            mHandleOutAnimation = new AlphaAnimation(1.0f, 0.0f);
-            mHandleOutAnimation.setFillAfter(true);
-            mHandleOutAnimation.setDuration(duration);
-        }
-
+        Animator outAlphaAnim = createOutAlphaAnim(this);
         if (mOutAnimation == null) {
-            mOutAnimation = new FastAnimationSet();
-            if (!LauncherApplication.isScreenXLarge()) {
-                final AnimationSet animationSet = mOutAnimation;
-                animationSet.setInterpolator(new AccelerateInterpolator());
-                animationSet.addAnimation(new AlphaAnimation(1.0f, 0.0f));
+            mOutAnimation = new AnimatorSet();
+            mOutAnimation.setInterpolator(new AccelerateInterpolator());
+            mOutAnimation.setDuration(duration);
+            if (!LauncherApplication.isScreenLarge()) {
+                Animator translateAnim;
                 if (mOrientation == ORIENTATION_HORIZONTAL) {
-                    animationSet.addAnimation(new FastTranslateAnimation(Animation.ABSOLUTE, 0.0f,
-                            Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
-                            Animation.RELATIVE_TO_SELF, 1.0f));
+                    translateAnim = ObjectAnimator.ofFloat(this, "translationY", 0f, 
+                            getMeasuredWidth());
                 } else {
-                    animationSet.addAnimation(new FastTranslateAnimation(Animation.RELATIVE_TO_SELF,
-                            0.0f, Animation.RELATIVE_TO_SELF, 1.0f, Animation.ABSOLUTE, 0.0f,
-                            Animation.ABSOLUTE, 0.0f));
+                    translateAnim = ObjectAnimator.ofFloat(this, "translationX", 0f, 
+                            getMeasuredHeight());
                 }
-                animationSet.setDuration(duration);
+                mOutAnimation.playTogether(translateAnim, outAlphaAnim);
             } else {
-                mOutAnimation.addAnimation(mHandleOutAnimation);
+                mOutAnimation.addListener(new AnimatorListenerAdapter() {
+                    public void onAnimationEnd(Animator animation) {
+                        setVisibility(GONE);
+                    }
+                });
+                mOutAnimation.play(outAlphaAnim);
             }
         }
     }
@@ -267,46 +263,12 @@
     }
 
     private int getTransitionAnimationDuration() {
-        return LauncherApplication.isScreenXLarge() ?
+        return LauncherApplication.isScreenLarge() ?
                 XLARGE_TRANSITION_DURATION : TRANSITION_DURATION;
     }
 
     private int getAnimationDuration() {
-        return LauncherApplication.isScreenXLarge() ?
+        return LauncherApplication.isScreenLarge() ?
                 XLARGE_ANIMATION_DURATION : ANIMATION_DURATION;
     }
-
-    private static class FastTranslateAnimation extends TranslateAnimation {
-        public FastTranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
-                int fromYType, float fromYValue, int toYType, float toYValue) {
-            super(fromXType, fromXValue, toXType, toXValue,
-                    fromYType, fromYValue, toYType, toYValue);
-        }
-
-        @Override
-        public boolean willChangeTransformationMatrix() {
-            return true;
-        }
-
-        @Override
-        public boolean willChangeBounds() {
-            return false;
-        }
-    }
-
-    private static class FastAnimationSet extends AnimationSet {
-        FastAnimationSet() {
-            super(false);
-        }
-
-        @Override
-        public boolean willChangeTransformationMatrix() {
-            return true;
-        }
-
-        @Override
-        public boolean willChangeBounds() {
-            return false;
-        }
-    }
 }
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 45b359d..5ca1e1c 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -73,10 +73,10 @@
     private boolean mDragging;
 
     /** X coordinate of the down event. */
-    private float mMotionDownX;
+    private int mMotionDownX;
 
     /** Y coordinate of the down event. */
-    private float mMotionDownY;
+    private int mMotionDownY;
 
     /** Info about the screen for clamping. */
     private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
@@ -85,10 +85,10 @@
     private View mOriginator;
 
     /** X offset from the upper-left corner of the cell to where we touched.  */
-    private float mTouchOffsetX;
+    private int mTouchOffsetX;
 
     /** Y offset from the upper-left corner of the cell to where we touched.  */
-    private float mTouchOffsetY;
+    private int mTouchOffsetY;
 
     /** the area at the edge of the screen that makes the workspace go left
      *   or right while you're dragging.
@@ -205,9 +205,7 @@
         int screenX = loc[0];
         int screenY = loc[1];
 
-        startDrag(b, screenX, screenY, 0, 0, b.getWidth(), b.getHeight(),
-                source, dragInfo, dragAction, dragRegion);
-
+        startDrag(b, screenX, screenY, source, dragInfo, dragAction, dragRegion);
         b.recycle();
 
         if (dragAction == DRAG_ACTION_MOVE) {
@@ -236,8 +234,7 @@
         int screenX = loc[0];
         int screenY = loc[1];
 
-        startDrag(bmp, screenX, screenY, 0, 0, bmp.getWidth(), bmp.getHeight(),
-                source, dragInfo, dragAction, dragRegion);
+        startDrag(bmp, screenX, screenY, source, dragInfo, dragAction, dragRegion);
 
         if (dragAction == DRAG_ACTION_MOVE) {
             v.setVisibility(View.GONE);
@@ -251,20 +248,14 @@
      *          enlarged size.
      * @param screenX The x position on screen of the left-top of the bitmap.
      * @param screenY The y position on screen of the left-top of the bitmap.
-     * @param textureLeft The left edge of the region inside b to use.
-     * @param textureTop The top edge of the region inside b to use.
-     * @param textureWidth The width of the region inside b to use.
-     * @param textureHeight The height of the region inside b to use.
      * @param source An object representing where the drag originated
      * @param dragInfo The data associated with the object that is being dragged
      * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
      *        {@link #DRAG_ACTION_COPY}
      */
     public void startDrag(Bitmap b, int screenX, int screenY,
-            int textureLeft, int textureTop, int textureWidth, int textureHeight,
             DragSource source, Object dragInfo, int dragAction) {
-        startDrag(b, screenX, screenY, textureLeft, textureTop, textureWidth, textureHeight,
-                source, dragInfo, dragAction, null);
+        startDrag(b, screenX, screenY, source, dragInfo, dragAction, null);
     }
 
     /**
@@ -274,10 +265,6 @@
      *          enlarged size.
      * @param screenX The x position on screen of the left-top of the bitmap.
      * @param screenY The y position on screen of the left-top of the bitmap.
-     * @param textureLeft The left edge of the region inside b to use.
-     * @param textureTop The top edge of the region inside b to use.
-     * @param textureWidth The width of the region inside b to use.
-     * @param textureHeight The height of the region inside b to use.
      * @param source An object representing where the drag originated
      * @param dragInfo The data associated with the object that is being dragged
      * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
@@ -286,7 +273,6 @@
      *          Makes dragging feel more precise, e.g. you can clip out a transparent border
      */
     public void startDrag(Bitmap b, int screenX, int screenY,
-            int textureLeft, int textureTop, int textureWidth, int textureHeight,
             DragSource source, Object dragInfo, int dragAction, Rect dragRegion) {
         if (PROFILE_DRAWING_DURING_DRAG) {
             android.os.Debug.startMethodTracing("Launcher");
@@ -303,13 +289,14 @@
             listener.onDragStart(source, dragInfo, dragAction);
         }
 
-        int registrationX = ((int)mMotionDownX) - screenX;
-        int registrationY = ((int)mMotionDownY) - screenY;
+        final int registrationX = ((int)mMotionDownX) - screenX;
+        final int registrationY = ((int)mMotionDownY) - screenY;
 
         final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
         final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
-        mTouchOffsetX = mMotionDownX - screenX - dragRegionLeft;
-        mTouchOffsetY = mMotionDownY - screenY - dragRegionTop;
+
+        mTouchOffsetX = mMotionDownX - (screenX + dragRegionLeft);
+        mTouchOffsetY = mMotionDownY - (screenY + dragRegionTop);
 
         mDragging = true;
         mDragSource = source;
@@ -318,7 +305,7 @@
         mVibrator.vibrate(VIBRATE_DURATION);
 
         DragView dragView = mDragView = new DragView(mContext, b, registrationX, registrationY,
-                textureLeft, textureTop, textureWidth, textureHeight);
+                0, 0, b.getWidth(), b.getHeight());
 
         final DragSource dragSource = source;
         dragView.setOnDrawRunnable(new Runnable() {
@@ -328,8 +315,7 @@
         });
 
         if (dragRegion != null) {
-            dragView.setDragRegion(dragRegionLeft, dragRegion.top,
-                    dragRegion.right - dragRegionLeft, dragRegion.bottom - dragRegionTop);
+            dragView.setDragRegion(new Rect(dragRegion));
         }
 
         dragView.show(mWindowToken, (int)mMotionDownX, (int)mMotionDownY);
@@ -400,7 +386,7 @@
     public void cancelDrag() {
         if (mDragging) {
             // Should we also be calling onDragExit() here?
-            mDragSource.onDropCompleted(null, false);
+            mDragSource.onDropCompleted(null, mDragInfo, false);
         }
         endDrag();
     }
@@ -571,6 +557,9 @@
             handleMoveEvent(screenX, screenY);
             break;
         case MotionEvent.ACTION_UP:
+            // Ensure that we've processed a move event at the current pointer location.
+            handleMoveEvent(screenX, screenY);
+
             mHandler.removeCallbacks(mScrollRunnable);
             if (mDragging) {
                 drop(screenX, screenY);
@@ -585,10 +574,11 @@
         return true;
     }
 
-    private boolean drop(float x, float y) {
+    private void drop(float x, float y) {
         final int[] coordinates = mCoordinatesTemp;
-        DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);
+        final DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);
 
+        boolean accepted = false;
         if (dropTarget != null) {
             dropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
                     (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
@@ -596,16 +586,10 @@
                     (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo)) {
                 dropTarget.onDrop(mDragSource, coordinates[0], coordinates[1],
                         (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);
-                mDragSource.onDropCompleted((View) dropTarget, true);
-                return true;
-            } else {
-                mDragSource.onDropCompleted((View) dropTarget, false);
-                return true;
+                accepted = true;
             }
-        } else {
-            mDragSource.onDropCompleted(null, false);
         }
-        return false;
+        mDragSource.onDropCompleted((View) dropTarget, mDragInfo, accepted);
     }
 
     private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
@@ -716,6 +700,10 @@
         mDeleteRegion = region;
     }
 
+    DragView getDragView() {
+        return mDragView;
+    }
+
     private class ScrollRunnable implements Runnable {
         private int mDirection;
 
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index a9dd7e3..7503dda 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -16,8 +16,11 @@
 
 package com.android.launcher2;
 
+import java.util.ArrayList;
+
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -25,6 +28,8 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import com.android.launcher.R;
+
 /**
  * A ViewGroup that coordinates dragging across its descendants
  */
@@ -32,6 +37,14 @@
     private DragController mDragController;
     private int[] mTmpXY = new int[2];
 
+    // Variables relating to resizing widgets
+    private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
+            new ArrayList<AppWidgetResizeFrame>();
+    private AppWidgetResizeFrame mCurrentResizeFrame;
+    private int mXDown, mYDown;
+    private Folder mCurrentFolder = null;
+    private Launcher mLauncher;
+
     /**
      * Used to create a new DragLayer from XML.
      *
@@ -54,13 +67,78 @@
         return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
     }
 
+    private boolean handleTouchDown(MotionEvent ev) {
+        Rect hitRect = new Rect();
+        int x = (int) ev.getX();
+        int y = (int) ev.getY();
+
+        for (AppWidgetResizeFrame child: mResizeFrames) {
+            child.getHitRect(hitRect);
+            if (hitRect.contains(x, y)) {
+                if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
+                    mCurrentResizeFrame = child;
+                    mXDown = x;
+                    mYDown = y;
+                    requestDisallowInterceptTouchEvent(true);
+                    return true;
+                }
+            }
+        }
+        if (mCurrentFolder != null) {
+            mCurrentFolder.getHitRect(hitRect);
+            int[] screenPos = new int[2];
+            View parent = (View) mCurrentFolder.getParent();
+            if (parent != null) {
+                parent.getLocationOnScreen(screenPos);
+                hitRect.offset(screenPos[0], screenPos[1]);
+                if (!hitRect.contains(x, y)) {
+                    mLauncher.closeFolder();
+                }
+            }
+        }
+        return false;
+    }
+
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (handleTouchDown(ev)) {
+                return true;
+            }
+        }
+        clearAllResizeFrames();
         return mDragController.onInterceptTouchEvent(ev);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
+        boolean handled = false;
+        int action = ev.getAction();
+
+        int x = (int) ev.getX();
+        int y = (int) ev.getY();
+
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+                if (handleTouchDown(ev)) {
+                    return true;
+                }
+            }
+        }
+
+        if (mCurrentResizeFrame != null) {
+            handled = true;
+            switch (action) {
+                case MotionEvent.ACTION_MOVE:
+                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
+                    break;
+                case MotionEvent.ACTION_CANCEL:
+                case MotionEvent.ACTION_UP:
+                    mCurrentResizeFrame.commitResizeForDelta(x - mXDown, y - mYDown);
+                    mCurrentResizeFrame = null;
+            }
+        }
+        if (handled) return true;
         return mDragController.onTouchEvent(ev);
     }
 
@@ -83,4 +161,102 @@
         v.getLocationOnScreen(mTmpXY);
         return createDragView(mDragController.getViewBitmap(v), mTmpXY[0], mTmpXY[1]);
     }
+
+    public static class LayoutParams extends FrameLayout.LayoutParams {
+        public int x, y;
+        public boolean customPosition = false;
+
+        /**
+         * {@inheritDoc}
+         */
+        public LayoutParams(int width, int height) {
+            super(width, height);
+        }
+
+        public void setWidth(int width) {
+            this.width = width;
+        }
+
+        public int getWidth() {
+            return width;
+        }
+
+        public void setHeight(int height) {
+            this.height = height;
+        }
+
+        public int getHeight() {
+            return height;
+        }
+
+        public void setX(int x) {
+            this.x = x;
+        }
+
+        public int getX() {
+            return x;
+        }
+
+        public void setY(int y) {
+            this.y = y;
+        }
+
+        public int getY() {
+            return y;
+        }
+    }
+
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
+            if (flp instanceof LayoutParams) {
+                final LayoutParams lp = (LayoutParams) flp;
+                if (lp.customPosition) {
+                    child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
+                }
+            }
+        }
+    }
+
+    public void clearAllResizeFrames() {
+        if (mResizeFrames.size() > 0) {
+            for (AppWidgetResizeFrame frame: mResizeFrames) {
+                removeView(frame);
+            }
+            mResizeFrames.clear();
+        }
+    }
+
+    public boolean hasResizeFrames() {
+        return mResizeFrames.size() > 0;
+    }
+
+    public boolean isWidgetBeingResized() {
+        return mCurrentResizeFrame != null;
+    }
+
+    public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
+            CellLayout cellLayout) {
+        AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
+                itemInfo, widget, cellLayout, this);
+
+        LayoutParams lp = new LayoutParams(-1, -1);
+        lp.customPosition = true;
+
+        addView(resizeFrame, lp);
+        mResizeFrames.add(resizeFrame);
+
+        resizeFrame.snapToWidget(false);
+    }
+
+    public void setLauncher(Launcher l) {
+        mLauncher = l;
+    }
+
+    public void setCurrentFolder(Folder f) {
+        mCurrentFolder = f;
+    }
 }
diff --git a/src/com/android/launcher2/DragScroller.java b/src/com/android/launcher2/DragScroller.java
index 6af9c30..6ef4bd8 100644
--- a/src/com/android/launcher2/DragScroller.java
+++ b/src/com/android/launcher2/DragScroller.java
@@ -26,6 +26,7 @@
 
     /**
      * The touch point has entered the scroll area; a scroll is imminent.
+     * This event will only occur while a drag is active.
      *
      * @param direction The scroll direction
      */
@@ -33,6 +34,7 @@
 
     /**
      * The touch point has left the scroll area.
+     * NOTE: This may not be called, if a drop occurs inside the scroll area.
      */
     void onExitScrollArea();
 }
diff --git a/src/com/android/launcher2/DragSource.java b/src/com/android/launcher2/DragSource.java
index 11cdcc9..649120d 100644
--- a/src/com/android/launcher2/DragSource.java
+++ b/src/com/android/launcher2/DragSource.java
@@ -23,13 +23,11 @@
  *
  */
 public interface DragSource {
-    void setDragController(DragController dragger);
-
     /**
      * Callback from the DragController when it begins drawing the drag view.
      * This allows the DragSource to dim or hide the original view.
      */
     void onDragViewVisible();
 
-    void onDropCompleted(View target, boolean success);
+    void onDropCompleted(View target, Object dragInfo, boolean success);
 }
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index c0776a9..b02e22b 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -26,6 +26,7 @@
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.os.IBinder;
 import android.view.Gravity;
 import android.view.View;
@@ -42,10 +43,7 @@
     private int mRegistrationX;
     private int mRegistrationY;
 
-    private int mDragRegionLeft = 0;
-    private int mDragRegionTop = 0;
-    private int mDragRegionWidth;
-    private int mDragRegionHeight;
+    private Rect mDragRegion = null;
 
     ValueAnimator mAnim;
     private float mOffsetX = 0.0f;
@@ -87,8 +85,8 @@
             scale.setScale(scaleFactor, scaleFactor);
         }
 
-        final int offsetX = res.getInteger(R.integer.config_dragViewOffsetX);
-        final int offsetY = res.getInteger(R.integer.config_dragViewOffsetY);
+        final int offsetX = res.getDimensionPixelSize(R.dimen.dragViewOffsetX);
+        final int offsetY = res.getDimensionPixelSize(R.dimen.dragViewOffsetY);
 
         // Animate the view into the correct position
         mAnim = ValueAnimator.ofFloat(0.0f, 1.0f);
@@ -117,7 +115,7 @@
         });
 
         mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true);
-        setDragRegion(0, 0, width, height);
+        setDragRegion(new Rect(0, 0, width, height));
 
         // The point in our scaled bitmap that the touch events are located
         mRegistrationX = registrationX;
@@ -132,31 +130,32 @@
         return mOffsetY;
     }
 
-    public void setDragRegion(int left, int top, int width, int height) {
-        mDragRegionLeft = left;
-        mDragRegionTop = top;
-        mDragRegionWidth = width;
-        mDragRegionHeight = height;
-    }
-
     public void setOnDrawRunnable(Runnable r) {
         mOnDrawRunnable = r;
     }
 
     public int getDragRegionLeft() {
-        return mDragRegionLeft;
+        return mDragRegion.left;
     }
 
     public int getDragRegionTop() {
-        return mDragRegionTop;
+        return mDragRegion.top;
     }
 
     public int getDragRegionWidth() {
-        return mDragRegionWidth;
+        return mDragRegion.width();
     }
 
     public int getDragRegionHeight() {
-        return mDragRegionHeight;
+        return mDragRegion.height();
+    }
+
+    public void setDragRegion(Rect r) {
+        mDragRegion = r;
+    }
+
+    public Rect getDragRegion() {
+        return mDragRegion;
     }
 
     @Override
@@ -245,5 +244,13 @@
     void remove() {
         mWindowManager.removeView(this);
     }
+
+    int[] getPosition(int[] result) {
+        WindowManager.LayoutParams lp = mLayoutParams;
+        if (result == null) result = new int[2];
+        result[0] = lp.x;
+        result[1] = lp.y;
+        return result;
+    }
 }
 
diff --git a/src/com/android/launcher2/FocusHelper.java b/src/com/android/launcher2/FocusHelper.java
new file mode 100644
index 0000000..861a70b
--- /dev/null
+++ b/src/com/android/launcher2/FocusHelper.java
@@ -0,0 +1,1056 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+import android.content.res.Configuration;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+
+import com.android.launcher.R;
+
+/**
+ * A keyboard listener we set on all the button bar buttons.
+ */
+class ButtonBarKeyEventListener implements View.OnKeyListener {
+    @Override
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        return FocusHelper.handleButtonBarButtonKeyEvent(v, keyCode, event);
+    }
+}
+
+/**
+ * A keyboard listener we set on the indicator buttons.
+ */
+class IndicatorKeyEventListener implements View.OnKeyListener {
+    @Override
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        return FocusHelper.handleIndicatorButtonKeyEvent(v, keyCode, event);
+    }
+}
+
+/**
+ * A keyboard listener we set on all the dock buttons.
+ */
+class DockKeyEventListener implements View.OnKeyListener {
+    @Override
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        final Configuration configuration = v.getResources().getConfiguration();
+        return FocusHelper.handleDockButtonKeyEvent(v, keyCode, event, configuration.orientation);
+    }
+}
+
+/**
+ * A keyboard listener we set on the last tab button in AllApps to jump to then
+ * market icon and vice versa.
+ */
+class AllAppsTabKeyEventListener implements View.OnKeyListener {
+    @Override
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        return FocusHelper.handleAllAppsTabKeyEvent(v, keyCode, event);
+    }
+}
+
+public class FocusHelper {
+    /**
+     * Private helper to get the parent TabHost in the view hiearchy.
+     */
+    private static TabHost findTabHostParent(View v) {
+        ViewParent p = v.getParent();
+        while (p != null && !(p instanceof TabHost)) {
+            p = p.getParent();
+        }
+        return (TabHost) p;
+    }
+
+    /**
+     * Handles key events in a AllApps tab between the last tab view and the shop button.
+     */
+    static boolean handleAllAppsTabKeyEvent(View v, int keyCode, KeyEvent e) {
+        final TabHost tabHost = findTabHostParent(v);
+        final ViewGroup contents = (ViewGroup)
+                tabHost.findViewById(com.android.internal.R.id.tabcontent);
+        final View shop = tabHost.findViewById(R.id.market_button);
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the shop button if we aren't on it
+                    if (v != shop) {
+                        shop.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the content view (down is handled by the tab key handler otherwise)
+                    if (v == shop) {
+                        contents.requestFocus();
+                        wasHandled = true;
+                    }
+                }
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Private helper to determine whether a view is visible.
+     */
+    private static boolean isVisible(View v) {
+        return v.getVisibility() == View.VISIBLE;
+    }
+
+    /**
+     * Handles key events in a PageViewExtendedLayout containing PagedViewWidgets.
+     * To be deprecated.
+     */
+    static boolean handlePagedViewWidgetKeyEvent(PagedViewWidget w, int keyCode, KeyEvent e) {
+        if (!LauncherApplication.isScreenLarge()) return false;
+
+        final PagedViewExtendedLayout parent = (PagedViewExtendedLayout) w.getParent();
+        final ViewGroup container = (ViewGroup) parent.getParent();
+        final TabHost tabHost = findTabHostParent(container);
+        final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs);
+        final int widgetIndex = parent.indexOfChild(w);
+        final int widgetCount = parent.getChildCount();
+        final int pageIndex = container.indexOfChild(parent);
+        final int pageCount = container.getChildCount();
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        PagedViewExtendedLayout newParent = null;
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous widget or the last widget on the previous page
+                    if (widgetIndex > 0) {
+                        parent.getChildAt(widgetIndex - 1).requestFocus();
+                    } else {
+                        if (pageIndex > 0) {
+                            newParent = (PagedViewExtendedLayout)
+                                    container.getChildAt(pageIndex - 1);
+                            newParent.getChildAt(newParent.getChildCount() - 1).requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next widget or the first widget on the next page
+                    if (widgetIndex < (widgetCount - 1)) {
+                        parent.getChildAt(widgetIndex + 1).requestFocus();
+                    } else {
+                        if (pageIndex < (pageCount - 1)) {
+                            newParent = (PagedViewExtendedLayout)
+                                    container.getChildAt(pageIndex + 1);
+                            newParent.getChildAt(0).requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (handleKeyEvent) {
+                    // Select widgets tab on the tab bar
+                    tabs.requestFocus();
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // TODO: Should focus the global search bar
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_ENTER:
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+                if (handleKeyEvent) {
+                    // Simulate a click on the widget
+                    View.OnClickListener clickListener = (View.OnClickListener) container;
+                    clickListener.onClick(w);
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_UP:
+                if (handleKeyEvent) {
+                    // Select the first item on the previous page, or the first item on this page
+                    // if there is no previous page
+                    if (pageIndex > 0) {
+                        newParent = (PagedViewExtendedLayout) container.getChildAt(pageIndex - 1);
+                        newParent.getChildAt(0).requestFocus();
+                    } else {
+                        parent.getChildAt(0).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_DOWN:
+                if (handleKeyEvent) {
+                    // Select the first item on the next page, or the last item on this page
+                    // if there is no next page
+                    if (pageIndex < (pageCount - 1)) {
+                        newParent = (PagedViewExtendedLayout) container.getChildAt(pageIndex + 1);
+                        newParent.getChildAt(0).requestFocus();
+                    } else {
+                        parent.getChildAt(widgetCount - 1).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_HOME:
+                if (handleKeyEvent) {
+                    // Select the first item on this page
+                    parent.getChildAt(0).requestFocus();
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_END:
+                if (handleKeyEvent) {
+                    // Select the last item on this page
+                    parent.getChildAt(widgetCount - 1).requestFocus();
+                }
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Handles key events in a PageViewExtendedLayout containing PagedViewWidgets.
+     */
+    static boolean handlePagedViewGridLayoutWidgetKeyEvent(PagedViewWidget w, int keyCode,
+            KeyEvent e) {
+
+        final PagedViewGridLayout parent = (PagedViewGridLayout) w.getParent();
+        final ViewGroup container = (ViewGroup) parent.getParent();
+        final TabHost tabHost = findTabHostParent(container);
+        final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs);
+        final int widgetIndex = parent.indexOfChild(w);
+        final int widgetCount = parent.getChildCount();
+        final int pageIndex = container.indexOfChild(parent);
+        final int pageCount = container.getChildCount();
+        final int cellCountX = parent.getCellCountX();
+        final int cellCountY = parent.getCellCountY();
+        final int x = widgetIndex % cellCountX;
+        final int y = widgetIndex / cellCountX;
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        PagedViewGridLayout newParent = null;
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous widget or the last widget on the previous page
+                    if (widgetIndex > 0) {
+                        parent.getChildAt(widgetIndex - 1).requestFocus();
+                    } else {
+                        if (pageIndex > 0) {
+                            newParent = (PagedViewGridLayout)
+                                    container.getChildAt(pageIndex - 1);
+                            newParent.getChildAt(newParent.getChildCount() - 1).requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next widget or the first widget on the next page
+                    if (widgetIndex < (widgetCount - 1)) {
+                        parent.getChildAt(widgetIndex + 1).requestFocus();
+                    } else {
+                        if (pageIndex < (pageCount - 1)) {
+                            newParent = (PagedViewGridLayout)
+                                    container.getChildAt(pageIndex + 1);
+                            newParent.getChildAt(0).requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the previous row, otherwise select the tab bar
+                    if (y > 0) {
+                        int newWidgetIndex = ((y - 1) * cellCountX) + x;
+                        parent.getChildAt(newWidgetIndex).requestFocus();
+                    } else {
+                        tabs.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the previous row, otherwise do nothing
+                    if (y < (cellCountY - 1)) {
+                        int newWidgetIndex = Math.min(widgetCount - 1, ((y + 1) * cellCountX) + x);
+                        parent.getChildAt(newWidgetIndex).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_ENTER:
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+                if (handleKeyEvent) {
+                    // Simulate a click on the widget
+                    View.OnClickListener clickListener = (View.OnClickListener) container;
+                    clickListener.onClick(w);
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_UP:
+                if (handleKeyEvent) {
+                    // Select the first item on the previous page, or the first item on this page
+                    // if there is no previous page
+                    if (pageIndex > 0) {
+                        newParent = (PagedViewGridLayout) container.getChildAt(pageIndex - 1);
+                        newParent.getChildAt(0).requestFocus();
+                    } else {
+                        parent.getChildAt(0).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_DOWN:
+                if (handleKeyEvent) {
+                    // Select the first item on the next page, or the last item on this page
+                    // if there is no next page
+                    if (pageIndex < (pageCount - 1)) {
+                        newParent = (PagedViewGridLayout) container.getChildAt(pageIndex + 1);
+                        newParent.getChildAt(0).requestFocus();
+                    } else {
+                        parent.getChildAt(widgetCount - 1).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_HOME:
+                if (handleKeyEvent) {
+                    // Select the first item on this page
+                    parent.getChildAt(0).requestFocus();
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_END:
+                if (handleKeyEvent) {
+                    // Select the last item on this page
+                    parent.getChildAt(widgetCount - 1).requestFocus();
+                }
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Private helper method to get the PagedViewCellLayoutChildren given a PagedViewCellLayout
+     * index.
+     */
+    private static PagedViewCellLayoutChildren getPagedViewCellLayoutChildrenForIndex(
+            ViewGroup container, int i) {
+        ViewGroup parent = (ViewGroup) container.getChildAt(i);
+        return (PagedViewCellLayoutChildren) parent.getChildAt(0);
+    }
+
+    /**
+     * Handles key events in a PageViewCellLayout containing PagedViewIcons.
+     */
+    static boolean handlePagedViewIconKeyEvent(PagedViewIcon v, int keyCode, KeyEvent e) {
+        final PagedViewCellLayoutChildren parent = (PagedViewCellLayoutChildren) v.getParent();
+        final PagedViewCellLayout parentLayout = (PagedViewCellLayout) parent.getParent();
+        // Note we have an extra parent because of the
+        // PagedViewCellLayout/PagedViewCellLayoutChildren relationship
+        final ViewGroup container = (ViewGroup) parentLayout.getParent();
+        final TabHost tabHost = findTabHostParent(container);
+        final TabWidget tabs = (TabWidget) tabHost.findViewById(com.android.internal.R.id.tabs);
+        final int widgetIndex = parent.indexOfChild(v);
+        final int widgetCount = parent.getChildCount();
+        final int pageIndex = container.indexOfChild(parentLayout);
+        final int pageCount = container.getChildCount();
+        final int cellCountX = parentLayout.getCellCountX();
+        final int cellCountY = parentLayout.getCellCountY();
+        final int x = widgetIndex % cellCountX;
+        final int y = widgetIndex / cellCountX;
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        PagedViewCellLayoutChildren newParent = null;
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous icon or the last icon on the previous page
+                    if (widgetIndex > 0) {
+                        parent.getChildAt(widgetIndex - 1).requestFocus();
+                    } else {
+                        if (pageIndex > 0) {
+                            newParent = getPagedViewCellLayoutChildrenForIndex(container,
+                                    pageIndex - 1);
+                            newParent.getChildAt(newParent.getChildCount() - 1).requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next icon or the first icon on the next page
+                    if (widgetIndex < (widgetCount - 1)) {
+                        parent.getChildAt(widgetIndex + 1).requestFocus();
+                    } else {
+                        if (pageIndex < (pageCount - 1)) {
+                            newParent = getPagedViewCellLayoutChildrenForIndex(container,
+                                    pageIndex + 1);
+                            newParent.getChildAt(0).requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the previous row, otherwise select the tab bar
+                    if (y > 0) {
+                        int newWidgetIndex = ((y - 1) * cellCountX) + x;
+                        parent.getChildAt(newWidgetIndex).requestFocus();
+                    } else {
+                        tabs.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the previous row, otherwise do nothing
+                    if (y < (cellCountY - 1)) {
+                        int newWidgetIndex = Math.min(widgetCount - 1, ((y + 1) * cellCountX) + x);
+                        parent.getChildAt(newWidgetIndex).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_ENTER:
+            case KeyEvent.KEYCODE_DPAD_CENTER:
+                if (handleKeyEvent) {
+                    // Simulate a click on the icon
+                    View.OnClickListener clickListener = (View.OnClickListener) container;
+                    clickListener.onClick(v);
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_UP:
+                if (handleKeyEvent) {
+                    // Select the first icon on the previous page, or the first icon on this page
+                    // if there is no previous page
+                    if (pageIndex > 0) {
+                        newParent = getPagedViewCellLayoutChildrenForIndex(container,
+                                pageIndex - 1);
+                        newParent.getChildAt(0).requestFocus();
+                    } else {
+                        parent.getChildAt(0).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_DOWN:
+                if (handleKeyEvent) {
+                    // Select the first icon on the next page, or the last icon on this page
+                    // if there is no next page
+                    if (pageIndex < (pageCount - 1)) {
+                        newParent = getPagedViewCellLayoutChildrenForIndex(container,
+                                pageIndex + 1);
+                        newParent.getChildAt(0).requestFocus();
+                    } else {
+                        parent.getChildAt(widgetCount - 1).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_HOME:
+                if (handleKeyEvent) {
+                    // Select the first icon on this page
+                    parent.getChildAt(0).requestFocus();
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_END:
+                if (handleKeyEvent) {
+                    // Select the last icon on this page
+                    parent.getChildAt(widgetCount - 1).requestFocus();
+                }
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Handles key events in the tab widget.
+     */
+    static boolean handleTabKeyEvent(AccessibleTabView v, int keyCode, KeyEvent e) {
+        if (!LauncherApplication.isScreenLarge()) return false;
+
+        final FocusOnlyTabWidget parent = (FocusOnlyTabWidget) v.getParent();
+        final TabHost tabHost = findTabHostParent(parent);
+        final ViewGroup contents = (ViewGroup)
+                tabHost.findViewById(com.android.internal.R.id.tabcontent);
+        final int tabCount = parent.getTabCount();
+        final int tabIndex = parent.getChildTabIndex(v);
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous tab
+                    if (tabIndex > 0) {
+                        parent.getChildTabViewAt(tabIndex - 1).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next tab, or if the last tab has a focus right id, select that
+                    if (tabIndex < (tabCount - 1)) {
+                        parent.getChildTabViewAt(tabIndex + 1).requestFocus();
+                    } else {
+                        if (v.getNextFocusRightId() != View.NO_ID) {
+                            tabHost.findViewById(v.getNextFocusRightId()).requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                // Do nothing
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the content view
+                    contents.requestFocus();
+                }
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Handles key events in the workspace button bar.
+     */
+    static boolean handleButtonBarButtonKeyEvent(View v, int keyCode, KeyEvent e) {
+        if (!LauncherApplication.isScreenLarge()) return false;
+
+        final ViewGroup parent = (ViewGroup) v.getParent();
+        final ViewGroup launcher = (ViewGroup) parent.getParent();
+        final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
+        final int buttonIndex = parent.indexOfChild(v);
+        final int buttonCount = parent.getChildCount();
+        final int pageIndex = workspace.getCurrentPage();
+        final int pageCount = workspace.getChildCount();
+        final int firstButtonIndex = parent.indexOfChild(parent.findViewById(R.id.search_button));
+        final int lastButtonIndex = parent.indexOfChild(parent.findViewById(R.id.configure_button));
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous button, otherwise do nothing (since the button bar is
+                    // static)
+                    if (buttonIndex > firstButtonIndex) {
+                        int newButtonIndex = buttonIndex - 1;
+                        while (newButtonIndex >= firstButtonIndex) {
+                            View prev = parent.getChildAt(newButtonIndex);
+                            if (isVisible(prev) && prev.isFocusable()) {
+                                prev.requestFocus();
+                                break;
+                            }
+                            --newButtonIndex;
+                        }
+                    } else {
+                        if (pageIndex > 0) {
+                            // Snap to previous page and clear focus
+                            workspace.snapToPage(pageIndex - 1);
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next button, otherwise do nothing (since the button bar is
+                    // static)
+                    if (buttonIndex < lastButtonIndex) {
+                        int newButtonIndex = buttonIndex + 1;
+                        while (newButtonIndex <= lastButtonIndex) {
+                            View next = parent.getChildAt(newButtonIndex);
+                            if (isVisible(next) && next.isFocusable()) {
+                                next.requestFocus();
+                                break;
+                            }
+                            ++newButtonIndex;
+                        }
+                    } else {
+                        if (pageIndex < (pageCount - 1)) {
+                            // Snap to next page and clear focus
+                            workspace.snapToPage(pageIndex + 1);
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                // Do nothing
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the first bubble text view in the current page of the workspace
+                    final CellLayout layout = (CellLayout) workspace.getChildAt(pageIndex);
+                    final CellLayoutChildren children = layout.getChildrenLayout();
+                    final View newIcon = getBubbleTextViewInDirection(layout, children, -1, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    } else {
+                        workspace.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Handles key events in the prev/next indicators.
+     */
+    static boolean handleIndicatorButtonKeyEvent(View v, int keyCode, KeyEvent e) {
+        final ViewGroup launcher = (ViewGroup) v.getParent();
+        final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
+        final ViewGroup hotseat = (ViewGroup) launcher.findViewById(R.id.all_apps_button_cluster);
+        final View previousIndicator = launcher.findViewById(R.id.previous_screen);
+        final View nextIndicator = launcher.findViewById(R.id.next_screen);
+        final int pageIndex = workspace.getCurrentPage();
+        final int pageCount = workspace.getChildCount();
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    if (v == previousIndicator) {
+                        if (pageIndex > 0) {
+                            // Snap to previous page and clear focus
+                            workspace.snapToPage(pageIndex - 1);
+                        }
+                    } else if (v == nextIndicator) {
+                        // Select the last button in the hot seat
+                        hotseat.getChildAt(hotseat.getChildCount() - 1).requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    if (v == previousIndicator) {
+                        // Select the first button in the hot seat
+                        hotseat.getChildAt(0).requestFocus();
+                    } else if (v == nextIndicator) {
+                        if (pageIndex < (pageCount - 1)) {
+                            // Snap to next page and clear focus
+                            workspace.snapToPage(pageIndex + 1);
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (handleKeyEvent) {
+                    // Select the first bubble text view in the current page of the workspace
+                    final CellLayout layout = (CellLayout) workspace.getChildAt(pageIndex);
+                    final CellLayoutChildren children = layout.getChildrenLayout();
+                    final View newIcon = getBubbleTextViewInDirection(layout, children, -1, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    } else {
+                        workspace.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                // Do nothing
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Handles key events in the workspace dock (bottom of the screen).
+     */
+    static boolean handleDockButtonKeyEvent(View v, int keyCode, KeyEvent e, int orientation) {
+        final ViewGroup parent = (ViewGroup) v.getParent();
+        final ViewGroup launcher = (ViewGroup) parent.getParent();
+        final Workspace workspace = (Workspace) launcher.findViewById(R.id.workspace);
+        final int buttonIndex = parent.indexOfChild(v);
+        final int buttonCount = parent.getChildCount();
+        final int pageIndex = workspace.getCurrentPage();
+        final int pageCount = workspace.getChildCount();
+        final View previousIndicator = launcher.findViewById(R.id.previous_screen);
+        final View nextIndicator = launcher.findViewById(R.id.next_screen);
+
+        // NOTE: currently we don't special case for the phone UI in different
+        // orientations, even though the dock is on the side in landscape mode.  This
+        // is to ensure that accessibility consistency is maintained across rotations.
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+
+                    // Select the previous button, otherwise select the previous page indicator
+                    if (buttonIndex > 0) {
+                        parent.getChildAt(buttonIndex - 1).requestFocus();
+                    } else {
+                        previousIndicator.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next button, otherwise select the next page indicator
+                    if (buttonIndex < (buttonCount - 1)) {
+                        parent.getChildAt(buttonIndex + 1).requestFocus();
+                    } else {
+                        nextIndicator.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (handleKeyEvent) {
+                    // Select the first bubble text view in the current page of the workspace
+                    final CellLayout layout = (CellLayout) workspace.getChildAt(pageIndex);
+                    final CellLayoutChildren children = layout.getChildrenLayout();
+                    final View newIcon = getBubbleTextViewInDirection(layout, children, -1, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    } else {
+                        workspace.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                // Do nothing
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+
+    /**
+     * Private helper method to get the CellLayoutChildren given a CellLayout index.
+     */
+    private static CellLayoutChildren getCellLayoutChildrenForIndex(ViewGroup container, int i) {
+        ViewGroup parent = (ViewGroup) container.getChildAt(i);
+        return (CellLayoutChildren) parent.getChildAt(0);
+    }
+
+    /**
+     * Private helper method to sort all the CellLayout children in order of their (x,y) spatially
+     * from top left to bottom right.
+     */
+    private static ArrayList<View> getCellLayoutChildrenSortedSpatially(CellLayout layout,
+            ViewGroup parent) {
+        // First we order each the CellLayout children by their x,y coordinates
+        final int cellCountX = layout.getCountX();
+        final int count = parent.getChildCount();
+        ArrayList<View> views = new ArrayList<View>();
+        for (int j = 0; j < count; ++j) {
+            views.add(parent.getChildAt(j));
+        }
+        Collections.sort(views, new Comparator<View>() {
+            @Override
+            public int compare(View lhs, View rhs) {
+                CellLayout.LayoutParams llp = (CellLayout.LayoutParams) lhs.getLayoutParams();
+                CellLayout.LayoutParams rlp = (CellLayout.LayoutParams) rhs.getLayoutParams();
+                int lvIndex = (llp.cellY * cellCountX) + llp.cellX;
+                int rvIndex = (rlp.cellY * cellCountX) + rlp.cellX;
+                return lvIndex - rvIndex;
+            }
+        });
+        return views;
+    }
+    /**
+     * Private helper method to find the index of the next BubbleTextView in the delta direction.
+     * @param delta either -1 or 1 depending on the direction we want to search
+     */
+    private static View findIndexOfBubbleTextView(ArrayList<View> views, int i, int delta) {
+        // Then we find the next BubbleTextView offset by delta from i
+        final int count = views.size();
+        int newI = i + delta;
+        while (0 <= newI && newI < count) {
+            View newV = views.get(newI);
+            if (newV instanceof BubbleTextView) {
+                return newV;
+            }
+            newI += delta;
+        }
+        return null;
+    }
+    private static View getBubbleTextViewInDirection(CellLayout layout, ViewGroup parent, int i,
+            int delta) {
+        final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+        return findIndexOfBubbleTextView(views, i, delta);
+    }
+    private static View getBubbleTextViewInDirection(CellLayout layout, ViewGroup parent, View v,
+            int delta) {
+        final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+        return findIndexOfBubbleTextView(views, views.indexOf(v), delta);
+    }
+    /**
+     * Private helper method to find the next closest BubbleTextView in the delta direction on the
+     * next line.
+     * @param delta either -1 or 1 depending on the line and direction we want to search
+     */
+    private static View getClosestBubbleTextViewOnLine(CellLayout layout, ViewGroup parent, View v,
+            int lineDelta) {
+        final ArrayList<View> views = getCellLayoutChildrenSortedSpatially(layout, parent);
+        final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
+        final int cellCountX = layout.getCountX();
+        final int cellCountY = layout.getCountY();
+        final int row = lp.cellY;
+        final int newRow = row + lineDelta;
+        if (0 <= newRow && newRow < cellCountY) {
+            float closestDistance = Float.MAX_VALUE;
+            int closestIndex = -1;
+            int index = views.indexOf(v);
+            int endIndex = (lineDelta < 0) ? -1 : views.size();
+            while (index != endIndex) {
+                View newV = views.get(index);
+                CellLayout.LayoutParams tmpLp = (CellLayout.LayoutParams) newV.getLayoutParams();
+                boolean satisfiesRow = (lineDelta < 0) ? (tmpLp.cellY < row) : (tmpLp.cellY > row);
+                if (satisfiesRow && newV instanceof BubbleTextView) {
+                    float tmpDistance = (float) Math.sqrt(Math.pow(tmpLp.cellX - lp.cellX, 2) +
+                            Math.pow(tmpLp.cellY - lp.cellY, 2));
+                    if (tmpDistance < closestDistance) {
+                        closestIndex = index;
+                        closestDistance = tmpDistance;
+                    }
+                }
+                if (index <= endIndex) {
+                    ++index;
+                } else {
+                    --index;
+                }
+            }
+            if (closestIndex > -1) {
+                return views.get(closestIndex);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Handles key events in a Workspace containing BubbleTextView.
+     */
+    static boolean handleBubbleTextViewKeyEvent(BubbleTextView v, int keyCode, KeyEvent e) {
+        CellLayoutChildren parent = (CellLayoutChildren) v.getParent();
+        final CellLayout layout = (CellLayout) parent.getParent();
+        final Workspace workspace = (Workspace) layout.getParent();
+        final ViewGroup launcher = (ViewGroup) workspace.getParent();
+        final ViewGroup tabs = (ViewGroup) launcher.findViewById(R.id.all_apps_button_cluster);
+        int iconIndex = parent.indexOfChild(v);
+        int iconCount = parent.getChildCount();
+        int pageIndex = workspace.indexOfChild(layout);
+        int pageCount = workspace.getChildCount();
+
+        final int action = e.getAction();
+        final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
+        boolean wasHandled = false;
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                if (handleKeyEvent) {
+                    // Select the previous icon or the last icon on the previous page if possible
+                    View newIcon = getBubbleTextViewInDirection(layout, parent, v, -1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    } else {
+                        if (pageIndex > 0) {
+                            parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+                            newIcon = getBubbleTextViewInDirection(layout, parent,
+                                    parent.getChildCount(), -1);
+                            if (newIcon != null) {
+                                newIcon.requestFocus();
+                            } else {
+                                // Snap to the previous page
+                                workspace.snapToPage(pageIndex - 1);
+                            }
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                if (handleKeyEvent) {
+                    // Select the next icon or the first icon on the next page if possible
+                    View newIcon = getBubbleTextViewInDirection(layout, parent, v, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    } else {
+                        if (pageIndex < (pageCount - 1)) {
+                            parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
+                            newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+                            if (newIcon != null) {
+                                newIcon.requestFocus();
+                            } else {
+                                // Snap to the next page
+                                workspace.snapToPage(pageIndex + 1);
+                            }
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_DPAD_UP:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the previous line, otherwise select the tab bar
+                    View newIcon = getClosestBubbleTextViewOnLine(layout, parent, v, -1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                        wasHandled = true;
+                    } else {
+                        tabs.requestFocus();
+                    }
+                }
+                break;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                if (handleKeyEvent) {
+                    // Select the closest icon in the next line, otherwise select the tab bar
+                    View newIcon = getClosestBubbleTextViewOnLine(layout, parent, v, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                        wasHandled = true;
+                    }
+                }
+                break;
+            case KeyEvent.KEYCODE_PAGE_UP:
+                if (handleKeyEvent) {
+                    // Select the first icon on the previous page or the first icon on this page
+                    // if there is no previous page
+                    if (pageIndex > 0) {
+                        parent = getCellLayoutChildrenForIndex(workspace, pageIndex - 1);
+                        View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+                        if (newIcon != null) {
+                            newIcon.requestFocus();
+                        } else {
+                            // Snap to the previous page
+                            workspace.snapToPage(pageIndex - 1);
+                        }
+                    } else {
+                        View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+                        if (newIcon != null) {
+                            newIcon.requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_PAGE_DOWN:
+                if (handleKeyEvent) {
+                    // Select the first icon on the next page or the last icon on this page
+                    // if there is no previous page
+                    if (pageIndex < (pageCount - 1)) {
+                        parent = getCellLayoutChildrenForIndex(workspace, pageIndex + 1);
+                        View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+                        if (newIcon != null) {
+                            newIcon.requestFocus();
+                        } else {
+                            // Snap to the next page
+                            workspace.snapToPage(pageIndex + 1);
+                        }
+                    } else {
+                        View newIcon = getBubbleTextViewInDirection(layout, parent,
+                                parent.getChildCount(), -1);
+                        if (newIcon != null) {
+                            newIcon.requestFocus();
+                        }
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_HOME:
+                if (handleKeyEvent) {
+                    // Select the first icon on this page
+                    View newIcon = getBubbleTextViewInDirection(layout, parent, -1, 1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            case KeyEvent.KEYCODE_MOVE_END:
+                if (handleKeyEvent) {
+                    // Select the last icon on this page
+                    View newIcon = getBubbleTextViewInDirection(layout, parent,
+                            parent.getChildCount(), -1);
+                    if (newIcon != null) {
+                        newIcon.requestFocus();
+                    }
+                }
+                wasHandled = true;
+                break;
+            default: break;
+        }
+        return wasHandled;
+    }
+}
diff --git a/src/com/android/launcher2/FocusOnlyTabWidget.java b/src/com/android/launcher2/FocusOnlyTabWidget.java
new file mode 100644
index 0000000..8e9f58c
--- /dev/null
+++ b/src/com/android/launcher2/FocusOnlyTabWidget.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TabWidget;
+
+public class FocusOnlyTabWidget extends TabWidget {
+    public FocusOnlyTabWidget(Context context) {
+        super(context);
+    }
+
+    public FocusOnlyTabWidget(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public FocusOnlyTabWidget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public View getSelectedTab() {
+        final int count = getTabCount();
+        for (int i = 0; i < count; ++i) {
+            View v = getChildTabViewAt(i);
+            if (v.isSelected()) {
+                return v;
+            }
+        }
+        return null;
+    }
+
+    public int getChildTabIndex(View v) {
+        final int tabCount = getTabCount();
+        for (int i = 0; i < tabCount; ++i) {
+            if (getChildTabViewAt(i) == v) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    public void setCurrentTabToFocusedTab() {
+        View tab = null;
+        int index = -1;
+        final int count = getTabCount();
+        for (int i = 0; i < count; ++i) {
+            View v = getChildTabViewAt(i);
+            if (v.hasFocus()) {
+                tab = v;
+                index = i;
+                break;
+            }
+        }
+        if (index > -1) {
+            super.setCurrentTab(index);
+            super.onFocusChange(tab, true);
+        }
+    }
+    public void superOnFocusChange(View v, boolean hasFocus) {
+        super.onFocusChange(v, hasFocus);
+    }
+
+    @Override
+    public void onFocusChange(android.view.View v, boolean hasFocus) {
+        if (v == this && hasFocus && getTabCount() > 0) {
+            getSelectedTab().requestFocus();
+            return;
+        }
+    }
+}
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index cb450b9..0470e41 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -16,34 +16,42 @@
 
 package com.android.launcher2;
 
+import java.util.ArrayList;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.widget.AbsListView;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
 import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.Button;
 import android.widget.LinearLayout;
+import android.widget.TextView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.AdapterView.OnItemLongClickListener;
 
 import com.android.launcher.R;
+import com.android.launcher2.FolderInfo.FolderListener;
 
 /**
  * Represents a set of icons chosen by the user or generated by the system.
  */
 public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener,
-        OnItemClickListener, OnClickListener, View.OnLongClickListener {
+        OnItemClickListener, OnClickListener, View.OnLongClickListener, DropTarget, FolderListener {
 
-    protected AbsListView mContent;
     protected DragController mDragController;
-    
+
     protected Launcher mLauncher;
 
-    protected Button mCloseButton;
-    
     protected FolderInfo mInfo;
     
     /**
@@ -51,6 +59,30 @@
      */
     protected ShortcutInfo mDragItem;
 
+    private static final String TAG = "Launcher.Folder";
+
+    static final int STATE_NONE = -1;
+    static final int STATE_SMALL = 0;
+    static final int STATE_ANIMATING = 1;
+    static final int STATE_OPEN = 2;
+
+    private int mExpandDuration;
+    protected CellLayout mContent;
+    private final LayoutInflater mInflater;
+    private final IconCache mIconCache;
+    private int mState = STATE_NONE;
+    private int[] mDragItemPosition = new int[2];
+    private static final int FULL_GROW = 0;
+    private static final int PARTIAL_GROW = 1;
+    private int mMode = PARTIAL_GROW;
+    private boolean mRearrangeOnClose = false;
+    private FolderIcon mFolderIcon;
+    private int mMaxCountX;
+    private int mMaxCountY;
+    private Rect mNewSize = new Rect();
+    private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
+    boolean mItemsInvalidated = false;
+
     /**
      * Used to inflate the Workspace from XML.
      *
@@ -60,21 +92,22 @@
     public Folder(Context context, AttributeSet attrs) {
         super(context, attrs);
         setAlwaysDrawnWithCacheEnabled(false);
+        mInflater = LayoutInflater.from(context);
+        mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
+        mExpandDuration = getResources().getInteger(R.integer.config_folderAnimDuration);
+
+        mMaxCountX = LauncherModel.getCellCountX() - 1;
+        mMaxCountY = LauncherModel.getCellCountY() - 1;
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-
-        mContent = (AbsListView) findViewById(R.id.folder_content);
-        mContent.setOnItemClickListener(this);
-        mContent.setOnItemLongClickListener(this);
-        
-        mCloseButton = (Button) findViewById(R.id.folder_close);
-        mCloseButton.setOnClickListener(this);
-        mCloseButton.setOnLongClickListener(this);
+        mContent = (CellLayout) findViewById(R.id.folder_content);
+        mContent.setGridSize(0, 0);
+        mContent.enableHardwareLayers();
     }
-    
+
     public void onItemClick(AdapterView parent, View v, int position, long id) {
         ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
         int[] pos = new int[2];
@@ -85,12 +118,47 @@
     }
 
     public void onClick(View v) {
-        mLauncher.closeFolder(this);
+        Object tag = v.getTag();
+        if (tag instanceof ShortcutInfo) {
+            // refactor this code from Folder
+            ShortcutInfo item = (ShortcutInfo) tag;
+            int[] pos = new int[2];
+            v.getLocationOnScreen(pos);
+            item.intent.setSourceBounds(new Rect(pos[0], pos[1],
+                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));
+            mLauncher.startActivitySafely(item.intent, item);
+        }
     }
 
     public boolean onLongClick(View v) {
-        mLauncher.closeFolder(this);
-        mLauncher.showRenameDialog(mInfo);
+        Object tag = v.getTag();
+        if (tag instanceof ShortcutInfo) {
+            mLauncher.closeFolder(this);
+
+            ShortcutInfo item = (ShortcutInfo) tag;
+            if (!v.isInTouchMode()) {
+                return false;
+            }
+
+            mLauncher.getWorkspace().onDragStartedWithItem(v);
+            mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
+            mDragItemPosition[0] = item.cellX;
+            mDragItemPosition[1] = item.cellY;
+            mInfo.remove(item);
+
+            mDragItem = item;
+        } else {
+            mLauncher.closeFolder(this);
+            mLauncher.showRenameDialog(mInfo);
+        }
+        return true;
+    }
+
+    /**
+     * We need to handle touch events to prevent them from falling through to the workspace below.
+     */
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
         return true;
     }
 
@@ -108,37 +176,21 @@
         return true;
     }
 
-    @Override
     public void setDragController(DragController dragController) {
         mDragController = dragController;
     }
 
-    @Override
-    public void onDropCompleted(View target, boolean success) {
-    }
-
-    @Override
     public void onDragViewVisible() {
     }
 
-    /**
-     * Sets the adapter used to populate the content area. The adapter must only
-     * contains ShortcutInfo items.
-     *
-     * @param adapter The list of applications to display in the folder.
-     */
-    void setContentAdapter(BaseAdapter adapter) {
-        mContent.setAdapter(adapter);
-    }
-
-    void notifyDataSetChanged() {
-        ((BaseAdapter) mContent.getAdapter()).notifyDataSetChanged();
-    }
-
     void setLauncher(Launcher launcher) {
         mLauncher = launcher;
     }
-    
+
+    void setFolderIcon(FolderIcon icon) {
+        mFolderIcon = icon;
+    }
+
     /**
      * @return the FolderInfo object associated with this folder
      */
@@ -146,10 +198,12 @@
         return mInfo;
     }
 
-    // When the folder opens, we need to refresh the GridView's selection by
-    // forcing a layout
     void onOpen() {
+        // When the folder opens, we need to refresh the GridView's selection by
+        // forcing a layout
+        // TODO: find out if this is still necessary
         mContent.requestLayout();
+        requestFocus();
     }
 
     void onClose() {
@@ -159,6 +213,413 @@
 
     void bind(FolderInfo info) {
         mInfo = info;
-        mCloseButton.setText(info.title);
+        ArrayList<ShortcutInfo> children = info.contents;
+        setupContentForNumItems(children.size());
+        for (int i = 0; i < children.size(); i++) {
+            ShortcutInfo child = (ShortcutInfo) children.get(i);
+            createAndAddShortcut(child);
+        }
+        mItemsInvalidated = true;
+        mInfo.addListener(this);
+    }
+
+    /**
+     * Creates a new UserFolder, inflated from R.layout.user_folder.
+     *
+     * @param context The application's context.
+     *
+     * @return A new UserFolder.
+     */
+    static Folder fromXml(Context context) {
+        return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
+    }
+
+    /**
+     * This method is intended to make the UserFolder to be visually identical in size and position
+     * to its associated FolderIcon. This allows for a seamless transition into the expanded state.
+     */
+    private void positionAndSizeAsIcon() {
+        if (!(getParent() instanceof CellLayoutChildren)) return;
+
+        CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+        if (mMode == PARTIAL_GROW) {
+            setScaleX(0.8f);
+            setScaleY(0.8f);
+            setAlpha(0f);
+        } else {
+            lp.width = iconLp.width;
+            lp.height = iconLp.height;
+            lp.x = iconLp.x;
+            lp.y = iconLp.y;
+            mContent.setAlpha(0);
+        }
+        mState = STATE_SMALL;
+    }
+
+    public void animateOpen() {
+        if (mState != STATE_SMALL) {
+            positionAndSizeAsIcon();
+        }
+        if (!(getParent() instanceof CellLayoutChildren)) return;
+
+        ObjectAnimator oa;
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+        centerAboutIcon();
+        if (mMode == PARTIAL_GROW) {
+            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
+            PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
+            PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
+            oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+        } else {
+            PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", mNewSize.width());
+            PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", mNewSize.height());
+            PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", mNewSize.left);
+            PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", mNewSize.top);
+            oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
+            oa.addUpdateListener(new AnimatorUpdateListener() {
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    requestLayout();
+                }
+            });
+
+            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
+            ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
+            alphaOa.setDuration(mExpandDuration);
+            alphaOa.setInterpolator(new AccelerateInterpolator(2.0f));
+            alphaOa.start();
+        }
+
+        oa.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mState = STATE_ANIMATING;
+            }
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mState = STATE_OPEN;
+            }
+        });
+        oa.setDuration(mExpandDuration);
+        oa.start();
+    }
+
+    public void animateClosed() {
+        if (!(getParent() instanceof CellLayoutChildren)) return;
+
+        CellLayoutChildren clc = (CellLayoutChildren) getParent();
+        final CellLayout cellLayout = (CellLayout) clc.getParent();
+        ObjectAnimator oa;
+
+        if (mMode == PARTIAL_GROW) {
+            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
+            PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
+            PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
+            oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
+        } else {
+            CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
+            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+            PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", iconLp.width);
+            PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", iconLp.height);
+            PropertyValuesHolder x = PropertyValuesHolder.ofInt("x",iconLp.x);
+            PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", iconLp.y);
+            oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
+            oa.addUpdateListener(new AnimatorUpdateListener() {
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    requestLayout();
+                }
+            });
+
+            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
+            ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
+            alphaOa.setDuration(mExpandDuration);
+            alphaOa.setInterpolator(new DecelerateInterpolator(2.0f));
+            alphaOa.start();
+        }
+
+        oa.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                onCloseComplete();
+                cellLayout.removeViewWithoutMarkingCells(Folder.this);
+                mState = STATE_SMALL;
+            }
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mState = STATE_ANIMATING;
+            }
+        });
+        oa.setDuration(mExpandDuration);
+        oa.start();
+    }
+
+    void notifyDataSetChanged() {
+        // recreate all the children if the data set changes under us. We may want to do this more
+        // intelligently (ie just removing the views that should no longer exist)
+        mContent.removeAllViewsInLayout();
+        bind(mInfo);
+    }
+
+    public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
+            DragView dragView, Object dragInfo) {
+        final ItemInfo item = (ItemInfo) dragInfo;
+        final int itemType = item.itemType;
+        return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+                    itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
+                    !isFull());
+    }
+
+    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
+            DragView dragView, Object dragInfo) {
+        ShortcutInfo item;
+        if (dragInfo instanceof ApplicationInfo) {
+            // Came from all apps -- make a copy
+            item = ((ApplicationInfo)dragInfo).makeShortcut();
+            item.spanX = 1;
+            item.spanY = 1;
+        } else {
+            item = (ShortcutInfo)dragInfo;
+        }
+        mInfo.add(item);
+        LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
+    }
+
+    protected boolean findAndSetEmptyCells(ShortcutInfo item) {
+        int[] emptyCell = new int[2];
+        if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
+            item.cellX = emptyCell[0];
+            item.cellY = emptyCell[1];
+            LauncherModel.addOrMoveItemInDatabase(
+                    mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    protected void createAndAddShortcut(ShortcutInfo item) {
+        final TextView textView =
+            (TextView) mInflater.inflate(R.layout.application_boxed, this, false);
+        textView.setCompoundDrawablesWithIntrinsicBounds(null,
+                new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
+        textView.setText(item.title);
+        textView.setTag(item);
+
+        textView.setOnClickListener(this);
+        textView.setOnLongClickListener(this);
+
+        CellLayout.LayoutParams lp =
+            new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
+        boolean insert = false;
+        mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
+    }
+
+    public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
+            DragView dragView, Object dragInfo) {
+        mContent.onDragEnter();
+    }
+
+    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
+            DragView dragView, Object dragInfo) {
+        float[] r = mapPointFromScreenToContent(x, y, null);
+        mContent.visualizeDropLocation(null, null, (int) r[0], (int) r[1], 1, 1);
+    }
+
+    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
+            DragView dragView, Object dragInfo) {
+        mContent.onDragExit();
+    }
+
+    public float[] mapPointFromScreenToContent(int x, int y, float[] r) {
+        if (r == null) {
+            r = new float[2];
+        }
+
+        int[] screenLocation = new int[2];
+        mContent.getLocationOnScreen(screenLocation);
+
+        r[0] = x - screenLocation[0];
+        r[1] = y - screenLocation[1];
+        return r;
+    }
+
+    public void onDropCompleted(View target, Object dragInfo, boolean success) {
+    }
+
+    public boolean isDropEnabled() {
+        return true;
+    }
+
+    public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
+            DragView dragView, Object dragInfo) {
+        return null;
+    }
+
+    private void setupContentDimension(int count) {
+        ArrayList<View> list = getItemsInReadingOrder();
+
+        int countX = mContent.getCountX();
+        int countY = mContent.getCountY();
+        boolean done = false;
+
+        while (!done) {
+            int oldCountX = countX;
+            int oldCountY = countY;
+            if (countX * countY < count) {
+                // Current grid is too small, expand it
+                if (countX <= countY && countX < mMaxCountX) {
+                    countX++;
+                } else if (countY < mMaxCountY) {
+                    countY++;
+                }
+                if (countY == 0) countY++;
+            } else if ((countY - 1) * countX >= count && countY >= countX) {
+                countY = Math.max(0, countY - 1);
+            } else if ((countX - 1) * countY >= count) {
+                countX = Math.max(0, countX - 1);
+            }
+            done = countX == oldCountX && countY == oldCountY;
+        }
+        mContent.setGridSize(countX, countY);
+        arrangeChildren(list);
+    }
+
+    public boolean isFull() {
+        return getItemCount() >= mMaxCountX * mMaxCountY;
+    }
+
+    private void centerAboutIcon() {
+        CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams();
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+        int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
+        int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight();
+
+        int centerX = iconLp.x + iconLp.width / 2;
+        int centerY = iconLp.y + iconLp.height / 2;
+        int centeredLeft = centerX - width / 2;
+        int centeredTop = centerY - height / 2;
+
+        CellLayoutChildren clc = (CellLayoutChildren) getParent();
+        int parentWidth = 0;
+        int parentHeight = 0;
+        if (clc != null) {
+            parentWidth = clc.getMeasuredWidth();
+            parentHeight = clc.getMeasuredHeight();
+        }
+
+        int left = Math.min(Math.max(0, centeredLeft), parentWidth - width);
+        int top = Math.min(Math.max(0, centeredTop), parentHeight - height);
+
+        int folderPivotX = width / 2 + (centeredLeft - left);
+        int folderPivotY = height / 2 + (centeredTop - top);
+        setPivotX(folderPivotX);
+        setPivotY(folderPivotY);
+        int folderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
+                (1.0f * folderPivotX / width));
+        int folderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
+                (1.0f * folderPivotY / height));
+        mFolderIcon.setPivotX(folderIconPivotX);
+        mFolderIcon.setPivotY(folderIconPivotY);
+
+        if (mMode == PARTIAL_GROW) {
+            lp.width = width;
+            lp.height = height;
+            lp.x = left;
+            lp.y = top;
+        } else {
+            mNewSize.set(left, top, left + width, top + height);
+        }
+    }
+
+    private void setupContentForNumItems(int count) {
+        setupContentDimension(count);
+
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+        if (lp == null) {
+            lp = new CellLayout.LayoutParams(0, 0, -1, -1);
+            lp.isLockedToGrid = false;
+            setLayoutParams(lp);
+        }
+        centerAboutIcon();
+    }
+
+    private void arrangeChildren(ArrayList<View> list) {
+        int[] vacant = new int[2];
+        if (list == null) {
+            list = getItemsInReadingOrder();
+        }
+        mContent.removeAllViews();
+
+        for (int i = 0; i < list.size(); i++) {
+            View v = list.get(i);
+            mContent.getVacantCell(vacant, 1, 1);
+            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
+            lp.cellX = vacant[0];
+            lp.cellY = vacant[1];
+            ItemInfo info = (ItemInfo) v.getTag();
+            info.cellX = vacant[0];
+            info.cellY = vacant[1];
+            boolean insert = false;
+            mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
+            LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0,
+                    info.cellX, info.cellY);
+        }
+        mItemsInvalidated = true;
+    }
+
+    public void onAdd(ShortcutInfo item) {
+        mItemsInvalidated = true;
+        if (!findAndSetEmptyCells(item)) {
+            // The current layout is full, can we expand it?
+            setupContentForNumItems(getItemCount() + 1);
+            findAndSetEmptyCells(item);
+        }
+        createAndAddShortcut(item);
+    }
+
+    public int getItemCount() {
+        return mContent.getChildrenLayout().getChildCount();
+    }
+
+    public View getItemAt(int index) {
+        return mContent.getChildrenLayout().getChildAt(index);
+    }
+
+    private void onCloseComplete() {
+        if (mRearrangeOnClose) {
+            setupContentForNumItems(getItemCount());
+            mRearrangeOnClose = false;
+        }
+    }
+
+    public void onRemove(ShortcutInfo item) {
+        mItemsInvalidated = true;
+        View v = mContent.getChildAt(mDragItemPosition[0], mDragItemPosition[1]);
+        mContent.removeView(v);
+        if (mState == STATE_ANIMATING) {
+            mRearrangeOnClose = true;
+        } else {
+            setupContentForNumItems(getItemCount());
+        }
+    }
+
+    public ArrayList<View> getItemsInReadingOrder() {
+        if (mItemsInvalidated) {
+            mItemsInReadingOrder.clear();
+            for (int j = 0; j < mContent.getCountY(); j++) {
+                for (int i = 0; i < mContent.getCountX(); i++) {
+                    View v = mContent.getChildAt(i, j);
+                    if (v != null) {
+                        mItemsInReadingOrder.add(v);
+                    }
+                }
+            }
+            mItemsInvalidated = false;
+        }
+        return mItemsInReadingOrder;
     }
 }
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index dd83c78..2a5a5a0 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -16,23 +16,55 @@
 
 package com.android.launcher2;
 
+import java.util.ArrayList;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
+import android.view.View;
 import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.TextView;
 
 import com.android.launcher.R;
+import com.android.launcher2.FolderInfo.FolderListener;
 
 /**
  * An icon that can appear on in the workspace representing an {@link UserFolder}.
  */
-public class FolderIcon extends BubbleTextView implements DropTarget {
-    private UserFolderInfo mInfo;
+public class FolderIcon extends FrameLayout implements DropTarget, FolderListener {
     private Launcher mLauncher;
-    private Drawable mCloseIcon;
-    private Drawable mOpenIcon;
+    Folder mFolder;
+    FolderInfo mInfo;
+
+    private static final int NUM_ITEMS_IN_PREVIEW = 4;
+    private static final float ICON_ANGLE = 15f;
+    private static final int CONSUMPTION_ANIMATION_DURATION = 100;
+    private static final float INNER_RING_GROWTH_FACTOR = 0.1f;
+    private static final float OUTER_RING_BASELINE_SCALE = 0.7f;
+    private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
+    private static final float INNER_RING_BASELINE_SCALE = 1.0f;
+
+    public static Drawable sFolderOuterRingDrawable = null;
+    public static Drawable sFolderInnerRingDrawable = null;
+
+    private int mOriginalWidth = -1;
+    private int mOriginalHeight = -1;
+    private int mOriginalX = -1;
+    private int mOriginalY = -1;
+
+    private int mFolderLocX;
+    private int mFolderLocY;
+    private float mOuterRingScale;
+    private float mInnerRingScale;
 
     public FolderIcon(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -43,35 +75,61 @@
     }
 
     public boolean isDropEnabled() {
-        return !((Workspace)getParent().getParent()).isSmall();
+        final ViewGroup cellLayoutChildren = (ViewGroup) getParent();
+        final ViewGroup cellLayout = (ViewGroup) cellLayoutChildren.getParent();
+        final Workspace workspace = (Workspace) cellLayout.getParent();
+        return !workspace.isSmall();
     }
 
     static FolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
-            UserFolderInfo folderInfo, IconCache iconCache) {
+            FolderInfo folderInfo, IconCache iconCache) {
 
         FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false);
 
         final Resources resources = launcher.getResources();
-        Drawable d = iconCache.getFullResIcon(resources, R.drawable.ic_launcher_folder);
-        icon.mCloseIcon = d;
-        icon.mOpenIcon = iconCache.getFullResIcon(resources, R.drawable.ic_launcher_folder_open);
-        icon.setCompoundDrawablesWithIntrinsicBounds(null, d, null, null);
-        icon.setText(folderInfo.title);
+        Drawable d = iconCache.getFullResIcon(resources, R.drawable.portal_ring_inner_holo);
+        icon.setBackgroundDrawable(d);
         icon.setTag(folderInfo);
         icon.setOnClickListener(launcher);
         icon.mInfo = folderInfo;
         icon.mLauncher = launcher;
-        
+
+        Folder folder = Folder.fromXml(launcher);
+        folder.setDragController(launcher.getDragController());
+        folder.setLauncher(launcher);
+        folder.setFolderIcon(icon);
+        folder.bind(folderInfo);
+        icon.mFolder = folder;
+
+        folderInfo.addListener(icon);
+        if (sFolderOuterRingDrawable == null) {
+            sFolderOuterRingDrawable =
+                    launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo);
+        }
+
+        if (sFolderInnerRingDrawable == null) {
+            sFolderInnerRingDrawable =
+                    launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo);
+        }
         return icon;
     }
 
+    private boolean willAcceptItem(ItemInfo item) {
+        final int itemType = item.itemType;
+        return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+                itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
+                !mFolder.isFull() && item != mInfo);
+    }
+
     public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
             DragView dragView, Object dragInfo) {
         final ItemInfo item = (ItemInfo) dragInfo;
-        final int itemType = item.itemType;
-        return (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
-                itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)
-                && item.container != mInfo.id;
+        return willAcceptItem(item);
+    }
+
+    public void addItem(ShortcutInfo item) {
+        mInfo.add(item);
+        LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
     }
 
     public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
@@ -83,15 +141,84 @@
         } else {
             item = (ShortcutInfo)dragInfo;
         }
-        mInfo.add(item);
-        LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
+        item.cellX = -1;
+        item.cellY = -1;
+        addItem(item);
+    }
+
+    void saveState(CellLayout.LayoutParams lp) {
+        mOriginalWidth = lp.width;
+        mOriginalHeight = lp.height;
+        mOriginalX = lp.x;
+        mOriginalY = lp.y;
+    }
+
+    private void animateToAcceptState() {
+        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
+
+        ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
+        va.setDuration(CONSUMPTION_ANIMATION_DURATION);
+        va.addUpdateListener(new AnimatorUpdateListener() {
+            public void onAnimationUpdate(ValueAnimator animation) {
+                final float percent = (Float) animation.getAnimatedValue();
+                mOuterRingScale = OUTER_RING_BASELINE_SCALE + percent * OUTER_RING_GROWTH_FACTOR;
+                mInnerRingScale = INNER_RING_BASELINE_SCALE + percent * INNER_RING_GROWTH_FACTOR;
+                mLauncher.getWorkspace().invalidate();
+                invalidate();
+            }
+        });
+        va.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                // Instead of setting the background drawable to null, we set the color to
+                // transparent. Setting the background drawable to null results in onDraw
+                // not getting called.
+                setBackgroundColor(Color.TRANSPARENT);
+                requestLayout();
+            }
+        });
+        va.start();
+    }
+
+    private void animateToNaturalState() {
+        ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
+        va.setDuration(CONSUMPTION_ANIMATION_DURATION);
+        va.addUpdateListener(new AnimatorUpdateListener() {
+            public void onAnimationUpdate(ValueAnimator animation) {
+                final float percent = (Float) animation.getAnimatedValue();
+                mOuterRingScale = OUTER_RING_BASELINE_SCALE + OUTER_RING_GROWTH_FACTOR
+                        - percent * OUTER_RING_GROWTH_FACTOR;
+                mInnerRingScale = INNER_RING_BASELINE_SCALE + INNER_RING_GROWTH_FACTOR
+                        - percent * INNER_RING_GROWTH_FACTOR;
+                mLauncher.getWorkspace().invalidate();
+                invalidate();
+            }
+        });
+        va.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                setBackgroundDrawable(sFolderInnerRingDrawable);
+                mLauncher.getWorkspace().hideFolderAccept(FolderIcon.this);
+            }
+        });
+        va.start();
+    }
+
+    private void determineFolderLocationInWorkspace() {
+        int tvLocation[] = new int[2];
+        int wsLocation[] = new int[2];
+        getLocationOnScreen(tvLocation);
+        mLauncher.getWorkspace().getLocationOnScreen(wsLocation);
+        mFolderLocX = tvLocation[0] - wsLocation[0] + getMeasuredWidth() / 2;
+        mFolderLocY = tvLocation[1] - wsLocation[1] + getMeasuredHeight() / 2;
     }
 
     public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
             DragView dragView, Object dragInfo) {
-        if (acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
-            setCompoundDrawablesWithIntrinsicBounds(null, mOpenIcon, null, null);
-        }
+        if (!willAcceptItem((ItemInfo) dragInfo)) return;
+        determineFolderLocationInWorkspace();
+        mLauncher.getWorkspace().showFolderAccept(this);
+        animateToAcceptState();
     }
 
     public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
@@ -100,7 +227,8 @@
 
     public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
             DragView dragView, Object dragInfo) {
-        setCompoundDrawablesWithIntrinsicBounds(null, mCloseIcon, null, null);
+        if (!willAcceptItem((ItemInfo) dragInfo)) return;
+        animateToNaturalState();
     }
 
     @Override
@@ -108,4 +236,64 @@
             DragView dragView, Object dragInfo) {
         return null;
     }
+
+    public void getFolderLocation(int[] loc) {
+        loc[0] = mFolderLocX;
+        loc[1] = mFolderLocY;
+    }
+
+    public float getOuterRingScale() {
+        return mOuterRingScale;
+    }
+
+    public float getInnerRingScale() {
+        return mInnerRingScale;
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mFolder == null) return;
+        if (mFolder.getItemCount() == 0) return;
+
+        canvas.save();
+        TextView v = (TextView) mFolder.getItemAt(0);
+        Drawable d = v.getCompoundDrawables()[1];
+
+        if (mOriginalWidth < 0 || mOriginalHeight < 0) {
+            mOriginalWidth = getMeasuredWidth();
+            mOriginalHeight = getMeasuredHeight();
+        }
+
+        int xShift = (mOriginalWidth - d.getIntrinsicWidth()) / 2;
+        int yShift = (mOriginalHeight - d.getIntrinsicHeight()) / 2;
+        canvas.translate(xShift, yShift);
+
+        ArrayList<View> items = mFolder.getItemsInReadingOrder();
+        int firstItemIndex = Math.max(0, items.size() - NUM_ITEMS_IN_PREVIEW);
+        for (int i = firstItemIndex; i < items.size(); i++) {
+            v = (TextView) items.get(i);
+            d = v.getCompoundDrawables()[1];
+
+            canvas.translate(d.getIntrinsicWidth() / 2, d.getIntrinsicHeight() / 2);
+            canvas.rotate(i == firstItemIndex ? ICON_ANGLE : -ICON_ANGLE);
+            canvas.translate(-d.getIntrinsicWidth() / 2, -d.getIntrinsicHeight() / 2);
+
+            if (d != null) {
+                d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
+                d.draw(canvas);
+            }
+        }
+
+        canvas.restore();
+    }
+
+    public void onAdd(ShortcutInfo item) {
+        invalidate();
+        requestLayout();
+    }
+
+    public void onRemove(ShortcutInfo item) {
+        invalidate();
+        requestLayout();
+    }
 }
diff --git a/src/com/android/launcher2/FolderInfo.java b/src/com/android/launcher2/FolderInfo.java
index 8732690..12ed27c 100644
--- a/src/com/android/launcher2/FolderInfo.java
+++ b/src/com/android/launcher2/FolderInfo.java
@@ -16,12 +16,15 @@
 
 package com.android.launcher2;
 
+import java.util.ArrayList;
+
+import android.content.ContentValues;
 
 /**
  * Represents a folder containing shortcuts or apps.
  */
 class FolderInfo extends ItemInfo {
-    
+
     /**
      * Whether this folder has been opened
      */
@@ -31,4 +34,60 @@
      * The folder name.
      */
     CharSequence title;
+
+    /**
+     * The apps and shortcuts
+     */
+    ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
+
+    ArrayList<FolderListener> listeners = new ArrayList<FolderListener>();
+
+    FolderInfo() {
+        itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
+    }
+
+    /**
+     * Add an app or shortcut
+     *
+     * @param item
+     */
+    public void add(ShortcutInfo item) {
+        contents.add(item);
+        for (int i = 0; i < listeners.size(); i++) {
+            listeners.get(i).onAdd(item);
+        }
+    }
+
+    /**
+     * Remove an app or shortcut. Does not change the DB.
+     *
+     * @param item
+     */
+    public void remove(ShortcutInfo item) {
+        contents.remove(item);
+        for (int i = 0; i < listeners.size(); i++) {
+            listeners.get(i).onRemove(item);
+        }
+    }
+
+    @Override
+    void onAddToDatabase(ContentValues values) {
+        super.onAddToDatabase(values);
+        values.put(LauncherSettings.Favorites.TITLE, title.toString());
+    }
+
+    void addListener(FolderListener listener) {
+        listeners.add(listener);
+    }
+
+    void removeListener(FolderListener listener) {
+        if (listeners.contains(listener)) {
+            listeners.remove(listener);
+        }
+    }
+
+    interface FolderListener {
+        public void onAdd(ShortcutInfo item);
+        public void onRemove(ShortcutInfo item);
+    }
 }
diff --git a/src/com/android/launcher2/HolographicOutlineHelper.java b/src/com/android/launcher2/HolographicOutlineHelper.java
index 1efc123..80548fb 100644
--- a/src/com/android/launcher2/HolographicOutlineHelper.java
+++ b/src/com/android/launcher2/HolographicOutlineHelper.java
@@ -32,6 +32,7 @@
     private final Paint mAlphaClipPaint = new Paint();
 
     public static final int MAX_OUTER_BLUR_RADIUS;
+    public static final int MIN_OUTER_BLUR_RADIUS;
 
     private static final BlurMaskFilter sExtraThickOuterBlurMaskFilter;
     private static final BlurMaskFilter sThickOuterBlurMaskFilter;
@@ -48,6 +49,7 @@
     static {
         final float scale = LauncherApplication.getScreenDensity();
 
+        MIN_OUTER_BLUR_RADIUS = (int) (scale * 1.0f);
         MAX_OUTER_BLUR_RADIUS = (int) (scale * 12.0f);
 
         sExtraThickOuterBlurMaskFilter = new BlurMaskFilter(scale * 12.0f, BlurMaskFilter.Blur.OUTER);
diff --git a/src/com/android/launcher2/HolographicPagedViewIcon.java b/src/com/android/launcher2/HolographicPagedViewIcon.java
index 5e18169..7123e2a 100644
--- a/src/com/android/launcher2/HolographicPagedViewIcon.java
+++ b/src/com/android/launcher2/HolographicPagedViewIcon.java
@@ -41,7 +41,6 @@
     @Override
     protected void onDraw(Canvas canvas) {
         Bitmap overlay = mOriginalIcon.getHolographicOutline();
-
         if (overlay != null) {
             final int offset = getScrollX();
             final int compoundPaddingLeft = getCompoundPaddingLeft();
diff --git a/src/com/android/launcher2/IconCache.java b/src/com/android/launcher2/IconCache.java
index 2e47adc..7e37afe 100644
--- a/src/com/android/launcher2/IconCache.java
+++ b/src/com/android/launcher2/IconCache.java
@@ -54,7 +54,7 @@
         mContext = context;
         mPackageManager = context.getPackageManager();
         mBubble = new Utilities.BubbleText(context);
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
             mIconDpi = DisplayMetrics.DENSITY_HIGH;
         } else {
             mIconDpi = context.getResources().getDisplayMetrics().densityDpi;
@@ -68,11 +68,13 @@
                 com.android.internal.R.mipmap.sym_def_app_icon);
     }
 
-    public Drawable getFullResIcon(Resources resources, int iconId) {
+    public Drawable getFullResIcon(Resources resources, int iconId)
+            throws Resources.NotFoundException {
         return resources.getDrawableForDensity(iconId, mIconDpi);
     }
 
-    public Drawable getFullResIcon(ResolveInfo info, PackageManager packageManager) {
+    public Drawable getFullResIcon(ResolveInfo info, PackageManager packageManager)
+            throws Resources.NotFoundException {
         Resources resources;
         try {
             resources = packageManager.getResourcesForApplication(
@@ -174,8 +176,14 @@
             if (entry.title == null) {
                 entry.title = info.activityInfo.name;
             }
-            entry.icon = Utilities.createIconBitmap(
-                    getFullResIcon(info, mPackageManager), mContext);
+
+            Drawable icon;
+            try {
+                icon = getFullResIcon(info, mPackageManager);
+            } catch (Resources.NotFoundException e) {
+                icon = getFullResDefaultActivityIcon();
+            }
+            entry.icon = Utilities.createIconBitmap(icon, mContext);
         }
         return entry;
     }
diff --git a/src/com/android/launcher2/IconDropTarget.java b/src/com/android/launcher2/IconDropTarget.java
index fb5d0f0..4d018e6 100644
--- a/src/com/android/launcher2/IconDropTarget.java
+++ b/src/com/android/launcher2/IconDropTarget.java
@@ -126,7 +126,7 @@
     @Override
     public void getHitRect(Rect outRect) {
         super.getHitRect(outRect);
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
             outRect.top -= mDragPadding[0];
             outRect.right += mDragPadding[1];
             outRect.bottom += mDragPadding[2];
diff --git a/src/com/android/launcher2/ItemInfo.java b/src/com/android/launcher2/ItemInfo.java
index dc45750..3bb3b07 100644
--- a/src/com/android/launcher2/ItemInfo.java
+++ b/src/com/android/launcher2/ItemInfo.java
@@ -38,7 +38,7 @@
     /**
      * One of {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
      * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
-     * {@link LauncherSettings.Favorites#ITEM_TYPE_USER_FOLDER}, or
+     * {@link LauncherSettings.Favorites#ITEM_TYPE_FOLDER}, or
      * {@link LauncherSettings.Favorites#ITEM_TYPE_APPWIDGET}.
      */
     int itemType;
@@ -81,6 +81,11 @@
      */
     boolean isGesture = false;
 
+    /**
+     * The position of the item in a drag-and-drop operation.
+     */
+    int[] dropPos = null;
+
     ItemInfo() {
     }
 
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index df6ff36..9dfed69 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -17,10 +17,13 @@
 
 package com.android.launcher2;
 
-import com.android.common.Search;
-import com.android.launcher.R;
-import com.android.launcher2.CustomizePagedView.CustomizationType;
-import com.android.launcher2.Workspace.ShrinkState;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -66,10 +69,8 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Message;
-import android.os.Parcelable;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.provider.LiveFolders;
 import android.provider.Settings;
 import android.speech.RecognizerIntent;
 import android.text.Selection;
@@ -88,6 +89,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.View.OnClickListener;
 import android.view.View.OnLongClickListener;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.DecelerateInterpolator;
@@ -98,20 +100,12 @@
 import android.widget.LinearLayout;
 import android.widget.PopupWindow;
 import android.widget.TabHost;
-import android.widget.TabWidget;
 import android.widget.TextView;
 import android.widget.Toast;
-import android.widget.TabHost.OnTabChangeListener;
-import android.widget.TabHost.TabContentFactory;
 
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
+import com.android.common.Search;
+import com.android.launcher.R;
+import com.android.launcher2.Workspace.ShrinkState;
 
 /**
  * Default launcher application.
@@ -137,11 +131,9 @@
     private static final int MENU_SETTINGS = MENU_NOTIFICATIONS + 1;
 
     private static final int REQUEST_CREATE_SHORTCUT = 1;
-    private static final int REQUEST_CREATE_LIVE_FOLDER = 4;
     private static final int REQUEST_CREATE_APPWIDGET = 5;
     private static final int REQUEST_PICK_APPLICATION = 6;
     private static final int REQUEST_PICK_SHORTCUT = 7;
-    private static final int REQUEST_PICK_LIVE_FOLDER = 8;
     private static final int REQUEST_PICK_APPWIDGET = 9;
     private static final int REQUEST_PICK_WALLPAPER = 10;
 
@@ -160,7 +152,7 @@
     // Type: int
     private static final String RUNTIME_STATE = "launcher.state";
     // Type: long
-    private static final String RUNTIME_STATE_USER_FOLDERS = "launcher.user_folder";
+    private static final String RUNTIME_STATE_FOLDERS = "launcher.folder";
     // Type: int
     private static final String RUNTIME_STATE_PENDING_ADD_SCREEN = "launcher.add_screen";
     // Type: int
@@ -172,16 +164,10 @@
     // Type: long
     private static final String RUNTIME_STATE_PENDING_FOLDER_RENAME_ID = "launcher.rename_folder_id";
 
-    // tags for the customization tabs
-    private static final String WIDGETS_TAG = "widgets";
-    private static final String APPLICATIONS_TAG = "applications";
-    private static final String SHORTCUTS_TAG = "shortcuts";
-    private static final String WALLPAPERS_TAG = "wallpapers";
-
     private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon";
 
     /** The different states that Launcher can be in. */
-    private enum State { WORKSPACE, ALL_APPS, CUSTOMIZE, OVERVIEW,
+    private enum State { WORKSPACE, APPS_CUSTOMIZE, ALL_APPS, CUSTOMIZE,
         CUSTOMIZE_SPRING_LOADED, ALL_APPS_SPRING_LOADED };
     private State mState = State.WORKSPACE;
     private AnimatorSet mStateAnimation;
@@ -214,9 +200,16 @@
     private DeleteZone mDeleteZone;
     private HandleView mHandleView;
     private AllAppsView mAllAppsGrid;
-    private TabHost mHomeCustomizationDrawer;
+    private AppsCustomizeTabHost mAppsCustomizeTabHost;
+    private AppsCustomizePagedView mAppsCustomizeContent;
+    private CustomizeTrayTabHost mHomeCustomizationDrawer;
     private boolean mAutoAdvanceRunning = false;
 
+    private ViewGroup mButtonCluster;
+    private View mAllAppsButton;
+    private View mDivider;
+    private View mConfigureButton;
+
     private AllAppsPagedView mAllAppsPagedView = null;
     private CustomizePagedView mCustomizePagedView = null;
 
@@ -245,6 +238,7 @@
 
     private static HashMap<Long, FolderInfo> sFolders = new HashMap<Long, FolderInfo>();
 
+    // The "signpost" images along the bottom of the screen (only in some layouts)
     private ImageView mPreviousView;
     private ImageView mNextView;
 
@@ -274,17 +268,19 @@
     private static Drawable.ConstantState sVoiceSearchIcon;
     private static Drawable.ConstantState sAppMarketIcon;
 
-    private CustomizationType getCustomizeFilterForTabTag(String tag) {
-        if (tag.equals(WIDGETS_TAG)) {
-            return CustomizationType.WidgetCustomization;
-        } else if (tag.equals(APPLICATIONS_TAG)) {
-            return CustomizationType.ApplicationCustomization;
-        } else if (tag.equals(WALLPAPERS_TAG)) {
-            return CustomizePagedView.CustomizationType.WallpaperCustomization;
-        } else if (tag.equals(SHORTCUTS_TAG)) {
-            return CustomizePagedView.CustomizationType.ShortcutCustomization;
-        }
-        return CustomizationType.WidgetCustomization;
+    private DragLayer mDragLayer;
+
+    private BubbleTextView mWaitingForResume;
+
+    private static ArrayList<PendingAddArguments> sPendingAddList
+            = new ArrayList<PendingAddArguments>();
+
+    private static class PendingAddArguments {
+        int requestCode;
+        Intent intent;
+        int screen;
+        int cellX;
+        int cellY;
     }
 
     @Override
@@ -315,68 +311,11 @@
         loadHotseats();
         checkForLocaleChange();
         setContentView(R.layout.launcher);
-        mHomeCustomizationDrawer = (TabHost) findViewById(R.id.customization_drawer);
+        mHomeCustomizationDrawer = (CustomizeTrayTabHost) findViewById(R.id.customization_drawer);
         if (mHomeCustomizationDrawer != null) {
-            mHomeCustomizationDrawer.setup();
-
             // share the same customization workspace across all the tabs
-            mCustomizePagedView = (CustomizePagedView) mInflater.inflate(
-                    R.layout.customization_drawer, mHomeCustomizationDrawer, false);
-            TabContentFactory contentFactory = new TabContentFactory() {
-                public View createTabContent(String tag) {
-                    return mCustomizePagedView;
-                }
-            };
-
-
-            TextView tabView;
-            TabWidget tabWidget = (TabWidget)
-                    mHomeCustomizationDrawer.findViewById(com.android.internal.R.id.tabs);
-
-            tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
-            tabView.setText(getString(R.string.widgets_tab_label));
-            mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(WIDGETS_TAG)
-                    .setIndicator(tabView).setContent(contentFactory));
-            tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
-            tabView.setText(getString(R.string.applications_tab_label));
-            mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(APPLICATIONS_TAG)
-                    .setIndicator(tabView).setContent(contentFactory));
-            tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
-            tabView.setText(getString(R.string.wallpapers_tab_label));
-            mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(WALLPAPERS_TAG)
-                    .setIndicator(tabView).setContent(contentFactory));
-            tabView = (TextView) mInflater.inflate(R.layout.tab_widget_indicator, tabWidget, false);
-            tabView.setText(getString(R.string.shortcuts_tab_label));
-            mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(SHORTCUTS_TAG)
-                    .setIndicator(tabView).setContent(contentFactory));
-            mHomeCustomizationDrawer.setOnTabChangedListener(new OnTabChangeListener() {
-                public void onTabChanged(String tabId) {
-                    final CustomizePagedView.CustomizationType newType =
-                        getCustomizeFilterForTabTag(tabId);
-                    if (newType != mCustomizePagedView.getCustomizationFilter()) {
-                        // animate the changing of the tab content by fading pages in and out
-                        final Resources res = getResources();
-                        final int duration = res.getInteger(R.integer.config_tabTransitionTime);
-                        final float alpha = mCustomizePagedView.getAlpha();
-                        ValueAnimator alphaAnim = ObjectAnimator.ofFloat(mCustomizePagedView,
-                                "alpha", alpha, 0.0f);
-                        alphaAnim.setDuration(duration);
-                        alphaAnim.addListener(new AnimatorListenerAdapter() {
-                            @Override
-                            public void onAnimationEnd(Animator animation) {
-                                mCustomizePagedView.setCustomizationFilter(newType);
-
-                                final float alpha = mCustomizePagedView.getAlpha();
-                                ValueAnimator alphaAnim = ObjectAnimator.ofFloat(
-                                        mCustomizePagedView, "alpha", alpha, 1.0f);
-                                alphaAnim.setDuration(duration);
-                                alphaAnim.start();
-                            }
-                        });
-                        alphaAnim.start();
-                    }
-                }
-            });
+            mCustomizePagedView = (CustomizePagedView) findViewById(
+                    R.id.customization_drawer_tab_contents);
         }
         setupViews();
 
@@ -391,6 +330,9 @@
         if (mCustomizePagedView != null) {
             mCustomizePagedView.update();
         }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.onPackagesUpdated();
+        }
 
         if (PROFILE_STARTUP) {
             android.os.Debug.stopMethodTracing();
@@ -408,9 +350,12 @@
         registerReceiver(mCloseSystemDialogsReceiver, filter);
 
         // If we have a saved version of these external icons, we load them up immediately
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
+            if (sGlobalSearchIcon == null || sVoiceSearchIcon == null || sAppMarketIcon == null) {
+                updateIconsAffectedByPackageManagerChanges();
+            }
             if (sGlobalSearchIcon != null) {
-                updateGlobalSearchIcon(sGlobalSearchIcon);
+                 updateGlobalSearchIcon(sGlobalSearchIcon);
             }
             if (sVoiceSearchIcon != null) {
                 updateVoiceSearchIcon(sVoiceSearchIcon);
@@ -421,21 +366,6 @@
         }
     }
 
-    @Override
-    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-        super.dispatchPopulateAccessibilityEvent(event);
-
-        // we want to take over text population so it is context dependent
-        event.getText().clear();
-        if (mState == State.ALL_APPS) {
-            event.getText().add(getString(R.string.all_apps_button_label));
-        } else if (mState == State.WORKSPACE) {
-            event.getText().add(getString(R.string.all_apps_home_button_label));
-        }
-
-        return true;
-    }
-
     private void checkForLocaleChange() {
         if (sLocaleConfiguration == null) {
             new AsyncTask<Void, Void, LocaleConfiguration>() {
@@ -695,8 +625,32 @@
         }
     }
 
+    private void completeAdd(PendingAddArguments args) {
+        switch (args.requestCode) {
+            case REQUEST_PICK_APPLICATION:
+                completeAddApplication(args.intent, args.screen, args.cellX, args.cellY);
+                break;
+            case REQUEST_PICK_SHORTCUT:
+                processShortcut(args.intent);
+                break;
+            case REQUEST_CREATE_SHORTCUT:
+                completeAddShortcut(args.intent, args.screen, args.cellX, args.cellY);
+                break;
+            case REQUEST_PICK_APPWIDGET:
+                addAppWidgetFromPick(args.intent);
+                break;
+            case REQUEST_CREATE_APPWIDGET:
+                int appWidgetId = args.intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
+                completeAddAppWidget(appWidgetId, args.screen);
+                break;
+            case REQUEST_PICK_WALLPAPER:
+                // We just wanted the activity result here so we can clear mWaitingForResult
+                break;
+        }
+    }
+
     @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+    protected void onActivityResult(final int requestCode, int resultCode, final Intent data) {
         mWaitingForResult = false;
 
         // The pattern used here is that a user PICKs a specific application,
@@ -706,33 +660,18 @@
         // launch over to the Music app to actually CREATE_SHORTCUT.
 
         if (resultCode == RESULT_OK && mAddScreen != -1) {
-            switch (requestCode) {
-                case REQUEST_PICK_APPLICATION:
-                    completeAddApplication(
-                            this, data, mAddScreen, mAddIntersectCellX, mAddIntersectCellY);
-                    break;
-                case REQUEST_PICK_SHORTCUT:
-                    processShortcut(data);
-                    break;
-                case REQUEST_CREATE_SHORTCUT:
-                    completeAddShortcut(data, mAddScreen, mAddIntersectCellX, mAddIntersectCellY);
-                    break;
-                case REQUEST_PICK_LIVE_FOLDER:
-                    addLiveFolder(data);
-                    break;
-                case REQUEST_CREATE_LIVE_FOLDER:
-                    completeAddLiveFolder(data, mAddScreen, mAddIntersectCellX, mAddIntersectCellY);
-                    break;
-                case REQUEST_PICK_APPWIDGET:
-                    addAppWidgetFromPick(data);
-                    break;
-                case REQUEST_CREATE_APPWIDGET:
-                    int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
-                    completeAddAppWidget(appWidgetId, mAddScreen);
-                    break;
-                case REQUEST_PICK_WALLPAPER:
-                    // We just wanted the activity result here so we can clear mWaitingForResult
-                    break;
+            final PendingAddArguments args = new PendingAddArguments();
+            args.requestCode = requestCode;
+            args.intent = data;
+            args.screen = mAddScreen;
+            args.cellX = mAddIntersectCellX;
+            args.cellY = mAddIntersectCellY;
+
+            // If the loader is still running, defer the add until it is done.
+            if (isWorkspaceLocked()) {
+                sPendingAddList.add(args);
+            } else {
+                completeAdd(args);
             }
         } else if ((requestCode == REQUEST_PICK_APPWIDGET ||
                 requestCode == REQUEST_CREATE_APPWIDGET) && resultCode == RESULT_CANCELED &&
@@ -755,6 +694,9 @@
             mRestoring = false;
             mOnResumeNeedsLoad = false;
         }
+        if (mWaitingForResume != null) {
+            mWaitingForResume.setStayPressed(false);
+        }
         // When we resume Launcher, a different Activity might be responsible for the app
         // market intent, so refresh the icon
         updateAppMarketIcon();
@@ -778,7 +720,12 @@
     public Object onRetainNonConfigurationInstance() {
         // Flag the loader to stop early before switching
         mModel.stopLoader();
-        mAllAppsGrid.surrender();
+        if (mAllAppsGrid != null) {
+            mAllAppsGrid.surrender();
+        }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.surrender();
+        }
         return Boolean.TRUE;
     }
 
@@ -811,8 +758,10 @@
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        boolean handled = super.onKeyDown(keyCode, event);
-        if (!handled && acceptFilter() && keyCode != KeyEvent.KEYCODE_ENTER) {
+        final int uniChar = event.getUnicodeChar();
+        final boolean handled = super.onKeyDown(keyCode, event);
+        final boolean isKeyNotWhitespace = uniChar > 0 && !Character.isWhitespace(uniChar);
+        if (!handled && acceptFilter() && isKeyNotWhitespace) {
             boolean gotKey = TextKeyListener.getInstance().onKeyDown(mWorkspace, mDefaultKeySsb,
                     keyCode, event);
             if (gotKey && mDefaultKeySsb != null && mDefaultKeySsb.length() > 0) {
@@ -872,7 +821,7 @@
 
         State state = intToState(savedState.getInt(RUNTIME_STATE, State.WORKSPACE.ordinal()));
 
-        if (state == State.ALL_APPS) {
+        if (state == State.ALL_APPS || state == State.APPS_CUSTOMIZE) {
             showAllApps(false);
         } else if (state == State.CUSTOMIZE) {
             showCustomizationDrawer(false);
@@ -917,13 +866,28 @@
             String curTab = savedState.getString("customize_currentTab");
             if (curTab != null) {
                 // We set this directly so that there is no delay before the tab is set
-                mCustomizePagedView.setCustomizationFilter(getCustomizeFilterForTabTag(curTab));
+                mCustomizePagedView.setCustomizationFilter(
+                        mHomeCustomizationDrawer.getCustomizeFilterForTabTag(curTab));
                 mHomeCustomizationDrawer.setCurrentTabByTag(curTab);
             }
 
             // Note: currently we do not restore the page for the customization tray because unlike
             // AllApps, the page content can change drastically
         }
+
+        // Restore the AppsCustomize tab
+        if (mAppsCustomizeTabHost != null) {
+            String curTab = savedState.getString("apps_customize_currentTab");
+            if (curTab != null) {
+             // We set this directly so that there is no delay before the tab is set
+                mAppsCustomizeContent.setContentType(
+                        mAppsCustomizeTabHost.getContentTypeForTabTag(curTab));
+                mAppsCustomizeTabHost.setCurrentTabByTag(curTab);
+            }
+
+            // Note: currently we do not restore the page for the AppsCustomize pane because the
+            // change in layout can drastically affect the saved page index
+        }
     }
 
     /**
@@ -934,19 +898,20 @@
 
         DragLayer dragLayer = (DragLayer) findViewById(R.id.drag_layer);
         dragLayer.setDragController(dragController);
+        dragLayer.setLauncher(this);
+        mDragLayer = dragLayer;
 
-        mAllAppsGrid = (AllAppsView)dragLayer.findViewById(R.id.all_apps_view);
-        mAllAppsGrid.setLauncher(this);
-        mAllAppsGrid.setDragController(dragController);
-        ((View) mAllAppsGrid).setWillNotDraw(false); // We don't want a hole punched in our window.
-        // Manage focusability manually since this thing is always visible (in non-xlarge)
-        ((View) mAllAppsGrid).setFocusable(false);
-
-        if (LauncherApplication.isScreenXLarge()) {
-            // They need to be INVISIBLE initially so that they will be measured in the layout.
-            // Otherwise the animations are messed up when we show them for the first time.
-            ((View) mAllAppsGrid).setVisibility(View.INVISIBLE);
-            mHomeCustomizationDrawer.setVisibility(View.INVISIBLE);
+        if (LauncherApplication.isScreenLarge()) {
+            mAllAppsGrid = (AllAppsView) dragLayer.findViewById(R.id.all_apps_view);
+            mAllAppsGrid.setup(this, dragController);
+            // We don't want a hole punched in our window.
+            ((View) mAllAppsGrid).setWillNotDraw(false);
+        } else {
+            mAppsCustomizeTabHost = (AppsCustomizeTabHost)
+                    findViewById(R.id.apps_customize_pane);
+            mAppsCustomizeContent = (AppsCustomizePagedView)
+                    mAppsCustomizeTabHost.findViewById(R.id.apps_customize_pane_content);
+            mAppsCustomizeContent.setup(this, dragController);
         }
 
         mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
@@ -962,7 +927,6 @@
             // we don't use handle view in xlarge mode
             mHandleView = (HandleView)handleView;
             mHandleView.setLauncher(this);
-            mHandleView.setOnClickListener(this);
             mHandleView.setOnLongClickListener(this);
         }
 
@@ -977,8 +941,11 @@
              hotseatRight.setContentDescription(mHotseatLabels[1]);
              hotseatRight.setImageDrawable(mHotseatIcons[1]);
 
+             View.OnKeyListener listener = new IndicatorKeyEventListener();
              mPreviousView = (ImageView) dragLayer.findViewById(R.id.previous_screen);
+             mPreviousView.setOnKeyListener(listener);
              mNextView = (ImageView) dragLayer.findViewById(R.id.next_screen);
+             mNextView.setOnKeyListener(listener);
 
              Drawable previous = mPreviousView.getDrawable();
              Drawable next = mNextView.getDrawable();
@@ -999,10 +966,10 @@
         deleteZone.setDragController(dragController);
 
         final View allAppsButton = findViewById(R.id.all_apps_button);
-        final View divider = findViewById(R.id.divider);
+        final View divider = findViewById(R.id.all_apps_divider);
         final View configureButton = findViewById(R.id.configure_button);
 
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
             deleteZone.setOverlappingViews(new View[] { allAppsButton, divider, configureButton });
         } else {
             deleteZone.setOverlappingView(findViewById(R.id.all_apps_button_cluster));
@@ -1024,10 +991,17 @@
             allAppsInfoTarget.setLauncher(this);
             dragController.addDragListener(allAppsInfoTarget);
             allAppsInfoTarget.setDragAndDropEnabled(false);
-            View marketButton = findViewById(R.id.market_button);
-            if (marketButton != null) {
+        }
+        View marketButton = findViewById(R.id.market_button);
+        if (marketButton != null) {
+            if (allAppsInfoTarget != null) {
                 allAppsInfoTarget.setOverlappingView(marketButton);
             }
+            marketButton.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    onClickAppMarketButton(v);
+                }
+            });
         }
 
         dragController.setDragScoller(workspace);
@@ -1043,18 +1017,60 @@
         if (allAppsDeleteZone != null) {
             dragController.addDropTarget(allAppsDeleteZone);
         }
+        mButtonCluster = (ViewGroup) findViewById(R.id.all_apps_button_cluster);
+        View.OnKeyListener listener = null;
+        if (LauncherApplication.isScreenLarge()) {
+            // For tablets, AllApps lives in the button bar at the top
+            listener = new ButtonBarKeyEventListener();
+        } else {
+            // For phones, AppsCustomize lives in the "dock" at the bottom
+            listener = new DockKeyEventListener();
+        }
+        int buttonCount = mButtonCluster.getChildCount();
+        for (int i = 0; i < buttonCount; ++i) {
+            mButtonCluster.getChildAt(i).setOnKeyListener(listener);
+        }
+
+        mAllAppsButton = findViewById(R.id.all_apps_button);
+        mDivider = findViewById(R.id.all_apps_divider);
+        mConfigureButton = findViewById(R.id.configure_button);
+
+        // We had previously set these click handlers in XML, but the first time we launched
+        // Configure or All Apps we had an extra 50ms of delay while the java reflection methods
+        // found the right handler. Setting the handlers directly here eliminates that cost.
+        if (mConfigureButton != null) {
+            mConfigureButton.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    onClickConfigureButton(v);
+                }
+            });
+        }
+        if (mDivider != null) {
+            mDivider.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    onClickAllAppsButton(v);
+                }
+            });
+        }
+        if (mAllAppsButton != null) {
+            mAllAppsButton.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    onClickAllAppsButton(v);
+                }
+            });
+        }
     }
 
     @SuppressWarnings({"UnusedDeclaration"})
     public void previousScreen(View v) {
-        if (mState != State.ALL_APPS) {
+        if (mState != State.ALL_APPS && mState != State.APPS_CUSTOMIZE) {
             mWorkspace.scrollLeft();
         }
     }
 
     @SuppressWarnings({"UnusedDeclaration"})
     public void nextScreen(View v) {
-        if (mState != State.ALL_APPS) {
+        if (mState != State.ALL_APPS && mState != State.APPS_CUSTOMIZE) {
             mWorkspace.scrollRight();
         }
     }
@@ -1114,7 +1130,7 @@
      * @param data The intent describing the application.
      * @param cellInfo The position on screen where to create the shortcut.
      */
-    void completeAddApplication(Context context, Intent data, int screen,
+    void completeAddApplication(Intent data, int screen,
             int intersectCellX, int intersectCellY) {
         final int[] cellXY = mTmpAddItemCellCoordinates;
         final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
@@ -1124,8 +1140,7 @@
             return;
         }
 
-        final ShortcutInfo info = mModel.getShortcutInfo(context.getPackageManager(),
-                data, context);
+        final ShortcutInfo info = mModel.getShortcutInfo(getPackageManager(), data, this);
 
         if (info != null) {
             info.setActivity(data.getComponent(), Intent.FLAG_ACTIVITY_NEW_TASK |
@@ -1182,7 +1197,7 @@
      * @param appWidgetId The app widget id
      * @param cellInfo The position on screen where to create the widget.
      */
-    private void completeAddAppWidget(int appWidgetId, int screen) {
+    private void completeAddAppWidget(final int appWidgetId, int screen) {
         AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
 
         // Calculate the grid spans needed to fit this widget
@@ -1212,7 +1227,16 @@
         }
 
         if (!foundCellSpan) {
-            if (appWidgetId != -1) mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+            if (appWidgetId != -1) {
+                // Deleting an app widget ID is a void call but writes to disk before returning
+                // to the caller...
+                final LauncherAppWidgetHost appWidgetHost = mAppWidgetHost;
+                new Thread("deleteAppWidgetId") {
+                    public void run() {
+                        mAppWidgetHost.deleteAppWidgetId(appWidgetId);
+                    }
+                }.start();
+            }
             showOutOfSpaceMessage();
             return;
         }
@@ -1249,6 +1273,14 @@
             if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                 mUserPresent = false;
                 updateRunning();
+
+                // Reset AllApps to it's initial state
+                if (mAllAppsGrid != null) {
+                    mAllAppsGrid.reset();
+                }
+                if (mAppsCustomizeContent != null) {
+                    mAppsCustomizeContent.reset();
+                }
             } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
                 mUserPresent = true;
                 updateRunning();
@@ -1402,16 +1434,11 @@
             boolean alreadyOnHome = ((intent.getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
                         != Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
 
-            // in all these cases, only animate if we're already on home
-            if (LauncherApplication.isScreenXLarge()) {
-                mWorkspace.unshrink(alreadyOnHome);
-            }
-            if (!mWorkspace.isDefaultPageShowing()) {
-                // on the phone, we don't animate the change to the workspace if all apps is visible
-                boolean animate = alreadyOnHome &&
-                    (LauncherApplication.isScreenXLarge() || mState != State.ALL_APPS);
-                mWorkspace.moveToDefaultScreen(animate);
-                if (!animate) mWorkspace.updateWallpaperOffsetImmediately();
+            // In all these cases, only animate if we're already on home
+            mWorkspace.unshrink(alreadyOnHome);
+            mWorkspace.exitWidgetResizeMode();
+            if (alreadyOnHome && mState == State.WORKSPACE && !mWorkspace.isTouchActive()) {
+                mWorkspace.moveToDefaultScreen(true);
             }
             showWorkspace(alreadyOnHome);
 
@@ -1421,6 +1448,14 @@
                         INPUT_METHOD_SERVICE);
                 imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
             }
+
+            // Reset AllApps to it's initial state
+            if (mAllAppsGrid != null) {
+                mAllAppsGrid.reset();
+            }
+            if (mAppsCustomizeContent != null) {
+                mAppsCustomizeContent.reset();
+            }
         }
     }
 
@@ -1442,7 +1477,7 @@
                 final FolderInfo info = folders.get(i).getInfo();
                 ids[i] = info.id;
             }
-            outState.putLongArray(RUNTIME_STATE_USER_FOLDERS, ids);
+            outState.putLongArray(RUNTIME_STATE_FOLDERS, ids);
         } else {
             super.onSaveInstanceState(outState);
         }
@@ -1469,7 +1504,6 @@
                 outState.putInt("allapps_currentPage", mAllAppsPagedView.getCurrentPage());
             }
         }
-
         // Save the current customization drawer tab
         if (mHomeCustomizationDrawer != null) {
             String currentTabTag = mHomeCustomizationDrawer.getCurrentTabTag();
@@ -1477,6 +1511,13 @@
                 outState.putString("customize_currentTab", currentTabTag);
             }
         }
+        // Save the current AppsCustomize tab
+        if (mAppsCustomizeTabHost != null) {
+            String currentTabTag = mAppsCustomizeTabHost.getCurrentTabTag();
+            if (currentTabTag != null) {
+                outState.putString("apps_customize_currentTab", currentTabTag);
+            }
+        }
     }
 
     @Override
@@ -1518,6 +1559,10 @@
         ValueAnimator.clearAllAnimations();
     }
 
+    public DragController getDragController() {
+        return mDragController;
+    }
+
     @Override
     public void startActivityForResult(Intent intent, int requestCode) {
         if (requestCode >= 0) mWaitingForResult = true;
@@ -1585,22 +1630,28 @@
     public boolean onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
 
-        // If all apps is animating, don't show the menu, because we don't know
-        // which one to show.
-        if (mAllAppsGrid.isAnimating()) {
-            return false;
+        if (mAllAppsGrid != null) {
+            // If all apps is animating, don't show the menu, because we don't know
+            // which one to show.
+            if (mAllAppsGrid.isAnimating()) {
+                return false;
+            }
+
+            // Only show the add and wallpaper options when we're not in all apps.
+            boolean visible = !mAllAppsGrid.isVisible();
+            menu.setGroupVisible(MENU_GROUP_ADD, visible);
+            menu.setGroupVisible(MENU_GROUP_WALLPAPER, visible);
+
+            // Disable add if the workspace is full.
+            if (visible) {
+                CellLayout layout = (CellLayout) mWorkspace.getChildAt(mWorkspace.getCurrentPage());
+                menu.setGroupEnabled(MENU_GROUP_ADD, layout.existsEmptyCell());
+            }
         }
 
-        // Only show the add and wallpaper options when we're not in all apps.
-        boolean visible = !mAllAppsGrid.isVisible();
-        menu.setGroupVisible(MENU_GROUP_ADD, visible);
-        menu.setGroupVisible(MENU_GROUP_WALLPAPER, visible);
-
-        // Disable add if the workspace is full.
-        if (visible) {
-            CellLayout layout = (CellLayout) mWorkspace.getChildAt(mWorkspace.getCurrentPage());
-            menu.setGroupEnabled(MENU_GROUP_ADD, layout.existsEmptyCell());
-        }
+        // TODO-APPS_CUSTOMIZE: Remove this for the phone UI at some point, along with all the menu
+        // related code?
+        if (mAppsCustomizeContent != null && mAppsCustomizeContent.isAnimating()) return false;
 
         return true;
     }
@@ -1643,8 +1694,14 @@
         return mWorkspaceLoading || mWaitingForResult;
     }
 
+    // Is the workspace preview (brought up by long-pressing on a signpost icon) visible?
+    private boolean isPreviewVisible() {
+        return (mPreviousView != null && mPreviousView.getTag() != null) ||
+                (mNextView != null && mNextView.getTag() != null);
+    }
+
     private void addItems() {
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
             // Animate the widget chooser up from the bottom of the screen
             if (mState != State.CUSTOMIZE) {
                 showCustomizationDrawer(true);
@@ -1761,38 +1818,15 @@
         startActivityForResult(intent, REQUEST_PICK_WALLPAPER);
     }
 
-    void addLiveFolderFromDrop(ComponentName componentName, int screen, int[] position) {
-        resetAddInfo();
-        mAddScreen = screen;
-        mAddDropPosition = position;
-
-        Intent createFolderIntent = new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER);
-        createFolderIntent.setComponent(componentName);
-
-        addLiveFolder(createFolderIntent);
-    }
-
-    void addLiveFolder(Intent intent) { // YYY add screen intersect etc. parameters here
-        // Handle case where user selected "Folder"
-        String folderName = getResources().getString(R.string.group_folder);
-        String shortcutName = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
-
-        if (folderName != null && folderName.equals(shortcutName)) {
-            addFolder(mAddScreen, mAddIntersectCellX, mAddIntersectCellY);
-        } else {
-            startActivityForResultSafely(intent, REQUEST_CREATE_LIVE_FOLDER);
-        }
-    }
-
-    void addFolder(int screen, int intersectCellX, int intersectCellY) {
-        UserFolderInfo folderInfo = new UserFolderInfo();
+    FolderIcon addFolder(int screen, int intersectCellX, int intersectCellY) {
+        FolderInfo folderInfo = new FolderInfo();
         folderInfo.title = getText(R.string.folder_name);
 
         final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
         final int[] cellXY = mTmpAddItemCellCoordinates;
         if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
             showOutOfSpaceMessage();
-            return;
+            return null;
         }
 
         // Update the model
@@ -1806,73 +1840,13 @@
                 (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()),
                 folderInfo, mIconCache);
         mWorkspace.addInScreen(newFolder, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
+        return newFolder;
     }
 
     void removeFolder(FolderInfo folder) {
         sFolders.remove(folder.id);
     }
 
-    private void completeAddLiveFolder(
-            Intent data, int screen, int intersectCellX, int intersectCellY) {
-        final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
-        final int[] cellXY = mTmpAddItemCellCoordinates;
-        if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
-            showOutOfSpaceMessage();
-            return;
-        }
-
-        final LiveFolderInfo info = addLiveFolder(this, data, screen, cellXY[0], cellXY[1], false);
-
-        if (!mRestoring) {
-            final View view = LiveFolderIcon.fromXml(R.layout.live_folder_icon, this,
-                (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), info);
-            mWorkspace.addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, isWorkspaceLocked());
-        }
-    }
-
-    static LiveFolderInfo addLiveFolder(Context context, Intent data,
-            int screen, int cellX, int cellY, boolean notify) {
-
-        Intent baseIntent = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_BASE_INTENT);
-        String name = data.getStringExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME);
-
-        Drawable icon = null;
-        Intent.ShortcutIconResource iconResource = null;
-
-        Parcelable extra = data.getParcelableExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON);
-        if (extra != null && extra instanceof Intent.ShortcutIconResource) {
-            try {
-                iconResource = (Intent.ShortcutIconResource) extra;
-                final PackageManager packageManager = context.getPackageManager();
-                Resources resources = packageManager.getResourcesForApplication(
-                        iconResource.packageName);
-                final int id = resources.getIdentifier(iconResource.resourceName, null, null);
-                icon = resources.getDrawable(id);
-            } catch (Exception e) {
-                Log.w(TAG, "Could not load live folder icon: " + extra);
-            }
-        }
-
-        if (icon == null) {
-            icon = context.getResources().getDrawable(R.drawable.ic_launcher_folder);
-        }
-
-        final LiveFolderInfo info = new LiveFolderInfo();
-        info.icon = Utilities.createIconBitmap(icon, context);
-        info.title = name;
-        info.iconResource = iconResource;
-        info.uri = data.getData();
-        info.baseIntent = baseIntent;
-        info.displayMode = data.getIntExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE,
-                LiveFolders.DISPLAY_MODE_GRID);
-
-        LauncherModel.addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
-                screen, cellX, cellY, notify);
-        sFolders.put(info.id, info);
-
-        return info;
-    }
-
     private void showNotifications() {
         final StatusBarManager statusBar = (StatusBarManager) getSystemService(STATUS_BAR_SERVICE);
         if (statusBar != null) {
@@ -1934,36 +1908,41 @@
 
     @Override
     public void onBackPressed() {
-        if (mState == State.ALL_APPS || mState == State.CUSTOMIZE) {
+        if (mState == State.ALL_APPS || mState == State.CUSTOMIZE || mState == State.APPS_CUSTOMIZE) {
             showWorkspace(true);
-        } else {
+        } else if (mWorkspace.getOpenFolder() != null) {
             closeFolder();
-        }
-        // Some launcher layouts don't have a previous and next view
-        if (mPreviousView != null) {
+        } else if (isPreviewVisible()) {
             dismissPreview(mPreviousView);
             dismissPreview(mNextView);
+        } else {
+            mWorkspace.exitWidgetResizeMode();
+
+            // Back button is a no-op here, but give at least some feedback for the button press
+            mWorkspace.showOutlinesTemporarily();
         }
     }
 
-    private void closeFolder() {
+    public void closeFolder() {
         Folder folder = mWorkspace.getOpenFolder();
         if (folder != null) {
             closeFolder(folder);
+            mDragLayer.setCurrentFolder(null);
         }
     }
 
     void closeFolder(Folder folder) {
         folder.getInfo().opened = false;
+
         ViewGroup parent = (ViewGroup) folder.getParent().getParent();
         if (parent != null) {
             CellLayout cl = (CellLayout) parent;
-            cl.removeViewWithoutMarkingCells(folder);
-            if (folder instanceof DropTarget) {
-                // Live folders aren't DropTargets.
-                mDragController.removeDropTarget((DropTarget)folder);
-            }
+            FolderIcon fi = (FolderIcon) cl.getChildAt(folder.mInfo.cellX, folder.mInfo.cellY);
+            shrinkAndFadeInFolderIcon(fi);
+            mDragController.removeDropTarget((DropTarget)folder);
         }
+
+        folder.animateClosed();
         folder.onClose();
     }
 
@@ -1971,7 +1950,9 @@
      * Re-listen when widgets are reset.
      */
     private void onAppWidgetReset() {
-        mAppWidgetHost.startListening();
+        if (mAppWidgetHost != null) {
+            mAppWidgetHost.startListening();
+        }
     }
 
     /**
@@ -1999,9 +1980,17 @@
             v.getLocationOnScreen(pos);
             intent.setSourceBounds(new Rect(pos[0], pos[1],
                     pos[0] + v.getWidth(), pos[1] + v.getHeight()));
-            startActivitySafely(intent, tag);
+            boolean success = startActivitySafely(intent, tag);
+
+            if (success && v instanceof BubbleTextView) {
+                mWaitingForResume = (BubbleTextView) v;
+                mWaitingForResume.setStayPressed(true);
+            }
         } else if (tag instanceof FolderInfo) {
-            handleFolderClick((FolderInfo) tag);
+            if (v instanceof FolderIcon) {
+                FolderIcon fi = (FolderIcon) v;
+                handleFolderClick(fi);
+            }
         } else if (v == mHandleView) {
             if (mState == State.ALL_APPS) {
                 showWorkspace(true);
@@ -2092,10 +2081,11 @@
         }
     }
 
-    void startActivitySafely(Intent intent, Object tag) {
+    boolean startActivitySafely(Intent intent, Object tag) {
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         try {
             startActivity(intent);
+            return true;
         } catch (ActivityNotFoundException e) {
             Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
             Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
@@ -2106,6 +2096,7 @@
                     "or use the exported attribute for this activity. "
                     + "tag="+ tag + " intent=" + intent, e);
         }
+        return false;
     }
 
     void startActivityForResultSafely(Intent intent, int requestCode) {
@@ -2121,15 +2112,16 @@
         }
     }
 
-    private void handleFolderClick(FolderInfo folderInfo) {
-        if (!folderInfo.opened) {
+    private void handleFolderClick(FolderIcon folderIcon) {
+        final FolderInfo info = folderIcon.mInfo;
+        if (!info.opened) {
             // Close any open folder
             closeFolder();
             // Open the requested folder
-            openFolder(folderInfo);
+            openFolder(folderIcon);
         } else {
             // Find the open folder...
-            Folder openFolder = mWorkspace.getFolderForTag(folderInfo);
+            Folder openFolder = mWorkspace.getFolderForTag(info);
             int folderScreen;
             if (openFolder != null) {
                 folderScreen = mWorkspace.getPageForView(openFolder);
@@ -2139,12 +2131,32 @@
                     // Close any folder open on the current screen
                     closeFolder();
                     // Pull the folder onto this screen
-                    openFolder(folderInfo);
+                    openFolder(folderIcon);
                 }
             }
         }
     }
 
+    private void growAndFadeOutFolderIcon(FolderIcon fi) {
+        PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
+        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.5f);
+        PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.5f);
+
+        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(fi, alpha, scaleX, scaleY);
+        oa.setDuration(getResources().getInteger(R.integer.config_folderAnimDuration));
+        oa.start();
+    }
+
+    private void shrinkAndFadeInFolderIcon(FolderIcon fi) {
+        PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
+        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
+        PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
+
+        ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(fi, alpha, scaleX, scaleY);
+        oa.setDuration(getResources().getInteger(R.integer.config_folderAnimDuration));
+        oa.start();
+    }
+
     /**
      * Opens the user folder described by the specified tag. The opening of the folder
      * is animated relative to the specified View. If the View is null, no animation
@@ -2152,46 +2164,41 @@
      *
      * @param folderInfo The FolderInfo describing the folder to open.
      */
-    public void openFolder(FolderInfo folderInfo) {
-        Folder openFolder;
+    public void openFolder(FolderIcon folderIcon) {
+        Folder folder = folderIcon.mFolder;
+        FolderInfo info = folder.mInfo;
 
-        if (folderInfo instanceof UserFolderInfo) {
-            openFolder = UserFolder.fromXml(this);
-        } else if (folderInfo instanceof LiveFolderInfo) {
-            openFolder = com.android.launcher2.LiveFolder.fromXml(this, folderInfo);
-        } else {
-            return;
-        }
+        growAndFadeOutFolderIcon(folderIcon);
+        info.opened = true;
 
-        openFolder.setDragController(mDragController);
-        openFolder.setLauncher(this);
-
-        openFolder.bind(folderInfo);
-        folderInfo.opened = true;
-
-        mWorkspace.addInFullScreen(openFolder, folderInfo.screen);
-
-        openFolder.onOpen();
+        mWorkspace.addInFullScreen(folder, info.screen);
+        mDragLayer.setCurrentFolder(folder);
+        folder.animateOpen();
+        folder.onOpen();
     }
 
     public boolean onLongClick(View v) {
+        if (mState != State.WORKSPACE) {
+            return false;
+        }
+
         switch (v.getId()) {
             case R.id.previous_screen:
-                if (mState != State.ALL_APPS) {
+                if (mState != State.ALL_APPS && mState != State.APPS_CUSTOMIZE) {
                     mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                             HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
                     showPreviews(v);
                 }
                 return true;
             case R.id.next_screen:
-                if (mState != State.ALL_APPS) {
+                if (mState != State.ALL_APPS && mState != State.APPS_CUSTOMIZE) {
                     mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                             HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
                     showPreviews(v);
                 }
                 return true;
             case R.id.all_apps_button:
-                if (mState != State.ALL_APPS) {
+                if (mState != State.ALL_APPS && mState != State.APPS_CUSTOMIZE) {
                     mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                             HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
                     showPreviews(v);
@@ -2207,7 +2214,6 @@
             v = (View) v.getParent().getParent();
         }
 
-
         resetAddInfo();
         CellLayout.CellInfo longClickCellInfo = (CellLayout.CellInfo) v.getTag();
         // This happens when long clicking an item with the dpad/trackball
@@ -2223,10 +2229,10 @@
                 mWorkspace.setAllowLongPress(false);
                 mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                         HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
-                if (LauncherApplication.isScreenXLarge()) {
+                if (LauncherApplication.isScreenLarge()) {
                     addItems();
                 } else {
-                    showAddDialog(longClickCellInfo.cellX, longClickCellInfo.cellY);
+                    startWallpaper();
                 }
             } else {
                 if (!(itemUnderLongClick instanceof Folder)) {
@@ -2253,11 +2259,12 @@
                     for (int i = 0; i < count; i++) {
                         ((ImageView) group.getChildAt(i)).setImageDrawable(null);
                     }
-                    ArrayList<Bitmap> bitmaps = (ArrayList<Bitmap>) v.getTag(R.id.icon);
+                    ArrayList<Bitmap> bitmaps =
+                        (ArrayList<Bitmap>) v.getTag(R.id.all_apps_button_cluster);
                     for (Bitmap bitmap : bitmaps) bitmap.recycle();
 
                     v.setTag(R.id.workspace, null);
-                    v.setTag(R.id.icon, null);
+                    v.setTag(R.id.all_apps_button_cluster, null);
                     window.setOnDismissListener(null);
                 }
             });
@@ -2349,7 +2356,7 @@
 
         anchor.setTag(p);
         anchor.setTag(R.id.workspace, preview);
-        anchor.setTag(R.id.icon, bitmaps);
+        anchor.setTag(R.id.all_apps_button_cluster, bitmaps);
     }
 
     class PreviewTouchHandler implements View.OnClickListener, Runnable, View.OnFocusChangeListener {
@@ -2379,6 +2386,10 @@
         return mWorkspace;
     }
 
+    TabHost getCustomizationDrawer() {
+        return mHomeCustomizationDrawer;
+    }
+
     @Override
     protected Dialog onCreateDialog(int id) {
         switch (id) {
@@ -2504,7 +2515,9 @@
                     final FolderIcon folderIcon = (FolderIcon)
                             mWorkspace.getViewForTag(mFolderInfo);
                     if (folderIcon != null) {
-                        folderIcon.setText(name);
+                        // TODO: At some point we'll probably want some version of setting
+                        // the text for a folder icon.
+                        //folderIcon.setText(name);
                         getWorkspace().requestLayout();
                     } else {
                         lockAllApps();
@@ -2525,29 +2538,25 @@
 
     // Now a part of LauncherModel.Callbacks. Used to reorder loading steps.
     public boolean isAllAppsVisible() {
-        return mState == State.ALL_APPS;
+        return (mState == State.ALL_APPS) || (mState == State.APPS_CUSTOMIZE);
     }
 
     // AllAppsView.Watcher
     public void zoomed(float zoom) {
         // In XLarge view, we zoom down the workspace below all apps so it's still visible
-        if (zoom == 1.0f && !LauncherApplication.isScreenXLarge()) {
+        if (zoom == 1.0f && !LauncherApplication.isScreenLarge()) {
             mWorkspace.setVisibility(View.GONE);
         }
     }
     
-    private void showToolbarButton(View button) {
+    private void showAndEnableToolbarButton(View button) {
         button.setVisibility(View.VISIBLE);
-        button.setFocusable(true);
-        button.setClickable(true);
     }
 
     private void hideToolbarButton(View button) {
-        button.setAlpha(0.0f);
         // We can't set it to GONE, otherwise the RelativeLayout gets screwed up
         button.setVisibility(View.INVISIBLE);
-        button.setFocusable(false);
-        button.setClickable(false);
+        button.setAlpha(0.0f);
     }
 
     /**
@@ -2567,12 +2576,17 @@
                 getResources().getInteger(R.integer.config_toolbarButtonFadeOutTime);
 
         if (seq != null) {
-            Animator anim = ObjectAnimator.ofFloat(view, "alpha", show ? 1.0f : 0.0f);
+            ValueAnimator anim = ValueAnimator.ofFloat(view.getAlpha(), show ? 1.0f : 0.0f);
             anim.setDuration(duration);
+            anim.addUpdateListener(new AnimatorUpdateListener() {
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    view.setAlpha((Float) animation.getAnimatedValue());
+                }
+            });
             anim.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationStart(Animator animation) {
-                    if (showing) showToolbarButton(view);
+                    if (showing) showAndEnableToolbarButton(view);
                 }
                 @Override
                 public void onAnimationEnd(Animator animation) {
@@ -2582,7 +2596,7 @@
             seq.play(anim);
         } else {
             if (showing) {
-                showToolbarButton(view);
+                showAndEnableToolbarButton(view);
                 view.setAlpha(1f);
             } else {
                 hideToolbarButton(view);
@@ -2599,26 +2613,24 @@
      * @param hideSeq AnimatorSet in which to put "hide" animations, or null.
      */
     private void hideAndShowToolbarButtons(State newState, AnimatorSet showSeq, AnimatorSet hideSeq) {
-        final View buttonCluster = findViewById(R.id.all_apps_button_cluster);
-
-        final View allAppsButton = findViewById(R.id.all_apps_button);
-        final View divider = findViewById(R.id.divider);
-        final View configureButton = findViewById(R.id.configure_button);
-
         switch (newState) {
         case WORKSPACE:
-            hideOrShowToolbarButton(true, buttonCluster, showSeq);
-            mDeleteZone.setOverlappingViews(new View[] { allAppsButton, divider, configureButton });
+            hideOrShowToolbarButton(true, mButtonCluster, showSeq);
             mDeleteZone.setDragAndDropEnabled(true);
-            mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_workspace));
+            if (LauncherApplication.isScreenLarge()) {
+                mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_workspace));
+            }
             break;
         case ALL_APPS:
-            hideOrShowToolbarButton(false, buttonCluster, hideSeq);
+        case APPS_CUSTOMIZE:
+            hideOrShowToolbarButton(false, mButtonCluster, hideSeq);
             mDeleteZone.setDragAndDropEnabled(false);
-            mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_all_apps));
+            if (LauncherApplication.isScreenLarge()) {
+                mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_all_apps));
+            }
             break;
         case CUSTOMIZE:
-            hideOrShowToolbarButton(false, buttonCluster, hideSeq);
+            hideOrShowToolbarButton(false, mButtonCluster, hideSeq);
             mDeleteZone.setDragAndDropEnabled(false);
             break;
         }
@@ -2637,7 +2649,7 @@
         // Set pivotY so that at the starting zoom factor, the view is partially
         // visible. Modifying initialHeightFactor changes how much of the view is
         // initially showing, and hence the perceived angle from which the view enters.
-        if (state == State.ALL_APPS) {
+        if (state == State.ALL_APPS || state == State.APPS_CUSTOMIZE) {
             final float initialHeightFactor = 0.175f;
             view.setPivotY((1 - initialHeightFactor) * height);
         } else {
@@ -2652,35 +2664,54 @@
      * of the screen.
      * @param toState The state to zoom out to. Must be ALL_APPS or CUSTOMIZE.
      */
-    private void cameraZoomOut(State toState, boolean animated) {
+    private void cameraZoomOut(State toState, boolean animated, boolean springLoaded) {
         final Resources res = getResources();
-        final boolean toAllApps = (toState == State.ALL_APPS);
+        final boolean toAllApps = (toState == State.ALL_APPS)
+                || (toState == State.APPS_CUSTOMIZE);
 
-        final int duration = toAllApps ?
-                res.getInteger(R.integer.config_allAppsZoomInTime) :
-                res.getInteger(R.integer.config_customizeZoomInTime);
+        final int duration = (toAllApps ?
+                res.getInteger(R.integer.config_appsCustomizeZoomInTime) :
+                res.getInteger(R.integer.config_customizeZoomInTime));
+        final int fadeDuration = (toAllApps ?
+                res.getInteger(R.integer.config_appsCustomizeFadeInTime) :
+                res.getInteger(R.integer.config_customizeFadeInTime));
 
         final float scale = toAllApps ?
-                (float) res.getInteger(R.integer.config_allAppsZoomScaleFactor) :
+                (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor) :
                 (float) res.getInteger(R.integer.config_customizeZoomScaleFactor);
 
-        final View toView = toAllApps ? (View) mAllAppsGrid : mHomeCustomizationDrawer;
+        View tmpView;
+        if (toAllApps) {
+            tmpView = (LauncherApplication.isScreenLarge())
+                    ? (View) mAllAppsGrid : mAppsCustomizeTabHost;
+        } else {
+            tmpView = mHomeCustomizationDrawer;
+        }
+        final View toView = tmpView;
 
         setPivotsForZoom(toView, toState, scale);
 
         if (toAllApps) {
-            mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
+            if (!springLoaded) {
+                mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
+
+                if (LauncherApplication.isScreenLarge()) {
+                    // Everytime we launch into AllApps, we reset the successful drop flag which
+                    // controls when it should hide/show the mini workspaces
+                    mAllAppsPagedView.resetSuccessfulDropFlag();
+                }
+            } else {
+                mWorkspace.shrink(ShrinkState.BOTTOM_VISIBLE, animated);
+            }
         } else {
             mWorkspace.shrink(ShrinkState.TOP, animated);
         }
 
         if (animated) {
-            ValueAnimator scaleAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
+            final ValueAnimator scaleAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
             scaleAnim.setInterpolator(new Workspace.ZoomOutInterpolator());
-            scaleAnim.addUpdateListener(new AnimatorUpdateListener() {
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    final float b = (Float) animation.getAnimatedValue();
-                    final float a = 1f - b;
+            scaleAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+                public void onAnimationUpdate(float a, float b) {
                     ((View) toView.getParent()).fastInvalidate();
                     toView.setFastScaleX(a * scale + b * 1f);
                     toView.setFastScaleY(a * scale + b * 1f);
@@ -2688,13 +2719,12 @@
             });
 
             if (toAllApps) {
-                toView.setAlpha(0f);
-                ValueAnimator alphaAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
+                toView.setVisibility(View.VISIBLE);
+                toView.setFastAlpha(0f);
+                ValueAnimator alphaAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(fadeDuration);
                 alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
-                alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
-                    public void onAnimationUpdate(ValueAnimator animation) {
-                        final float b = (Float) animation.getAnimatedValue();
-                        final float a = 1f - b;
+                alphaAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+                    public void onAnimationUpdate(float a, float b) {
                         // don't need to invalidate because we do so above
                         toView.setFastAlpha(a * 0f + b * 1f);
                     }
@@ -2702,9 +2732,8 @@
                 alphaAnim.start();
             }
 
-            // Only use hardware layers in portrait mode, they don't give any gains in landscape
-            if (mWorkspace.getWidth() < mWorkspace.getHeight()) {
-                toView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            if (toView instanceof LauncherTransitionable) {
+                ((LauncherTransitionable) toView).onLauncherTransitionStart(scaleAnim);
             }
             scaleAnim.addListener(new AnimatorListenerAdapter() {
                 @Override
@@ -2713,8 +2742,9 @@
                     toView.setTranslationX(0.0f);
                     toView.setTranslationY(0.0f);
                     toView.setVisibility(View.VISIBLE);
+                    toView.bringToFront();
                     if (!toAllApps) {
-                        toView.setAlpha(1.0f);
+                        toView.setFastAlpha(1.0f);
                     }
                 }
                 @Override
@@ -2722,9 +2752,11 @@
                     // If we don't set the final scale values here, if this animation is cancelled
                     // it will have the wrong scale value and subsequent cameraPan animations will
                     // not fix that
-                    toView.setLayerType(View.LAYER_TYPE_NONE, null);
                     toView.setScaleX(1.0f);
                     toView.setScaleY(1.0f);
+                    if (toView instanceof LauncherTransitionable) {
+                        ((LauncherTransitionable) toView).onLauncherTransitionEnd(scaleAnim);
+                    }
                 }
             });
 
@@ -2750,6 +2782,11 @@
             toView.setScaleX(1.0f);
             toView.setScaleY(1.0f);
             toView.setVisibility(View.VISIBLE);
+            toView.bringToFront();
+            if (toView instanceof LauncherTransitionable) {
+                ((LauncherTransitionable) toView).onLauncherTransitionStart(null);
+                ((LauncherTransitionable) toView).onLauncherTransitionEnd(null);
+            }
             hideAndShowToolbarButtons(toState, null, null);
         }
     }
@@ -2760,33 +2797,38 @@
      * @param fromState The current state (must be ALL_APPS or CUSTOMIZE).
      * @param animated If true, the transition will be animated.
      */
-    private void cameraZoomIn(State fromState, boolean animated) {
-        cameraZoomIn(fromState, animated, false);
-    }
-
     private void cameraZoomIn(State fromState, boolean animated, boolean springLoaded) {
         Resources res = getResources();
-        final boolean fromAllApps = (fromState == State.ALL_APPS);
+        final boolean fromAllApps = (fromState == State.ALL_APPS)
+                || (fromState == State.APPS_CUSTOMIZE);
 
         int duration = fromAllApps ?
-            res.getInteger(R.integer.config_allAppsZoomOutTime) :
+            res.getInteger(R.integer.config_appsCustomizeZoomOutTime) :
             res.getInteger(R.integer.config_customizeZoomOutTime);
 
         final float scaleFactor = fromAllApps ?
-            (float) res.getInteger(R.integer.config_allAppsZoomScaleFactor) :
+            (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor) :
             (float) res.getInteger(R.integer.config_customizeZoomScaleFactor);
 
-        final View fromView = fromAllApps ? (View) mAllAppsGrid : mHomeCustomizationDrawer;
+        View tmpView;
+        if (fromAllApps) {
+            tmpView = (LauncherApplication.isScreenLarge())
+                    ? (View) mAllAppsGrid : mAppsCustomizeTabHost;
+        } else {
+            tmpView = mHomeCustomizationDrawer;
+        }
+        final View fromView = tmpView;
 
-        mCustomizePagedView.endChoiceMode();
-        mAllAppsPagedView.endChoiceMode();
+        if (LauncherApplication.isScreenLarge()) {
+            mCustomizePagedView.endChoiceMode();
+            mAllAppsPagedView.endChoiceMode();
+        }
 
         setPivotsForZoom(fromView, fromState, scaleFactor);
 
         if (!springLoaded) {
             mWorkspace.unshrink(animated);
         }
-
         if (animated) {
             if (mStateAnimation != null) mStateAnimation.cancel();
             mStateAnimation = new AnimatorSet();
@@ -2796,33 +2838,32 @@
 
             ValueAnimator scaleAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
             scaleAnim.setInterpolator(new Workspace.ZoomInInterpolator());
-            scaleAnim.addUpdateListener(new AnimatorUpdateListener() {
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    final float b = (Float) animation.getAnimatedValue();
-                    final float a = 1f - b;
+            scaleAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+                public void onAnimationUpdate(float a, float b) {
                     ((View)fromView.getParent()).fastInvalidate();
                     fromView.setFastScaleX(a * oldScaleX + b * scaleFactor);
                     fromView.setFastScaleY(a * oldScaleY + b * scaleFactor);
                 }
             });
-            ValueAnimator alphaAnim = ValueAnimator.ofFloat(0f, 1f);
-            alphaAnim.setDuration(res.getInteger(R.integer.config_allAppsFadeOutTime));
+            final ValueAnimator alphaAnim = ValueAnimator.ofFloat(0f, 1f);
+            alphaAnim.setDuration(res.getInteger(R.integer.config_appsCustomizeFadeOutTime));
             alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
-            alphaAnim.addUpdateListener(new AnimatorUpdateListener() {
-                public void onAnimationUpdate(ValueAnimator animation) {
-                    final float b = (Float) animation.getAnimatedValue();
-                    final float a = 1f - b;
+            alphaAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+                public void onAnimationUpdate(float a, float b) {
                     // don't need to invalidate because we do so above
                     fromView.setFastAlpha(a * 1f + b * 0f);
                 }
             });
-
-            fromView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            if (fromView instanceof LauncherTransitionable) {
+                ((LauncherTransitionable) fromView).onLauncherTransitionStart(alphaAnim);
+            }
             alphaAnim.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
                     fromView.setVisibility(View.GONE);
-                    fromView.setLayerType(View.LAYER_TYPE_NONE, null);
+                    if (fromView instanceof LauncherTransitionable) {
+                        ((LauncherTransitionable) fromView).onLauncherTransitionEnd(alphaAnim);
+                    }
                 }
             });
 
@@ -2841,121 +2882,16 @@
             mStateAnimation.start();
         } else {
             fromView.setVisibility(View.GONE);
+            if (fromView instanceof LauncherTransitionable) {
+                ((LauncherTransitionable) fromView).onLauncherTransitionStart(null);
+                ((LauncherTransitionable) fromView).onLauncherTransitionEnd(null);
+            }
             if (!springLoaded) {
                 hideAndShowToolbarButtons(State.WORKSPACE, null, null);
             }
         }
     }
 
-    /**
-     * Pan the camera in the vertical plane between 'fromView' and 'toView'.
-     * This is the transition used on xlarge screens to go between all apps and
-     * the home customization drawer.
-     * @param fromState The view to pan away from. Must be ALL_APPS or CUSTOMIZE.
-     * @param toState The view to pan into the frame. Must be ALL_APPS or CUSTOMIZE.
-     * @param animated If true, the transition will be animated.
-     */
-    private void cameraPan(State fromState, State toState, boolean animated) {
-        final Resources res = getResources();
-        final int duration = res.getInteger(R.integer.config_allAppsCameraPanTime);
-        final int workspaceHeight = mWorkspace.getHeight();
-
-        final boolean fromAllApps = (fromState == State.ALL_APPS);
-        final View fromView = fromAllApps ? (View) mAllAppsGrid : mHomeCustomizationDrawer;
-        final View toView = fromAllApps ? mHomeCustomizationDrawer : (View) mAllAppsGrid;
-
-        final float fromViewStartY = fromAllApps ? 0.0f : fromView.getY();
-        final float fromViewEndY = fromAllApps ? -fromView.getHeight() * 2 : workspaceHeight * 2;
-        final float toViewStartY = fromAllApps ? workspaceHeight * 2 : -toView.getHeight() * 2;
-        final float toViewEndY = fromAllApps ? workspaceHeight - toView.getHeight() : 0.0f;
-
-        mCustomizePagedView.endChoiceMode();
-        mAllAppsPagedView.endChoiceMode();
-
-        if (toState == State.ALL_APPS) {
-            mWorkspace.shrink(Workspace.ShrinkState.BOTTOM_HIDDEN, animated);
-        } else {
-            mWorkspace.shrink(Workspace.ShrinkState.TOP, animated);
-        }
-
-        if (animated) {
-            if (mStateAnimation != null) mStateAnimation.cancel();
-            mStateAnimation = new AnimatorSet();
-            mStateAnimation.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    toView.setVisibility(View.VISIBLE);
-                    toView.setY(toViewStartY);
-                    toView.setAlpha(1.0f);
-                }
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    fromView.setVisibility(View.GONE);
-                }
-            });
-
-            AnimatorSet toolbarHideAnim = new AnimatorSet();
-            AnimatorSet toolbarShowAnim = new AnimatorSet();
-            hideAndShowToolbarButtons(toState, toolbarShowAnim, toolbarHideAnim);
-
-            ObjectAnimator fromAnim = ObjectAnimator.ofFloat(fromView, "y",
-                    fromViewStartY, fromViewEndY);
-            fromAnim.setDuration(duration);
-            ObjectAnimator toAnim = ObjectAnimator.ofPropertyValuesHolder(toView,
-                    PropertyValuesHolder.ofFloat("y", toViewStartY, toViewEndY),
-                    PropertyValuesHolder.ofFloat("scaleX", toView.getScaleX(), 1.0f),
-                    PropertyValuesHolder.ofFloat("scaleY", toView.getScaleY(), 1.0f)
-                    );
-            fromAnim.setDuration(duration);
-            mStateAnimation.playTogether(toolbarHideAnim, fromAnim, toAnim);
-
-            // Show the new toolbar buttons just as the main animation is ending
-            final int fadeInTime = res.getInteger(R.integer.config_toolbarButtonFadeInTime);
-            mStateAnimation.play(toolbarShowAnim).after(duration - fadeInTime);
-            mStateAnimation.start();
-        } else {
-            fromView.setY(fromViewEndY);
-            fromView.setVisibility(View.GONE);
-            toView.setY(toViewEndY);
-            toView.setScaleX(1.0f);
-            toView.setScaleY(1.0f);
-            toView.setVisibility(View.VISIBLE);
-            hideAndShowToolbarButtons(toState, null, null);
-        }
-    }
-
-    void showAllApps(boolean animated) {
-        if (mState == State.ALL_APPS) {
-            return;
-        }
-
-        if (LauncherApplication.isScreenXLarge()) {
-            if (mState == State.CUSTOMIZE) {
-                cameraPan(State.CUSTOMIZE, State.ALL_APPS, animated);
-            } else {
-                cameraZoomOut(State.ALL_APPS, animated);
-            }
-        } else {
-            mAllAppsGrid.zoom(1.0f, animated);
-        }
-
-        ((View) mAllAppsGrid).setFocusable(true);
-        ((View) mAllAppsGrid).requestFocus();
-
-        // TODO: fade these two too
-        mDeleteZone.setVisibility(View.GONE);
-
-        // Change the state *after* we've called all the transition code
-        mState = State.ALL_APPS;
-
-        // Pause the auto-advance of widgets until we are out of AllApps
-        mUserPresent = false;
-        updateRunning();
-
-        // send an accessibility event to announce the context change
-        getWindow().getDecorView().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
-    }
-
     void showWorkspace(boolean animated) {
         showWorkspace(animated, null);
     }
@@ -2968,7 +2904,7 @@
         } else {
             mWorkspace.unshrink(animated);
         }
-        if (mState == State.ALL_APPS) {
+        if (mState == State.ALL_APPS || mState == State.APPS_CUSTOMIZE) {
             closeAllApps(animated);
         } else if (mState == State.CUSTOMIZE) {
             hideCustomizationDrawer(animated);
@@ -2987,12 +2923,16 @@
 
     void enterSpringLoadedDragMode(CellLayout layout) {
         mWorkspace.enterSpringLoadedDragMode(layout);
-        if (mState == State.ALL_APPS) {
-            cameraZoomIn(State.ALL_APPS, true, true);
+        if (mState == State.ALL_APPS || mState == State.APPS_CUSTOMIZE) {
             mState = State.ALL_APPS_SPRING_LOADED;
+            if (LauncherApplication.isScreenLarge()) {
+                cameraZoomIn(State.ALL_APPS, true, true);
+            } else {
+                cameraZoomIn(State.APPS_CUSTOMIZE, true, true);
+            }
         } else if (mState == State.CUSTOMIZE) {
-            cameraZoomIn(State.CUSTOMIZE, true, true);
             mState = State.CUSTOMIZE_SPRING_LOADED;
+            cameraZoomIn(State.CUSTOMIZE, true, true);
         }/* else {
             // we're already in spring loaded mode; don't do anything
         }*/
@@ -3001,17 +2941,50 @@
     void exitSpringLoadedDragMode() {
         if (mState == State.ALL_APPS_SPRING_LOADED) {
             mWorkspace.exitSpringLoadedDragMode(Workspace.ShrinkState.BOTTOM_VISIBLE);
-            cameraZoomOut(State.ALL_APPS, true);
-            mState = State.ALL_APPS;
+            if (LauncherApplication.isScreenLarge()) {
+                cameraZoomOut(State.ALL_APPS, true, true);
+                mState = State.ALL_APPS;
+            } else {
+                cameraZoomOut(State.APPS_CUSTOMIZE, true, true);
+                mState = State.APPS_CUSTOMIZE;
+            }
         } else if (mState == State.CUSTOMIZE_SPRING_LOADED) {
             mWorkspace.exitSpringLoadedDragMode(Workspace.ShrinkState.TOP);
-            cameraZoomOut(State.CUSTOMIZE, true);
+            cameraZoomOut(State.CUSTOMIZE, true, true);
             mState = State.CUSTOMIZE;
         }/* else {
             // we're not in spring loaded mode; don't do anything
         }*/
     }
 
+    void showAllApps(boolean animated) {
+        if (mState != State.WORKSPACE) return;
+        if (LauncherApplication.isScreenLarge()) {
+            cameraZoomOut(State.ALL_APPS, animated, false);
+            ((View) mAllAppsGrid).requestFocus();
+
+            // TODO: fade these two too
+            mDeleteZone.setVisibility(View.GONE);
+
+            // Change the state *after* we've called all the transition code
+            mState = State.ALL_APPS;
+        } else {
+            View appsCustomizePane = findViewById(R.id.apps_customize_pane);
+            cameraZoomOut(State.APPS_CUSTOMIZE, animated, false);
+            appsCustomizePane.requestFocus();
+
+            // Change the state *after* we've called all the transition code
+            mState = State.APPS_CUSTOMIZE;
+        }
+
+        // Pause the auto-advance of widgets until we are out of AllApps
+        mUserPresent = false;
+        updateRunning();
+
+        // Send an accessibility event to announce the context change
+        getWindow().getDecorView().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+    }
+
     /**
      * Things to test when changing this code.
      *   - Home from workspace
@@ -3052,15 +3025,22 @@
      *          - From another workspace
      */
     void closeAllApps(boolean animated) {
-        if (mState == State.ALL_APPS || mState == State.ALL_APPS_SPRING_LOADED) {
-            mWorkspace.setVisibility(View.VISIBLE);
-            if (LauncherApplication.isScreenXLarge()) {
-                cameraZoomIn(State.ALL_APPS, animated);
-            } else {
-                mAllAppsGrid.zoom(0.0f, animated);
+        if (LauncherApplication.isScreenLarge()) {
+            if (mState == State.ALL_APPS || mState == State.ALL_APPS_SPRING_LOADED) {
+                mWorkspace.setVisibility(View.VISIBLE);
+                cameraZoomIn(State.ALL_APPS, animated, false);
+
+                // Set focus to the AllApps button
+                findViewById(R.id.all_apps_button).requestFocus();
             }
-            ((View)mAllAppsGrid).setFocusable(false);
-            mWorkspace.getChildAt(mWorkspace.getCurrentPage()).requestFocus();
+        } else {
+            if (mState == State.APPS_CUSTOMIZE || mState == State.ALL_APPS_SPRING_LOADED) {
+                mWorkspace.setVisibility(View.VISIBLE);
+                cameraZoomIn(State.APPS_CUSTOMIZE, animated, false);
+
+                // Set focus to the AllApps button
+                findViewById(R.id.all_apps_button).requestFocus();
+            }
         }
     }
 
@@ -3074,11 +3054,12 @@
 
     // Show the customization drawer (only exists in x-large configuration)
     private void showCustomizationDrawer(boolean animated) {
-        if (mState == State.ALL_APPS) {
-            cameraPan(State.ALL_APPS, State.CUSTOMIZE, animated);
-        } else {
-            cameraZoomOut(State.CUSTOMIZE, animated);
+        if (mState != State.WORKSPACE) {
+            return;
         }
+
+        cameraZoomOut(State.CUSTOMIZE, animated, false);
+
         // Change the state *after* we've called all the transition code
         mState = State.CUSTOMIZE;
 
@@ -3090,13 +3071,22 @@
     // Hide the customization drawer (only exists in x-large configuration)
     void hideCustomizationDrawer(boolean animated) {
         if (mState == State.CUSTOMIZE || mState == State.CUSTOMIZE_SPRING_LOADED) {
-            cameraZoomIn(State.CUSTOMIZE, animated);
+            cameraZoomIn(State.CUSTOMIZE, animated, false);
+
+            // Set focus to the customize button
+            findViewById(R.id.configure_button).requestFocus();
         }
     }
 
-    void addExternalItemToScreen(ItemInfo itemInfo, CellLayout layout) {
+    /**
+     * Add an item from all apps or customize onto the given workspace screen.
+     * If layout is null, add to the current screen.
+     */
+    void addExternalItemToScreen(ItemInfo itemInfo, final CellLayout layout) {
         if (!mWorkspace.addExternalItemToScreen(itemInfo, layout)) {
             showOutOfSpaceMessage();
+        } else {
+            layout.animateDrop();
         }
     }
 
@@ -3104,11 +3094,7 @@
         showWorkspace(true, layout);
     }
 
-    // if successful in getting icon, return it; otherwise, set button to use default drawable
-    private Drawable.ConstantState updateButtonWithIconFromExternalActivity(
-            int buttonId, ComponentName activityName, int fallbackDrawableId) {
-        ImageView button = (ImageView) findViewById(buttonId);
-        Drawable toolbarIcon = null;
+    private Drawable getExternalPackageToolbarIcon(ComponentName activityName) {
         try {
             PackageManager packageManager = getPackageManager();
             // Look for the toolbar icon specified in the activity meta-data
@@ -3118,12 +3104,37 @@
                 int iconResId = metaData.getInt(TOOLBAR_ICON_METADATA_NAME);
                 if (iconResId != 0) {
                     Resources res = packageManager.getResourcesForActivity(activityName);
-                    toolbarIcon = res.getDrawable(iconResId);
+                    return res.getDrawable(iconResId);
                 }
             }
         } catch (NameNotFoundException e) {
             // Do nothing
         }
+        return null;
+    }
+
+    // if successful in getting icon, return it; otherwise, set button to use default drawable
+    private Drawable.ConstantState updateTextButtonWithIconFromExternalActivity(
+            int buttonId, ComponentName activityName, int fallbackDrawableId) {
+        TextView button = (TextView) findViewById(buttonId);
+        Drawable toolbarIcon = getExternalPackageToolbarIcon(activityName);
+
+        // If we were unable to find the icon via the meta-data, use a generic one
+        if (toolbarIcon == null) {
+            button.setCompoundDrawablesWithIntrinsicBounds(fallbackDrawableId, 0, 0, 0);
+            return null;
+        } else {
+            button.setCompoundDrawablesWithIntrinsicBounds(toolbarIcon, null, null, null);
+            return toolbarIcon.getConstantState();
+        }
+    }
+
+    // if successful in getting icon, return it; otherwise, set button to use default drawable
+    private Drawable.ConstantState updateButtonWithIconFromExternalActivity(
+            int buttonId, ComponentName activityName, int fallbackDrawableId) {
+        ImageView button = (ImageView) findViewById(buttonId);
+        Drawable toolbarIcon = getExternalPackageToolbarIcon(activityName);
+
         // If we were unable to find the icon via the meta-data, use a generic one
         if (toolbarIcon == null) {
             button.setImageResource(fallbackDrawableId);
@@ -3134,21 +3145,32 @@
         }
     }
 
+    private void updateTextButtonWithDrawable(int buttonId, Drawable.ConstantState d) {
+        TextView button = (TextView) findViewById(buttonId);
+        button.setCompoundDrawables(d.newDrawable(getResources()), null, null, null);
+    }
+
     private void updateButtonWithDrawable(int buttonId, Drawable.ConstantState d) {
         ImageView button = (ImageView) findViewById(buttonId);
         button.setImageDrawable(d.newDrawable(getResources()));
     }
 
     private void updateGlobalSearchIcon() {
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
+            final View searchButton = findViewById(R.id.search_button);
+            final View searchDivider = findViewById(R.id.search_divider);
+
             final SearchManager searchManager =
                     (SearchManager) getSystemService(Context.SEARCH_SERVICE);
             ComponentName activityName = searchManager.getGlobalSearchActivity();
             if (activityName != null) {
                 sGlobalSearchIcon = updateButtonWithIconFromExternalActivity(
                         R.id.search_button, activityName, R.drawable.ic_generic_search);
+                searchButton.setVisibility(View.VISIBLE);
+                searchDivider.setVisibility(View.VISIBLE);
             } else {
-                findViewById(R.id.search_button).setVisibility(View.GONE);
+                searchButton.setVisibility(View.GONE);
+                searchDivider.setVisibility(View.GONE);
             }
         }
     }
@@ -3158,14 +3180,20 @@
     }
 
     private void updateVoiceSearchIcon() {
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
+            final View searchDivider = findViewById(R.id.search_divider);
+            final View voiceButton = findViewById(R.id.voice_button);
+
             Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
             ComponentName activityName = intent.resolveActivity(getPackageManager());
             if (activityName != null) {
                 sVoiceSearchIcon = updateButtonWithIconFromExternalActivity(
                         R.id.voice_button, activityName, R.drawable.ic_voice_search);
+                searchDivider.setVisibility(View.VISIBLE);
+                voiceButton.setVisibility(View.VISIBLE);
             } else {
-                findViewById(R.id.voice_button).setVisibility(View.GONE);
+                searchDivider.setVisibility(View.GONE);
+                voiceButton.setVisibility(View.GONE);
             }
         }
     }
@@ -3178,21 +3206,26 @@
      * Sets the app market icon (shown when all apps is visible on x-large screens)
      */
     private void updateAppMarketIcon() {
-        if (LauncherApplication.isScreenXLarge()) {
-            Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET);
-            // Find the app market activity by resolving an intent.
-            // (If multiple app markets are installed, it will return the ResolverActivity.)
-            ComponentName activityName = intent.resolveActivity(getPackageManager());
-            if (activityName != null) {
-                mAppMarketIntent = intent;
-                sAppMarketIcon = updateButtonWithIconFromExternalActivity(
-                        R.id.market_button, activityName, R.drawable.app_market_generic);
-            }
+        final View marketButton = findViewById(R.id.market_button);
+        Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET);
+        // Find the app market activity by resolving an intent.
+        // (If multiple app markets are installed, it will return the ResolverActivity.)
+        ComponentName activityName = intent.resolveActivity(getPackageManager());
+        if (activityName != null) {
+            mAppMarketIntent = intent;
+            sAppMarketIcon = updateTextButtonWithIconFromExternalActivity(
+                    R.id.market_button, activityName, R.drawable.app_market_generic);
+            marketButton.setVisibility(View.VISIBLE);
+        } else {
+            // We should hide and disable the view so that we don't try and restore the visibility
+            // of it when we swap between drag & normal states from IconDropTarget subclasses.
+            marketButton.setVisibility(View.GONE);
+            marketButton.setEnabled(false);
         }
     }
 
     private void updateAppMarketIcon(Drawable.ConstantState d) {
-        updateButtonWithDrawable(R.id.market_button, d);
+        updateTextButtonWithDrawable(R.id.market_button, d);
     }
 
     /**
@@ -3261,31 +3294,6 @@
                     break;
                 }
 
-                case AddAdapter.ITEM_LIVE_FOLDER: {
-                    // Insert extra item to handle inserting folder
-                    Bundle bundle = new Bundle();
-
-                    ArrayList<String> shortcutNames = new ArrayList<String>();
-                    shortcutNames.add(res.getString(R.string.group_folder));
-                    bundle.putStringArrayList(Intent.EXTRA_SHORTCUT_NAME, shortcutNames);
-
-                    ArrayList<ShortcutIconResource> shortcutIcons =
-                            new ArrayList<ShortcutIconResource>();
-                    shortcutIcons.add(ShortcutIconResource.fromContext(Launcher.this,
-                            R.drawable.ic_launcher_folder));
-                    bundle.putParcelableArrayList(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, shortcutIcons);
-
-                    Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
-                    pickIntent.putExtra(Intent.EXTRA_INTENT,
-                            new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER));
-                    pickIntent.putExtra(Intent.EXTRA_TITLE,
-                            getText(R.string.title_select_live_folder));
-                    pickIntent.putExtras(bundle);
-
-                    startActivityForResult(pickIntent, REQUEST_PICK_LIVE_FOLDER);
-                    break;
-                }
-
                 case AddAdapter.ITEM_WALLPAPER: {
                     startWallpaper();
                     break;
@@ -3376,6 +3384,8 @@
      */
     public void startBinding() {
         final Workspace workspace = mWorkspace;
+
+        mWorkspace.clearDropTargets();
         int count = workspace.getChildCount();
         for (int i = 0; i < count; i++) {
             // Use removeAllViewsInLayout() to avoid an extra requestLayout() and invalidate().
@@ -3421,21 +3431,13 @@
                     workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1,
                             false);
                     break;
-                case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
+                case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                     final FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
                             (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
-                            (UserFolderInfo) item, mIconCache);
+                            (FolderInfo) item, mIconCache);
                     workspace.addInScreen(newFolder, item.screen, item.cellX, item.cellY, 1, 1,
                             false);
                     break;
-                case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
-                    final FolderIcon newLiveFolder = LiveFolderIcon.fromXml(
-                            R.layout.live_folder_icon, this,
-                            (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
-                            (LiveFolderInfo) item);
-                    workspace.addInScreen(newLiveFolder, item.screen, item.cellX, item.cellY, 1, 1,
-                            false);
-                    break;
             }
         }
 
@@ -3504,12 +3506,14 @@
                 mWorkspace.getChildAt(mWorkspace.getCurrentPage()).requestFocus();
             }
 
-            final long[] userFolders = mSavedState.getLongArray(RUNTIME_STATE_USER_FOLDERS);
-            if (userFolders != null) {
-                for (long folderId : userFolders) {
+            final long[] folders = mSavedState.getLongArray(RUNTIME_STATE_FOLDERS);
+            if (folders != null) {
+                for (long folderId : folders) {
                     final FolderInfo info = sFolders.get(folderId);
-                    if (info != null) {
-                        openFolder(info);
+                    final FolderIcon folderIcon = (FolderIcon)
+                        mWorkspace.getViewForTag(info);
+                    if (folderIcon != null) {
+                        openFolder(folderIcon);
                     }
                 }
                 final Folder openFolder = mWorkspace.getOpenFolder();
@@ -3528,7 +3532,7 @@
 
         // Workaround a bug that occurs when rotating the device while the customization mode is
         // open, we trigger a new layout on all the CellLayout children.
-        if (LauncherApplication.isScreenXLarge() && (mState == State.CUSTOMIZE)) {
+        if (LauncherApplication.isScreenLarge() && (mState == State.CUSTOMIZE)) {
             final int childCount = mWorkspace.getChildCount();
             for (int i = 0; i < childCount; ++i) {
                 mWorkspace.getChildAt(i).requestLayout();
@@ -3536,6 +3540,13 @@
         }
 
         mWorkspaceLoading = false;
+
+        // If we received the result of any pending adds while the loader was running (e.g. the
+        // widget configuration forced an orientation change), process them now.
+        for (int i = 0; i < sPendingAddList.size(); i++) {
+            completeAdd(sPendingAddList.get(i));
+        }
+        sPendingAddList.clear();
     }
 
     /**
@@ -3554,7 +3565,12 @@
      * Implementation of the method from LauncherModel.Callbacks.
      */
     public void bindAllApplications(ArrayList<ApplicationInfo> apps) {
-        mAllAppsGrid.setApps(apps);
+        if (mAllAppsGrid != null) {
+            mAllAppsGrid.setApps(apps);
+        }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.setApps(apps);
+        }
         if (mCustomizePagedView != null) {
             mCustomizePagedView.setApps(apps);
         }
@@ -3569,7 +3585,12 @@
     public void bindAppsAdded(ArrayList<ApplicationInfo> apps) {
         setLoadOnResume();
         removeDialog(DIALOG_CREATE_SHORTCUT);
-        mAllAppsGrid.addApps(apps);
+        if (mAllAppsGrid != null) {
+            mAllAppsGrid.addApps(apps);
+        }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.addApps(apps);
+        }
         if (mCustomizePagedView != null) {
             mCustomizePagedView.addApps(apps);
         }
@@ -3584,8 +3605,15 @@
     public void bindAppsUpdated(ArrayList<ApplicationInfo> apps) {
         setLoadOnResume();
         removeDialog(DIALOG_CREATE_SHORTCUT);
-        mWorkspace.updateShortcuts(apps);
-        mAllAppsGrid.updateApps(apps);
+        if (mWorkspace != null) {
+            mWorkspace.updateShortcuts(apps);
+        }
+        if (mAllAppsGrid != null) {
+            mAllAppsGrid.updateApps(apps);
+        }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.updateApps(apps);
+        }
         if (mCustomizePagedView != null) {
             mCustomizePagedView.updateApps(apps);
         }
@@ -3602,7 +3630,12 @@
         if (permanent) {
             mWorkspace.removeItems(apps);
         }
-        mAllAppsGrid.removeApps(apps);
+        if (mAllAppsGrid != null) {
+            mAllAppsGrid.removeApps(apps);
+        }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.removeApps(apps);
+        }
         if (mCustomizePagedView != null) {
             mCustomizePagedView.removeApps(apps);
         }
@@ -3617,6 +3650,9 @@
         if (mCustomizePagedView != null) {
             mCustomizePagedView.update();
         }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.onPackagesUpdated();
+        }
     }
 
     private int mapConfigurationOriActivityInfoOri(int configOri) {
@@ -3675,7 +3711,17 @@
         Log.d(TAG, "mDesktopItems.size=" + mDesktopItems.size());
         Log.d(TAG, "sFolders.size=" + sFolders.size());
         mModel.dumpState();
-        mAllAppsGrid.dumpState();
+        if (mAllAppsGrid != null) {
+            mAllAppsGrid.dumpState();
+        }
+        if (mAppsCustomizeContent != null) {
+            mAppsCustomizeContent.dumpState();
+        }
         Log.d(TAG, "END launcher2 dump state");
     }
 }
+
+interface LauncherTransitionable {
+    void onLauncherTransitionStart(Animator animation);
+    void onLauncherTransitionEnd(Animator animation);
+}
diff --git a/src/com/android/launcher2/LauncherAnimatorUpdateListener.java b/src/com/android/launcher2/LauncherAnimatorUpdateListener.java
new file mode 100644
index 0000000..dd82113
--- /dev/null
+++ b/src/com/android/launcher2/LauncherAnimatorUpdateListener.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+
+abstract class LauncherAnimatorUpdateListener implements AnimatorUpdateListener {
+    public void onAnimationUpdate(ValueAnimator animation) {
+        final float b = (Float) animation.getAnimatedValue();
+        final float a = 1f - b;
+        onAnimationUpdate(a, b);
+    }
+
+    abstract void onAnimationUpdate(float a, float b);
+}
\ No newline at end of file
diff --git a/src/com/android/launcher2/LauncherAppWidgetHostView.java b/src/com/android/launcher2/LauncherAppWidgetHostView.java
index 85a80f9..0dd1d83 100644
--- a/src/com/android/launcher2/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher2/LauncherAppWidgetHostView.java
@@ -22,6 +22,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
+import android.view.ViewGroup;
 
 import com.android.launcher.R;
 
@@ -72,7 +73,7 @@
         // Otherwise continue letting touch events fall through to children
         return false;
     }
-    
+
     class CheckForLongPress implements Runnable {
         private int mOriginalWindowAttachCount;
 
@@ -122,4 +123,9 @@
         }
         super.onVisibilityChanged(changedView, visibility);
     }
+
+    @Override
+    public int getDescendantFocusability() {
+        return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+    }
 }
diff --git a/src/com/android/launcher2/LauncherApplication.java b/src/com/android/launcher2/LauncherApplication.java
index ed007dd..67573e0 100644
--- a/src/com/android/launcher2/LauncherApplication.java
+++ b/src/com/android/launcher2/LauncherApplication.java
@@ -23,23 +23,22 @@
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.os.Handler;
-import dalvik.system.VMRuntime;
 
 public class LauncherApplication extends Application {
     public LauncherModel mModel;
     public IconCache mIconCache;
-    private static boolean sIsScreenXLarge;
+    private static boolean sIsScreenLarge;
     private static float sScreenDensity;
     private static final boolean ENABLE_ROTATION = false;
 
     @Override
     public void onCreate() {
-        VMRuntime.getRuntime().setMinimumHeapSize(4 * 1024 * 1024);
-
         super.onCreate();
 
         // set sIsScreenXLarge and sScreenDensity *before* creating icon cache
-        sIsScreenXLarge = (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE;
+        final int screenSize = getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
+        sIsScreenLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE ||
+            screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE;
         sScreenDensity = getResources().getDisplayMetrics().density;
 
         mIconCache = new IconCache(this);
@@ -100,11 +99,11 @@
     }
 
     public static boolean isInPlaceRotationEnabled() {
-        return sIsScreenXLarge && ENABLE_ROTATION;
+        return sIsScreenLarge && ENABLE_ROTATION;
     }
 
-    public static boolean isScreenXLarge() {
-        return sIsScreenXLarge;
+    public static boolean isScreenLarge() {
+        return sIsScreenLarge;
     }
 
     public static float getScreenDensity() {
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 0052737..d5505c5 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -37,13 +37,13 @@
 import android.content.Intent.ShortcutIconResource;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Parcelable;
@@ -65,6 +65,7 @@
     static final String TAG = "Launcher.Model";
 
     private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
+    private final boolean mAppsCanBeOnExternalStorage;
     private int mBatchSize; // 0 is all apps at once
     private int mAllAppsLoadDelay; // milliseconds between batches
 
@@ -89,9 +90,6 @@
 
     private AllAppsList mAllAppsList; // only access in worker thread
     private IconCache mIconCache;
-    final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
-    final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
-    final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
 
     private Bitmap mDefaultIcon;
 
@@ -115,6 +113,7 @@
     }
 
     LauncherModel(LauncherApplication app, IconCache iconCache) {
+        mAppsCanBeOnExternalStorage = !Environment.isExternalStorageEmulated();
         mApp = app;
         mAllAppsList = new AllAppsList(iconCache);
         mIconCache = iconCache;
@@ -174,6 +173,33 @@
     }
 
     /**
+     * Resize an item in the DB to a new <spanX, spanY, cellX, cellY>
+     */
+    static void resizeItemInDatabase(Context context, ItemInfo item, int cellX, int cellY,
+            int spanX, int spanY) {
+        item.spanX = spanX;
+        item.spanY = spanY;
+        item.cellX = cellX;
+        item.cellY = cellY;
+
+        final Uri uri = LauncherSettings.Favorites.getContentUri(item.id, false);
+        final ContentValues values = new ContentValues();
+        final ContentResolver cr = context.getContentResolver();
+
+        values.put(LauncherSettings.Favorites.CONTAINER, item.container);
+        values.put(LauncherSettings.Favorites.SPANX, spanX);
+        values.put(LauncherSettings.Favorites.SPANY, spanY);
+        values.put(LauncherSettings.Favorites.CELLX, cellX);
+        values.put(LauncherSettings.Favorites.CELLY, cellY);
+
+        sWorker.post(new Runnable() {
+                public void run() {
+                    cr.update(uri, values, null, null);
+                }
+            });
+    }
+
+    /**
      * Returns true if the shortcuts already exists in the database.
      * we identify a shortcut by its title and intent.
      */
@@ -241,8 +267,7 @@
         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,
                 "_id=? and (itemType=? or itemType=?)",
                 new String[] { String.valueOf(id),
-                        String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER),
-                        String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER) }, null);
+                        String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)}, null);
 
         try {
             if (c.moveToFirst()) {
@@ -255,11 +280,8 @@
 
                 FolderInfo folderInfo = null;
                 switch (c.getInt(itemTypeIndex)) {
-                    case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
-                        folderInfo = findOrMakeUserFolder(folderList, id);
-                        break;
-                    case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
-                        folderInfo = findOrMakeLiveFolder(folderList, id);
+                    case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+                        folderInfo = findOrMakeFolder(folderList, id);
                         break;
                 }
 
@@ -361,7 +383,7 @@
     /**
      * Remove the contents of the specified folder from the database
      */
-    static void deleteUserFolderContentsFromDatabase(Context context, UserFolderInfo info) {
+    static void deleteFolderContentsFromDatabase(Context context, FolderInfo info) {
         final ContentResolver cr = context.getContentResolver();
 
         cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
@@ -492,9 +514,6 @@
                 mLoaderTask.stopLocked();
             }
         }
-        mItems.clear();
-        mAppWidgets.clear();
-        mFolders.clear();
     }
 
     /**
@@ -510,6 +529,10 @@
         private boolean mStopped;
         private boolean mLoadAndBindStepFinished;
 
+        final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
+        final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
+        final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
+
         LoaderTask(Context context, boolean isLaunching) {
             mContext = context;
             mIsLaunching = isLaunching;
@@ -629,22 +652,6 @@
                     mLoaderTask = null;
                 }
             }
-
-            // Trigger a gc to try to clean up after the stuff is done, since the
-            // renderscript allocations aren't charged to the java heap.
-            if (mStopped) {
-                mHandler.post(new Runnable() {
-                        public void run() {
-                            System.gc();
-                        }
-                    });
-            } else {
-                mHandler.postIdle(new Runnable() {
-                        public void run() {
-                            System.gc();
-                        }
-                    });
-            }
         }
 
         public void stopLocked() {
@@ -794,8 +801,6 @@
                             }
 
                             if (info != null) {
-                                updateSavedIcon(context, info, c, iconIndex);
-
                                 info.intent = intent;
                                 info.id = c.getLong(idIndex);
                                 container = c.getInt(containerIndex);
@@ -815,11 +820,15 @@
                                     break;
                                 default:
                                     // Item is in a user folder
-                                    UserFolderInfo folderInfo =
-                                            findOrMakeUserFolder(mFolders, container);
+                                    FolderInfo folderInfo =
+                                            findOrMakeFolder(mFolders, container);
                                     folderInfo.add(info);
                                     break;
                                 }
+
+                                // now that we've loaded everthing re-save it with the
+                                // icon in case it disappears somehow.
+                                updateSavedIcon(context, info, c, iconIndex);
                             } else {
                                 // Failed to load the shortcut, probably because the
                                 // activity manager couldn't resolve it (maybe the app
@@ -832,9 +841,9 @@
                             }
                             break;
 
-                        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
+                        case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                             id = c.getLong(idIndex);
-                            UserFolderInfo folderInfo = findOrMakeUserFolder(mFolders, id);
+                            FolderInfo folderInfo = findOrMakeFolder(mFolders, id);
 
                             folderInfo.title = c.getString(titleIndex);
                             folderInfo.id = id;
@@ -857,57 +866,6 @@
                             mFolders.put(folderInfo.id, folderInfo);
                             break;
 
-                        case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
-                            id = c.getLong(idIndex);
-                            Uri uri = Uri.parse(c.getString(uriIndex));
-
-                            // Make sure the live folder exists
-                            final ProviderInfo providerInfo =
-                                    context.getPackageManager().resolveContentProvider(
-                                            uri.getAuthority(), 0);
-
-                            if (providerInfo == null && !isSafeMode) {
-                                itemsToRemove.add(id);
-                            } else {
-                                LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(mFolders, id);
-                                intentDescription = c.getString(intentIndex);
-                                intent = null;
-                                if (intentDescription != null) {
-                                    try {
-                                        intent = Intent.parseUri(intentDescription, 0);
-                                    } catch (URISyntaxException e) {
-                                        // Ignore, a live folder might not have a base intent
-                                    }
-                                }
-
-                                liveFolderInfo.title = c.getString(titleIndex);
-                                liveFolderInfo.id = id;
-                                liveFolderInfo.uri = uri;
-                                container = c.getInt(containerIndex);
-                                liveFolderInfo.container = container;
-                                liveFolderInfo.screen = c.getInt(screenIndex);
-                                liveFolderInfo.cellX = c.getInt(cellXIndex);
-                                liveFolderInfo.cellY = c.getInt(cellYIndex);
-                                liveFolderInfo.baseIntent = intent;
-                                liveFolderInfo.displayMode = c.getInt(displayModeIndex);
-
-                                // check & update map of what's occupied
-                                if (!checkItemPlacement(occupied, liveFolderInfo)) {
-                                    break;
-                                }
-
-                                loadLiveFolderIcon(context, c, iconTypeIndex, iconPackageIndex,
-                                        iconResourceIndex, liveFolderInfo);
-
-                                switch (container) {
-                                    case LauncherSettings.Favorites.CONTAINER_DESKTOP:
-                                        mItems.add(liveFolderInfo);
-                                        break;
-                                }
-                                mFolders.put(liveFolderInfo.id, liveFolderInfo);
-                            }
-                            break;
-
                         case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
                             // Read all Launcher-specific widget details
                             int appWidgetId = c.getInt(appWidgetIdIndex);
@@ -1262,6 +1220,7 @@
             Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);
             Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);
             Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
+            Log.d(TAG, "mItems size=" + mItems.size());
         }
     }
 
@@ -1591,13 +1550,11 @@
         Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
 
         Bitmap icon = null;
-        boolean filtered = false;
         boolean customIcon = false;
         ShortcutIconResource iconResource = null;
 
         if (bitmap != null && bitmap instanceof Bitmap) {
             icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);
-            filtered = true;
             customIcon = true;
         } else {
             Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
@@ -1636,39 +1593,11 @@
         return info;
     }
 
-    private void loadLiveFolderIcon(Context context, Cursor c, int iconTypeIndex,
-            int iconPackageIndex, int iconResourceIndex, LiveFolderInfo liveFolderInfo) {
-
-        int iconType = c.getInt(iconTypeIndex);
-        switch (iconType) {
-        case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
-            String packageName = c.getString(iconPackageIndex);
-            String resourceName = c.getString(iconResourceIndex);
-            PackageManager packageManager = context.getPackageManager();
-            try {
-                Resources appResources = packageManager.getResourcesForApplication(packageName);
-                final int id = appResources.getIdentifier(resourceName, null, null);
-                liveFolderInfo.icon = Utilities.createIconBitmap(
-                        mIconCache.getFullResIcon(appResources, id), context);
-            } catch (Exception e) {
-                Resources resources = context.getResources();
-                liveFolderInfo.icon = Utilities.createIconBitmap(
-                        mIconCache.getFullResIcon(resources, R.drawable.ic_launcher_folder),
-                        context);
-            }
-            liveFolderInfo.iconResource = new Intent.ShortcutIconResource();
-            liveFolderInfo.iconResource.packageName = packageName;
-            liveFolderInfo.iconResource.resourceName = resourceName;
-            break;
-        default:
-            Resources resources = context.getResources();
-            liveFolderInfo.icon = Utilities.createIconBitmap(
-                    mIconCache.getFullResIcon(resources, R.drawable.ic_launcher_folder),
-                    context);
-        }
-    }
-
     void updateSavedIcon(Context context, ShortcutInfo info, Cursor c, int iconIndex) {
+        // If apps can't be on SD, don't even bother.
+        if (!mAppsCanBeOnExternalStorage) {
+            return;
+        }
         // If this icon doesn't have a custom icon, check to see
         // what's stored in the DB, and if it doesn't match what
         // we're going to show, store what we are going to show back
@@ -1691,53 +1620,26 @@
             }
             if (needSave) {
                 Log.d(TAG, "going to save icon bitmap for info=" + info);
-                // This is slower than is ideal, but this only happens either
-                // after the froyo OTA or when the app is updated with a new
-                // icon.
+                // This is slower than is ideal, but this only happens once
+                // or when the app is updated with a new icon.
                 updateItemInDatabase(context, info);
             }
         }
     }
 
     /**
-     * Return an existing UserFolderInfo object if we have encountered this ID previously,
+     * Return an existing FolderInfo object if we have encountered this ID previously,
      * or make a new one.
      */
-    private static UserFolderInfo findOrMakeUserFolder(HashMap<Long, FolderInfo> folders, long id) {
+    private static FolderInfo findOrMakeFolder(HashMap<Long, FolderInfo> folders, long id) {
         // See if a placeholder was created for us already
         FolderInfo folderInfo = folders.get(id);
-        if (folderInfo == null || !(folderInfo instanceof UserFolderInfo)) {
+        if (folderInfo == null) {
             // No placeholder -- create a new instance
-            folderInfo = new UserFolderInfo();
+            folderInfo = new FolderInfo();
             folders.put(id, folderInfo);
         }
-        return (UserFolderInfo) folderInfo;
-    }
-
-    /**
-     * Return an existing UserFolderInfo object if we have encountered this ID previously, or make a
-     * new one.
-     */
-    private static LiveFolderInfo findOrMakeLiveFolder(HashMap<Long, FolderInfo> folders, long id) {
-        // See if a placeholder was created for us already
-        FolderInfo folderInfo = folders.get(id);
-        if (folderInfo == null || !(folderInfo instanceof LiveFolderInfo)) {
-            // No placeholder -- create a new instance
-            folderInfo = new LiveFolderInfo();
-            folders.put(id, folderInfo);
-        }
-        return (LiveFolderInfo) folderInfo;
-    }
-
-    private static String getLabel(PackageManager manager, ActivityInfo activityInfo) {
-        String label = activityInfo.loadLabel(manager).toString();
-        if (label == null) {
-            label = manager.getApplicationLabel(activityInfo.applicationInfo).toString();
-            if (label == null) {
-                label = activityInfo.name;
-            }
-        }
-        return label;
+        return folderInfo;
     }
 
     private static final Collator sCollator = Collator.getInstance();
@@ -1755,6 +1657,48 @@
             return 0;
         }
     };
+    public static final Comparator<AppWidgetProviderInfo> WIDGET_NAME_COMPARATOR
+            = new Comparator<AppWidgetProviderInfo>() {
+        public final int compare(AppWidgetProviderInfo a, AppWidgetProviderInfo b) {
+            return sCollator.compare(a.label.toString(), b.label.toString());
+        }
+    };
+    public static class ShortcutNameComparator implements Comparator<ResolveInfo> {
+        private PackageManager mPackageManager;
+        private HashMap<Object, String> mLabelCache;
+        ShortcutNameComparator(PackageManager pm) {
+            mPackageManager = pm;
+            mLabelCache = new HashMap<Object, String>();
+        }
+        public final int compare(ResolveInfo a, ResolveInfo b) {
+            String labelA, labelB;
+            if (mLabelCache.containsKey(a)) labelA = mLabelCache.get(a);
+            else labelA = a.loadLabel(mPackageManager).toString();
+            if (mLabelCache.containsKey(b)) labelB = mLabelCache.get(b);
+            else labelB = b.loadLabel(mPackageManager).toString();
+            return sCollator.compare(labelA, labelB);
+        }
+    };
+    public static class WidgetAndShortcutNameComparator implements Comparator<Object> {
+        private PackageManager mPackageManager;
+        private HashMap<Object, String> mLabelCache;
+        WidgetAndShortcutNameComparator(PackageManager pm) {
+            mPackageManager = pm;
+            mLabelCache = new HashMap<Object, String>();
+        }
+        public final int compare(Object a, Object b) {
+            String labelA, labelB;
+            if (mLabelCache.containsKey(a)) labelA = mLabelCache.get(a);
+            else labelA = (a instanceof AppWidgetProviderInfo) ?
+                    ((AppWidgetProviderInfo) a).label :
+                    ((ResolveInfo) a).loadLabel(mPackageManager).toString();
+            if (mLabelCache.containsKey(b)) labelB = mLabelCache.get(b);
+            else labelB = (b instanceof AppWidgetProviderInfo) ?
+                    ((AppWidgetProviderInfo) b).label :
+                    ((ResolveInfo) b).loadLabel(mPackageManager).toString();
+            return sCollator.compare(labelA, labelB);
+        }
+    };
 
     public void dumpState() {
         Log.d(TAG, "mCallbacks=" + mCallbacks);
@@ -1762,7 +1706,6 @@
         ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.added", mAllAppsList.added);
         ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.removed", mAllAppsList.removed);
         ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.modified", mAllAppsList.modified);
-        Log.d(TAG, "mItems size=" + mItems.size());
         if (mLoaderTask != null) {
             mLoaderTask.dumpState();
         } else {
diff --git a/src/com/android/launcher2/LauncherSettings.java b/src/com/android/launcher2/LauncherSettings.java
index 9c685ce..c378405 100644
--- a/src/com/android/launcher2/LauncherSettings.java
+++ b/src/com/android/launcher2/LauncherSettings.java
@@ -16,8 +16,8 @@
 
 package com.android.launcher2;
 
-import android.provider.BaseColumns;
 import android.net.Uri;
+import android.provider.BaseColumns;
 
 /**
  * Settings related utilities.
@@ -169,11 +169,15 @@
         /**
          * The favorite is a user created folder
          */
-        static final int ITEM_TYPE_USER_FOLDER = 2;
+        static final int ITEM_TYPE_FOLDER = 2;
 
         /**
-         * The favorite is a live folder
-         */
+        * The favorite is a live folder
+        *
+        * Note: live folders can no longer be added to Launcher, and any live folders which
+        * exist within the launcher database will be ignored when loading.  That said, these
+        * entries in the database may still exist, and are not automatically stripped.
+        */
         static final int ITEM_TYPE_LIVE_FOLDER = 3;
 
         /**
diff --git a/src/com/android/launcher2/LiveFolder.java b/src/com/android/launcher2/LiveFolder.java
deleted file mode 100644
index 07a295f..0000000
--- a/src/com/android/launcher2/LiveFolder.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.launcher2;
-
-import android.content.Context;
-import android.content.Intent;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-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;
-
-import com.android.launcher.R;
-
-public class LiveFolder extends Folder {
-    private AsyncTask<LiveFolderInfo,Void,Cursor> mLoadingTask;
-
-    public LiveFolder(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    static LiveFolder fromXml(Context context, FolderInfo folderInfo) {
-        final int layout = isDisplayModeList(folderInfo) ?
-                R.layout.live_folder_list : R.layout.live_folder_grid;
-        return (LiveFolder) LayoutInflater.from(context).inflate(layout, null);
-    }
-
-    private static boolean isDisplayModeList(FolderInfo folderInfo) {
-        return ((LiveFolderInfo) folderInfo).displayMode ==
-                LiveFolders.DISPLAY_MODE_LIST;
-    }
-
-    @Override
-    public void onItemClick(AdapterView parent, View v, int position, long id) {
-        LiveFolderAdapter.ViewHolder holder = (LiveFolderAdapter.ViewHolder) v.getTag();
-
-        if (holder.useBaseIntent) {
-            final Intent baseIntent = ((LiveFolderInfo) mInfo).baseIntent;
-            if (baseIntent != null) {
-                final Intent intent = new Intent(baseIntent);
-                Uri uri = baseIntent.getData();
-                uri = uri.buildUpon().appendPath(Long.toString(holder.id)).build();
-                intent.setData(uri);
-                mLauncher.startActivitySafely(intent, "(position=" + position + ", id=" + id + ")");
-            }
-        } else if (holder.intent != null) {
-            mLauncher.startActivitySafely(holder.intent,
-                    "(position=" + position + ", id=" + id + ")");
-        }
-    }
-
-    @Override
-    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
-        return false;
-    }
-
-    void bind(FolderInfo info) {
-        super.bind(info);
-        if (mLoadingTask != null && mLoadingTask.getStatus() == AsyncTask.Status.RUNNING) {
-            mLoadingTask.cancel(true);
-        }
-        mLoadingTask = new FolderLoadingTask(this).execute((LiveFolderInfo) info);
-    }
-
-    @Override
-    void onOpen() {
-        super.onOpen();
-        requestFocus();
-    }
-
-    @Override
-    void onClose() {
-        super.onClose();
-        if (mLoadingTask != null && mLoadingTask.getStatus() == AsyncTask.Status.RUNNING) {
-            mLoadingTask.cancel(true);
-        }
-
-        // The adapter can be null if onClose() is called before FolderLoadingTask
-        // is done querying the provider
-        final LiveFolderAdapter adapter = (LiveFolderAdapter) mContent.getAdapter();
-        if (adapter != null) {
-            adapter.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/launcher2/LiveFolderAdapter.java b/src/com/android/launcher2/LiveFolderAdapter.java
deleted file mode 100644
index fb9c6a3..0000000
--- a/src/com/android/launcher2/LiveFolderAdapter.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * 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.launcher2;
-
-import android.widget.CursorAdapter;
-import android.widget.TextView;
-import android.widget.ImageView;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.content.pm.PackageManager;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-import android.database.Cursor;
-import android.provider.LiveFolders;
-import android.graphics.drawable.Drawable;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
-
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.lang.ref.SoftReference;
-
-import com.android.launcher.R;
-
-class LiveFolderAdapter extends CursorAdapter {
-    private boolean mIsList;
-    private LayoutInflater mInflater;
-
-    private final HashMap<String, Drawable> mIcons = new HashMap<String, Drawable>();
-    private final HashMap<Long, SoftReference<Drawable>> mCustomIcons =
-            new HashMap<Long, SoftReference<Drawable>>();
-    private final Launcher mLauncher;
-
-    LiveFolderAdapter(Launcher launcher, LiveFolderInfo info, Cursor cursor) {
-        super(launcher, cursor, true);
-        mIsList = info.displayMode == LiveFolders.DISPLAY_MODE_LIST;
-        mInflater = LayoutInflater.from(launcher);
-        mLauncher = launcher;
-
-        mLauncher.startManagingCursor(getCursor());
-    }
-
-    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) {
-        View view;
-        final ViewHolder holder = new ViewHolder();
-
-        if (!mIsList) {
-            view = mInflater.inflate(R.layout.application_boxed, parent, false);
-        } else {
-            view = mInflater.inflate(R.layout.application_list, parent, false);
-            holder.description = (TextView) view.findViewById(R.id.description);
-            holder.icon = (ImageView) view.findViewById(R.id.icon);
-        }
-
-        holder.name = (TextView) view.findViewById(R.id.name);
-
-        holder.idIndex = cursor.getColumnIndexOrThrow(LiveFolders._ID);
-        holder.nameIndex = cursor.getColumnIndexOrThrow(LiveFolders.NAME);
-        holder.descriptionIndex = cursor.getColumnIndex(LiveFolders.DESCRIPTION);
-        holder.intentIndex = cursor.getColumnIndex(LiveFolders.INTENT);
-        holder.iconBitmapIndex = cursor.getColumnIndex(LiveFolders.ICON_BITMAP);
-        holder.iconResourceIndex = cursor.getColumnIndex(LiveFolders.ICON_RESOURCE);
-        holder.iconPackageIndex = cursor.getColumnIndex(LiveFolders.ICON_PACKAGE);
-
-        view.setTag(holder);
-
-        return view;
-    }
-
-    public void bindView(View view, Context context, Cursor cursor) {
-        final ViewHolder holder = (ViewHolder) view.getTag();
-
-        holder.id = cursor.getLong(holder.idIndex);
-        final Drawable icon = loadIcon(context, cursor, holder);
-
-        holder.name.setText(cursor.getString(holder.nameIndex));
-
-        if (!mIsList) {
-            holder.name.setCompoundDrawablesWithIntrinsicBounds(null, icon, null, null);
-        } else {
-            final boolean hasIcon = icon != null;
-            holder.icon.setVisibility(hasIcon ? View.VISIBLE : View.GONE);
-            if (hasIcon) holder.icon.setImageDrawable(icon);
-
-            if (holder.descriptionIndex != -1) {
-                final String description = cursor.getString(holder.descriptionIndex);
-                if (description != null) {
-                    holder.description.setText(description);
-                    holder.description.setVisibility(View.VISIBLE);
-                } else {
-                    holder.description.setVisibility(View.GONE);                    
-                }
-            } else {
-                holder.description.setVisibility(View.GONE);                
-            }
-        }
-
-        if (holder.intentIndex != -1) {
-            try {
-                holder.intent = Intent.parseUri(cursor.getString(holder.intentIndex), 0);
-            } catch (URISyntaxException e) {
-                // Ignore
-            }
-        } else {
-            holder.useBaseIntent = true;
-        }
-    }
-
-    private Drawable loadIcon(Context context, Cursor cursor, ViewHolder holder) {
-        Drawable icon = null;
-        byte[] data = null;
-
-        if (holder.iconBitmapIndex != -1) {
-            data = cursor.getBlob(holder.iconBitmapIndex);
-        }
-
-        if (data != null) {
-            final SoftReference<Drawable> reference = mCustomIcons.get(holder.id);
-            if (reference != null) {
-                icon = reference.get();
-            }
-
-            if (icon == null) {
-                final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
-                final Bitmap resampled = Utilities.resampleIconBitmap(bitmap, mContext);
-                if (bitmap != resampled) {
-                    // If we got back a different object, we don't need the old one any more.
-                    bitmap.recycle();
-                }
-                icon = new FastBitmapDrawable(resampled);
-                mCustomIcons.put(holder.id, new SoftReference<Drawable>(icon));
-            }
-        } else if (holder.iconResourceIndex != -1 && holder.iconPackageIndex != -1) {
-            final String resource = cursor.getString(holder.iconResourceIndex);
-            icon = mIcons.get(resource);
-            if (icon == null) {
-                try {
-                    final PackageManager packageManager = context.getPackageManager();
-                    Resources resources = packageManager.getResourcesForApplication(
-                            cursor.getString(holder.iconPackageIndex));
-                    final int id = resources.getIdentifier(resource,
-                            null, null);
-                    icon = new FastBitmapDrawable(
-                            Utilities.createIconBitmap(resources.getDrawable(id), mContext));
-                    mIcons.put(resource, icon);
-                } catch (Exception e) {
-                    // Ignore
-                }
-            }
-        }
-
-        return icon;
-    }
-
-    void cleanup() {
-        for (Drawable icon : mIcons.values()) {
-            icon.setCallback(null);
-        }
-        mIcons.clear();
-
-        for (SoftReference<Drawable> icon : mCustomIcons.values()) {
-            final Drawable drawable = icon.get();
-            if (drawable != null) {
-                drawable.setCallback(null);
-            }
-        }
-        mCustomIcons.clear();
-
-        final Cursor cursor = getCursor();
-        if (cursor != null) {
-            try {
-                cursor.close();
-            } finally {
-                mLauncher.stopManagingCursor(cursor);
-            }
-        }
-    }
-
-    static class ViewHolder {
-        TextView name;
-        TextView description;
-        ImageView icon;
-
-        Intent intent;
-        long id;
-        boolean useBaseIntent;
-
-        int idIndex;
-        int nameIndex;
-        int descriptionIndex = -1;
-        int intentIndex = -1;
-        int iconBitmapIndex = -1;
-        int iconResourceIndex = -1;
-        int iconPackageIndex = -1;
-    }
-}
diff --git a/src/com/android/launcher2/LiveFolderIcon.java b/src/com/android/launcher2/LiveFolderIcon.java
deleted file mode 100644
index 5b73a59..0000000
--- a/src/com/android/launcher2/LiveFolderIcon.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.launcher2;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.AttributeSet;
-import android.view.ViewGroup;
-import android.view.LayoutInflater;
-import android.graphics.Bitmap;
-
-import com.android.launcher.R;
-
-public class LiveFolderIcon extends FolderIcon {
-    public LiveFolderIcon(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public LiveFolderIcon(Context context) {
-        super(context);
-    }
-
-    static LiveFolderIcon fromXml(int resId, Launcher launcher, ViewGroup group,
-            LiveFolderInfo folderInfo) {
-
-        LiveFolderIcon icon = (LiveFolderIcon)
-                LayoutInflater.from(launcher).inflate(resId, group, false);
-
-        final Resources resources = launcher.getResources();
-        Bitmap b = folderInfo.icon;
-        if (b == null) {
-            b = Utilities.createIconBitmap(resources.getDrawable(R.drawable.ic_launcher_folder),
-                    launcher);
-        }
-        icon.setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(b), null, null);
-        icon.setText(folderInfo.title);
-        icon.setTag(folderInfo);
-        icon.setOnClickListener(launcher);
-        
-        return icon;
-    }
-
-    @Override
-    public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-        return false;
-    }
-
-    @Override
-    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-    }
-
-    @Override
-    public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-    }
-
-    @Override
-    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-    }
-
-    @Override
-    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-    }
-}
diff --git a/src/com/android/launcher2/LiveFolderInfo.java b/src/com/android/launcher2/LiveFolderInfo.java
deleted file mode 100644
index 74b0217..0000000
--- a/src/com/android/launcher2/LiveFolderInfo.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.launcher2;
-
-import android.content.ContentValues;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.net.Uri;
-
-class LiveFolderInfo extends FolderInfo {
-
-    /**
-     * The base intent, if it exists.
-     */
-    Intent baseIntent;
-
-    /**
-     * The live folder's content uri.
-     */
-    Uri uri;
-
-    /**
-     * The live folder's display type.
-     */
-    int displayMode;
-
-    /**
-     * The live folder icon.
-     */
-    Bitmap icon;
-
-    /**
-     * Reference to the live folder icon as an application's resource.
-     */
-    Intent.ShortcutIconResource iconResource;
-
-    LiveFolderInfo() {
-        itemType = LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER;
-    }
-
-    @Override
-    void onAddToDatabase(ContentValues values) {
-        super.onAddToDatabase(values);
-        values.put(LauncherSettings.Favorites.TITLE, title.toString());
-        values.put(LauncherSettings.Favorites.URI, uri.toString());
-        if (baseIntent != null) {
-            values.put(LauncherSettings.Favorites.INTENT, baseIntent.toUri(0));
-        }
-        values.put(LauncherSettings.Favorites.ICON_TYPE, LauncherSettings.Favorites.ICON_TYPE_RESOURCE);
-        values.put(LauncherSettings.Favorites.DISPLAY_MODE, displayMode);
-        if (iconResource != null) {
-            values.put(LauncherSettings.Favorites.ICON_PACKAGE, iconResource.packageName);
-            values.put(LauncherSettings.Favorites.ICON_RESOURCE, iconResource.resourceName);
-        }
-    }
-}
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index e4cdd59..1180106 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -29,7 +29,10 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.ActionMode;
+import android.view.InputDevice;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
@@ -48,6 +51,7 @@
  */
 public abstract class PagedView extends ViewGroup {
     private static final String TAG = "PagedView";
+    private static final boolean DEBUG = false;
     protected static final int INVALID_PAGE = -1;
 
     // the min drag distance for a fling to register, to prevent random page shifts
@@ -61,6 +65,7 @@
     private static final float OVERSCROLL_DAMP_FACTOR = 0.08f;
     private static final int MINIMUM_SNAP_VELOCITY = 2200;
     private static final int MIN_FLING_VELOCITY = 250;
+    private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f;
 
     // the velocity at which a fling gesture will cause us to snap to the next page
     protected int mSnapVelocity = 500;
@@ -81,6 +86,7 @@
     protected float mLastMotionX;
     protected float mLastMotionXRemainder;
     protected float mLastMotionY;
+    protected float mTotalMotionX;
     private int mLastScreenCenter = -1;
 
     protected final static int TOUCH_STATE_REST = 0;
@@ -98,6 +104,7 @@
     protected int mTouchSlop;
     private int mPagingTouchSlop;
     private int mMaximumVelocity;
+    private int mMinimumWidth;
     protected int mPageSpacing;
     protected int mPageLayoutPaddingTop;
     protected int mPageLayoutPaddingBottom;
@@ -105,6 +112,7 @@
     protected int mPageLayoutPaddingRight;
     protected int mPageLayoutWidthGap;
     protected int mPageLayoutHeightGap;
+    protected int mPageLayoutMaxHeight;
     protected int mCellCountX;
     protected int mCellCountY;
     protected boolean mCenterPagesVertically;
@@ -173,17 +181,19 @@
                 R.styleable.PagedView, defStyle, 0);
         mPageSpacing = a.getDimensionPixelSize(R.styleable.PagedView_pageSpacing, 0);
         mPageLayoutPaddingTop = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingTop, 10);
+                R.styleable.PagedView_pageLayoutPaddingTop, 0);
         mPageLayoutPaddingBottom = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingBottom, 10);
+                R.styleable.PagedView_pageLayoutPaddingBottom, 0);
         mPageLayoutPaddingLeft = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingLeft, 10);
+                R.styleable.PagedView_pageLayoutPaddingLeft, 0);
         mPageLayoutPaddingRight = a.getDimensionPixelSize(
-                R.styleable.PagedView_pageLayoutPaddingRight, 10);
+                R.styleable.PagedView_pageLayoutPaddingRight, 0);
         mPageLayoutWidthGap = a.getDimensionPixelSize(
                 R.styleable.PagedView_pageLayoutWidthGap, -1);
         mPageLayoutHeightGap = a.getDimensionPixelSize(
                 R.styleable.PagedView_pageLayoutHeightGap, -1);
+        mPageLayoutMaxHeight = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutMaxHeight, -1);
         a.recycle();
 
         setHapticFeedbackEnabled(false);
@@ -284,6 +294,10 @@
         mIsPageMoving = false;
     }
 
+    protected boolean isPageMoving() {
+        return mIsPageMoving;
+    }
+
     // a method that subclasses can override to add behavior
     protected void onPageBeginMoving() {
     }
@@ -379,8 +393,13 @@
 
         final int verticalPadding = mPaddingTop + mPaddingBottom;
 
+        if (mPageLayoutMaxHeight != -1) {
+            heightSize = Math.min(mPageLayoutMaxHeight, heightSize);
+        }
+
         // The children are given the same width and height as the workspace
         // unless they were set to WRAP_CONTENT
+        if (DEBUG) Log.d(TAG, "PagedView.onMeasure(): " + widthSize + ", " + heightSize);
         final int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             // disallowing padding in paged view (just pass 0)
@@ -408,6 +427,8 @@
 
             child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
             maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
+            if (DEBUG) Log.d(TAG, "\tmeasure-child" + i + ": " + child.getMeasuredWidth() + ", "
+                    + child.getMeasuredHeight());
         }
 
         if (heightMode == MeasureSpec.AT_MOST) {
@@ -462,6 +483,7 @@
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (DEBUG) Log.d(TAG, "PagedView.onLayout()");
         if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
             setHorizontalScrollBarEnabled(false);
             int newX = getChildOffset(mCurrentPage) - getRelativeChildOffset(mCurrentPage);
@@ -475,6 +497,8 @@
         final int childCount = getChildCount();
         int childLeft = 0;
         if (childCount > 0) {
+            if (DEBUG) Log.d(TAG, "getRelativeChildOffset(): " + getMeasuredWidth() + ", "
+                    + getChildWidth(0));
             childLeft = getRelativeChildOffset(0);
         }
 
@@ -488,6 +512,7 @@
                     childTop += ((getMeasuredHeight() - verticalPadding) - childHeight) / 2;
                 }
 
+                if (DEBUG) Log.d(TAG, "\tlayout-child" + i + ": " + childLeft + ", " + childTop);
                 child.layout(childLeft, childTop,
                         childLeft + child.getMeasuredWidth(), childTop + childHeight);
                 childLeft += childWidth + mPageSpacing;
@@ -498,10 +523,16 @@
         }
     }
 
+    protected void forceUpdateAdjacentPagesAlpha() {
+        mDirtyPageAlpha = true;
+        updateAdjacentPagesAlpha();
+    }
+
     protected void updateAdjacentPagesAlpha() {
         if (mFadeInAdjacentScreens) {
             if (mDirtyPageAlpha || (mTouchState == TOUCH_STATE_SCROLLING) || !mScroller.isFinished()) {
-                int halfScreenSize = getMeasuredWidth() / 2;
+                int screenWidth = getMeasuredWidth();
+                int halfScreenSize = screenWidth / 2;
                 int screenCenter = mScrollX + halfScreenSize;
                 final int childCount = getChildCount();
                 for (int i = 0; i < childCount; ++i) {
@@ -514,7 +545,7 @@
                     // we should just assume full page width (and calculate the offset according to
                     // that).
                     if (childWidth <= 0) {
-                        childWidth = getMeasuredWidth();
+                        childWidth = screenWidth;
                         childCenter = (i * childWidth) + (childWidth / 2);
                     }
 
@@ -544,6 +575,11 @@
                         alpha = 1.0f;
                     }
 
+                    // Due to the way we're setting alpha on our children in PagedViewCellLayout,
+                    // this optimization causes alpha to not be properly updated sometimes (repro
+                    // case: in xlarge mode, swipe to second page in All Apps, then click on "My
+                    // Apps" tab. the page will have alpha 0 until you swipe it). Removing
+                    // optimization fixes the issue, but we should fix this in a better manner
                     //if (Float.compare(alpha, layout.getAlpha()) != 0) {
                         layout.setAlpha(alpha);
                     //}
@@ -596,21 +632,7 @@
             canvas.clipRect(mScrollX, mScrollY, mScrollX + mRight - mLeft,
                     mScrollY + mBottom - mTop);
 
-            for (int i = 0; i < pageCount; i++) {
-                View child = getChildAt(i);
-                if (child != null && child instanceof PagedViewCellLayout) {
-                    boolean willBeDrawn = i >= leftScreen && i <= rightScreen;
-                    if (!willBeDrawn) {
-                        ((PagedViewCellLayout)child).destroyHardwareLayers();
-                    }
-                }
-            }
-
             for (int i = leftScreen; i <= rightScreen; i++) {
-                View child = getChildAt(i);
-                if (child != null && child instanceof PagedViewCellLayout) {
-                    ((PagedViewCellLayout)child).createHardwareLayers();
-                }
                 drawChild(canvas, getChildAt(i), drawingTime);
             }
             canvas.restore();
@@ -737,6 +759,7 @@
          * If we return true, onTouchEvent will be called and we do the actual
          * scrolling there.
          */
+        acquireVelocityTrackerAndAddMovement(ev);
 
         // Skip touch handling if there are no pages to swipe
         if (getChildCount() <= 0) return super.onInterceptTouchEvent(ev);
@@ -777,6 +800,7 @@
                 mLastMotionX = x;
                 mLastMotionY = y;
                 mLastMotionXRemainder = 0;
+                mTotalMotionX = 0;
                 mActivePointerId = ev.getPointerId(0);
                 mAllowLongPress = true;
 
@@ -814,10 +838,12 @@
                 mTouchState = TOUCH_STATE_REST;
                 mAllowLongPress = false;
                 mActivePointerId = INVALID_POINTER;
+                releaseVelocityTracker();
                 break;
 
             case MotionEvent.ACTION_POINTER_UP:
                 onSecondaryPointerUp(ev);
+                releaseVelocityTracker();
                 break;
         }
 
@@ -869,6 +895,7 @@
             if (mUsePagingTouchSlop ? xPaged : xMoved) {
                 // Scroll if the user moved far enough along the X axis
                 mTouchState = TOUCH_STATE_SCROLLING;
+                mTotalMotionX += Math.abs(mLastMotionX - x);
                 mLastMotionX = x;
                 mLastMotionXRemainder = 0;
                 mTouchX = mScrollX;
@@ -952,6 +979,7 @@
             // Remember where the motion event started
             mDownMotionX = mLastMotionX = ev.getX();
             mLastMotionXRemainder = 0;
+            mTotalMotionX = 0;
             mActivePointerId = ev.getPointerId(0);
             if (mTouchState == TOUCH_STATE_SCROLLING) {
                 pageBeginMoving();
@@ -965,6 +993,8 @@
                 final float x = ev.getX(pointerIndex);
                 final float deltaX = mLastMotionX + mLastMotionXRemainder - x;
 
+                mTotalMotionX += Math.abs(deltaX);
+
                 // Only scroll and update mLastMotionX if we have moved some discrete amount.  We
                 // keep the remainder because we are actually testing if we've moved from the last
                 // scrolled position (which is discrete).
@@ -973,6 +1003,7 @@
                     mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
                     if (!mDeferScrollUpdate) {
                         scrollBy((int) deltaX, 0);
+                        if (DEBUG) Log.d(TAG, "onTouchEvent().Scrolling: " + deltaX);
                     } else {
                         invalidate();
                     }
@@ -995,17 +1026,37 @@
                 velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                 int velocityX = (int) velocityTracker.getXVelocity(activePointerId);
                 final int deltaX = (int) (x - mDownMotionX);
-                boolean isfling = Math.abs(deltaX) > MIN_LENGTH_FOR_FLING;
                 boolean isSignificantMove = Math.abs(deltaX) > MIN_LENGTH_FOR_MOVE;
-
                 final int snapVelocity = mSnapVelocity;
-                if ((isSignificantMove && deltaX > 0 ||
-                        (isfling && velocityX > snapVelocity)) && mCurrentPage > 0) {
-                    snapToPageWithVelocity(mCurrentPage - 1, velocityX);
-                } else if ((isSignificantMove && deltaX < 0 ||
-                        (isfling && velocityX < -snapVelocity)) &&
+
+                mTotalMotionX += Math.abs(mLastMotionX + mLastMotionXRemainder - x);
+
+                // In the case that the page is moved far to one direction and then is flung
+                // in the opposite direction, we use a threshold to determine whether we should
+                // just return to the starting page, or if we should skip one further.
+                boolean returnToOriginalPage = false;
+                final int pageWidth = getScaledMeasuredWidth(getChildAt(mCurrentPage));
+                if (Math.abs(deltaX) > pageWidth * RETURN_TO_ORIGINAL_PAGE_THRESHOLD &&
+                        Math.signum(velocityX) != Math.signum(deltaX)) {
+                    returnToOriginalPage = true;
+                }
+
+                boolean isFling = mTotalMotionX > MIN_LENGTH_FOR_FLING &&
+                        Math.abs(velocityX) > snapVelocity;
+
+                int finalPage;
+                // We give flings precedence over large moves, which is why we short-circuit our
+                // test for a large move if a fling has been registered. That is, a large
+                // move to the left and fling to the right will register as a fling to the right.
+                if (((isSignificantMove && deltaX > 0 && !isFling) ||
+                        (isFling && velocityX > 0)) && mCurrentPage > 0) {
+                    finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage - 1;
+                    snapToPageWithVelocity(finalPage, velocityX);
+                } else if (((isSignificantMove && deltaX < 0 && !isFling) ||
+                        (isFling && velocityX < 0)) &&
                         mCurrentPage < getChildCount() - 1) {
-                    snapToPageWithVelocity(mCurrentPage + 1, velocityX);
+                    finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage + 1;
+                    snapToPageWithVelocity(finalPage, velocityX);
                 } else {
                     snapToDestination();
                 }
@@ -1054,6 +1105,35 @@
         return true;
     }
 
+    @Override
+    public boolean onGenericMotionEvent(MotionEvent event) {
+        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_SCROLL: {
+                    // Handle mouse (or ext. device) by shifting the page depending on the scroll
+                    final float vscroll;
+                    final float hscroll;
+                    if ((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) {
+                        vscroll = 0;
+                        hscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                    } else {
+                        vscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                        hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
+                    }
+                    if (hscroll != 0 || vscroll != 0) {
+                        if (hscroll > 0 || vscroll > 0) {
+                            scrollRight();
+                        } else {
+                            scrollLeft();
+                        }
+                        return true;
+                    }
+                }
+            }
+        }
+        return super.onGenericMotionEvent(event);
+    }
+
     private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
@@ -1097,7 +1177,7 @@
     public void requestChildFocus(View child, View focused) {
         super.requestChildFocus(child, focused);
         int page = indexOfChild(child);
-        if (page >= 0 && !isInTouchMode()) {
+        if (page >= 0 && page != getCurrentPage() && !isInTouchMode()) {
             snapToPage(page);
         }
     }
@@ -1116,8 +1196,23 @@
         return -1;
     }
 
+    protected void setMinimumWidthOverride(int minimumWidth) {
+        mMinimumWidth = minimumWidth;
+    }
+    protected void resetMinimumWidthOverride() {
+        mMinimumWidth = 0;
+    }
+
+    protected int getChildWidth(int index) {
+        // This functions are called enough times that it actually makes a difference in the
+        // profiler -- so just inline the max() here
+        final int measuredWidth = getChildAt(index).getMeasuredWidth();
+        final int minWidth = mMinimumWidth;
+        return (minWidth > measuredWidth) ? minWidth : measuredWidth;
+    }
+
     protected int getRelativeChildOffset(int index) {
-        return (getMeasuredWidth() - getChildAt(index).getMeasuredWidth()) / 2;
+        return (getMeasuredWidth() - getChildWidth(index)) / 2;
     }
 
     protected int getChildOffset(int index) {
@@ -1132,7 +1227,12 @@
     }
 
     protected int getScaledMeasuredWidth(View child) {
-        return (int) (child.getMeasuredWidth() * mLayoutScale + 0.5f);
+        // This functions are called enough times that it actually makes a difference in the
+        // profiler -- so just inline the max() here
+        final int measuredWidth = child.getMeasuredWidth();
+        final int minWidth = mMinimumWidth;
+        final int maxWidth = (minWidth > measuredWidth) ? minWidth : measuredWidth;
+        return (int) (maxWidth * mLayoutScale + 0.5f);
     }
 
     int getPageNearestToCenterOfScreen() {
@@ -1182,6 +1282,9 @@
         whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1));
         int halfScreenSize = getMeasuredWidth() / 2;
 
+        if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
+        if (DEBUG) Log.d(TAG, "snapToPageWithVelocity.getRelativeChildOffset(): "
+                + getMeasuredWidth() + ", " + getChildWidth(whichPage));
         final int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
         int delta = newX - mUnboundedScrollX;
         int duration = 0;
@@ -1219,6 +1322,9 @@
     protected void snapToPage(int whichPage, int duration) {
         whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1));
 
+        if (DEBUG) Log.d(TAG, "snapToPage.getChildOffset(): " + getChildOffset(whichPage));
+        if (DEBUG) Log.d(TAG, "snapToPage.getRelativeChildOffset(): " + getMeasuredWidth() + ", "
+                + getChildWidth(whichPage));
         int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage);
         final int sX = mUnboundedScrollX;
         final int delta = newX - sX;
@@ -1330,6 +1436,8 @@
             if (page < count) {
                 int lowerPageBound = getAssociatedLowerPageBound(page);
                 int upperPageBound = getAssociatedUpperPageBound(page);
+                if (DEBUG) Log.d(TAG, "loadAssociatedPages: " + lowerPageBound + "/"
+                        + upperPageBound);
                 for (int i = 0; i < count; ++i) {
                     Page layout = (Page) getChildAt(i);
                     final int childCount = layout.getPageChildCount();
@@ -1398,7 +1506,7 @@
      * Otherwise, returns null.
      */
     protected Checkable getSingleCheckedGrandchild() {
-        if (mChoiceMode == CHOICE_MODE_SINGLE) {
+        if (mChoiceMode != CHOICE_MODE_MULTIPLE) {
             final int childCount = getChildCount();
             for (int i = 0; i < childCount; ++i) {
                 Page layout = (Page) getChildAt(i);
@@ -1414,14 +1522,6 @@
         return null;
     }
 
-    public Object getChosenItem() {
-        View checkedView = (View) getSingleCheckedGrandchild();
-        if (checkedView != null) {
-            return checkedView.getTag();
-        }
-        return null;
-    }
-
     protected void resetCheckedGrandchildren() {
         // loop through children, and set all of their children to _not_ be checked
         final ArrayList<Checkable> checked = getCheckedGrandchildren();
diff --git a/src/com/android/launcher2/PagedViewCellLayout.java b/src/com/android/launcher2/PagedViewCellLayout.java
index d64f3c9..9022cac 100644
--- a/src/com/android/launcher2/PagedViewCellLayout.java
+++ b/src/com/android/launcher2/PagedViewCellLayout.java
@@ -17,12 +17,15 @@
 package com.android.launcher2;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 
+import com.android.launcher.R;
+
 /**
  * An abstraction of the original CellLayout which supports laying out items
  * which span multiple cells into a grid-like layout.  Also supports dimming
@@ -37,10 +40,10 @@
     private int mCellHeight;
     private int mWidthGap;
     private int mHeightGap;
-    private static int sDefaultCellDimensions = 96;
     protected PagedViewCellLayoutChildren mChildren;
     private PagedViewCellLayoutChildren mHolographicChildren;
-    private boolean mUseHardwareLayers = false;
+    private boolean mAllowHardwareLayerCreation = false;
+    private boolean mCreateHardwareLayersIfAllowed = false;
 
     public PagedViewCellLayout(Context context) {
         this(context, null);
@@ -56,7 +59,9 @@
         setAlwaysDrawnWithCacheEnabled(false);
 
         // setup default cell parameters
-        mCellWidth = mCellHeight = sDefaultCellDimensions;
+        Resources resources = context.getResources();
+        mCellWidth = resources.getDimensionPixelSize(R.dimen.apps_customize_cell_width);
+        mCellHeight = resources.getDimensionPixelSize(R.dimen.apps_customize_cell_height);
         mCellCountX = LauncherModel.getCellCountX();
         mCellCountY = LauncherModel.getCellCountY();
         mWidthGap = mHeightGap = -1;
@@ -74,8 +79,17 @@
         addView(mHolographicChildren);
     }
 
-    public void enableHardwareLayers() {
-        mUseHardwareLayers = true;
+    public void allowHardwareLayerCreation() {
+        // This is called after the first time we launch into All Apps. Before that point,
+        // there's no need for hardware layers here since there's a hardware layer set on the
+        // parent, AllAppsTabbed, during the AllApps transition -- creating hardware layers here
+        // before the animation is done slows down the animation
+        if (!mAllowHardwareLayerCreation) {
+            mAllowHardwareLayerCreation = true;
+            if (mCreateHardwareLayersIfAllowed) {
+                createHardwareLayers();
+            }
+        }
     }
 
     @Override
@@ -85,13 +99,18 @@
     }
 
     void destroyHardwareLayers() {
-        if (mUseHardwareLayers) {
+        // called when a page is no longer visible (triggered by loadAssociatedPages ->
+        // removeAllViewsOnPage)
+        mCreateHardwareLayersIfAllowed = false;
+        if (mAllowHardwareLayerCreation) {
             mChildren.destroyHardwareLayer();
             mHolographicChildren.destroyHardwareLayer();
         }
     }
     void createHardwareLayers() {
-        if (mUseHardwareLayers) {
+        // called when a page is visible (triggered by loadAssociatedPages -> syncPageItems)
+        mCreateHardwareLayersIfAllowed = true;
+        if (mAllowHardwareLayerCreation) {
             mChildren.createHardwareLayer();
             mHolographicChildren.createHardwareLayer();
         }
@@ -109,6 +128,15 @@
         }
     }
 
+    /** Syncs the holographic icon views to the child icon views */
+    public void reloadHolographicIcons(boolean createHolographicOutlines) {
+        if (createHolographicOutlines) {
+            mChildren.loadHolographicOutlines();
+        } else {
+            mChildren.clearHolographicOutlines();
+        }
+    }
+
     public boolean addViewToCellLayout(View child, int index, int childId,
             PagedViewCellLayout.LayoutParams params) {
         final PagedViewCellLayout.LayoutParams lp = params;
@@ -127,10 +155,11 @@
 
             if (child instanceof PagedViewIcon) {
                 PagedViewIcon pagedViewIcon = (PagedViewIcon) child;
-                if (mUseHardwareLayers) {
+                if (mAllowHardwareLayerCreation) {
                     pagedViewIcon.disableCache();
                 }
-                mHolographicChildren.addView(pagedViewIcon.getHolographicOutlineView(), index, lp);
+                mHolographicChildren.addView(pagedViewIcon.getHolographicOutlineView(),
+                        index, lp);
             }
             return true;
         }
@@ -141,6 +170,7 @@
     public void removeAllViewsOnPage() {
         mChildren.removeAllViews();
         mHolographicChildren.removeAllViews();
+        destroyHardwareLayers();
     }
 
     @Override
@@ -164,6 +194,14 @@
         return mChildren.indexOfChild(v);
     }
 
+    public int getCellCountX() {
+        return mCellCountX;
+    }
+
+    public int getCellCountY() {
+        return mCellCountY;
+    }
+
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         // TODO: currently ignoring padding
 
@@ -227,12 +265,37 @@
         setMeasuredDimension(newWidth, newHeight);
     }
 
+    int getContentWidth() {
+        if (LauncherApplication.isScreenLarge()) {
+            // Return the distance from the left edge of the content of the leftmost icon to
+            // the right edge of the content of the rightmost icon
+
+            // icons are centered within cells, find out how much padding that accounts for
+            return getWidthBeforeFirstLayout() - (mCellWidth - Utilities.getIconContentSize());
+        } else {
+            return getWidthBeforeFirstLayout() + mPaddingLeft + mPaddingRight;
+        }
+    }
+
+    int getContentHeight() {
+        return mCellCountY * mCellHeight + (mCellCountY - 1) * Math.max(0, mHeightGap);
+    }
+
+    int getWidthBeforeFirstLayout() {
+        return mCellCountX * mCellWidth + (mCellCountX - 1) * Math.max(0, mWidthGap);
+    }
+
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         int count = getChildCount();
         for (int i = 0; i < count; i++) {
             View child = getChildAt(i);
-            child.layout(0, 0, r - l, b - t);
+            if (LauncherApplication.isScreenLarge()) {
+                child.layout(0, 0, r - l, b - t);
+            } else {
+                child.layout(mPaddingLeft, mPaddingTop, getMeasuredWidth() - mPaddingRight,
+                        getMeasuredHeight() - mPaddingBottom);
+            }
         }
     }
 
@@ -265,17 +328,6 @@
         mHolographicChildren.setGap(widthGap, heightGap);
     }
 
-    public void setCellDimensions(int width, int height) {
-        mCellWidth = width;
-        mCellHeight = height;
-        mChildren.setCellDimensions(width, height);
-        mHolographicChildren.setCellDimensions(width, height);
-    }
-
-    public int getDefaultCellDimensions() {
-        return sDefaultCellDimensions;
-    }
-
     public int[] getCellCountForDimensions(int width, int height) {
         // Always assume we're working with the smallest span to make sure we
         // reserve enough space in both orientations
@@ -432,8 +484,13 @@
             height = myCellVSpan * cellHeight + ((myCellVSpan - 1) * heightGap) -
                     topMargin - bottomMargin;
 
-            x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
-            y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
+            if (LauncherApplication.isScreenLarge()) {
+                x = hStartPadding + myCellX * (cellWidth + widthGap) + leftMargin;
+                y = vStartPadding + myCellY * (cellHeight + heightGap) + topMargin;
+            } else {
+                x = myCellX * (cellWidth + widthGap) + leftMargin;
+                y = myCellY * (cellHeight + heightGap) + topMargin;
+            }
         }
 
         public Object getTag() {
diff --git a/src/com/android/launcher2/PagedViewCellLayoutChildren.java b/src/com/android/launcher2/PagedViewCellLayoutChildren.java
index 27da02a..6333f7f 100644
--- a/src/com/android/launcher2/PagedViewCellLayoutChildren.java
+++ b/src/com/android/launcher2/PagedViewCellLayoutChildren.java
@@ -139,12 +139,12 @@
     }
 
     void destroyHardwareLayer() {
-        if (getLayerType() == LAYER_TYPE_HARDWARE) {
+        if (getLayerType() != LAYER_TYPE_NONE) {
             setLayerType(LAYER_TYPE_NONE, null);
         }
     }
     void createHardwareLayer() {
-        if (getLayerType() == LAYER_TYPE_NONE) {
+        if (getLayerType() != LAYER_TYPE_HARDWARE) {
             setLayerType(LAYER_TYPE_HARDWARE, null);
         }
     }
@@ -165,4 +165,26 @@
             }
         }
     }
+
+    public void loadHolographicOutlines() {
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View view = getChildAt(i);
+            if (view instanceof PagedViewIcon) {
+                PagedViewIcon icon = (PagedViewIcon) view;
+                icon.loadHolographicIcon();
+            }
+        }
+    }
+
+    public void clearHolographicOutlines() {
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View view = getChildAt(i);
+            if (view instanceof PagedViewIcon) {
+                PagedViewIcon icon = (PagedViewIcon) view;
+                icon.clearHolographicIcon();
+            }
+        }
+    }
 }
diff --git a/src/com/android/launcher2/PagedViewExtendedLayout.java b/src/com/android/launcher2/PagedViewExtendedLayout.java
index e54d261..94890d8 100644
--- a/src/com/android/launcher2/PagedViewExtendedLayout.java
+++ b/src/com/android/launcher2/PagedViewExtendedLayout.java
@@ -23,10 +23,11 @@
 import android.widget.LinearLayout;
 
 /**
- * The linear layout used strictly for the widget/wallpaper tab of the customization tray
+ * The linear layout used strictly for the widget/wallpaper tab of the customization tray.
+ * To be deprecated.
  */
 public class PagedViewExtendedLayout extends LinearLayout implements Page {
-    static final String TAG = "PagedViewWidgetLayout";
+    static final String TAG = "PagedViewExtendedLayout";
 
     public PagedViewExtendedLayout(Context context) {
         this(context, null);
@@ -40,6 +41,22 @@
         super(context, attrs, defStyle);
     }
 
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (LauncherApplication.isScreenLarge()) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        } else {
+            // PagedView currently has issues with different-sized pages since it calculates the
+            // offset of each page to scroll to before it updates the actual size of each page
+            // (which canchange depending on the content if the contains aren't a fixed size).
+            // We work around this by having a minimum size on each widget page).
+            int widthSpecSize = Math.max(getSuggestedMinimumWidth(),
+                    MeasureSpec.getSize(widthMeasureSpec));
+            int widthSpecMode = MeasureSpec.AT_MOST;
+            super.onMeasure(MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode),
+                    heightMeasureSpec);
+        }
+    }
+
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         // We eat up the touch events here, since the PagedView (which uses the same swiping
@@ -94,4 +111,11 @@
     public int indexOfChildOnPage(View v) {
         return indexOfChild(v);
     }
+
+    public static class LayoutParams extends LinearLayout.LayoutParams {
+        public LayoutParams() {
+            super(LinearLayout.LayoutParams.WRAP_CONTENT,
+                    LinearLayout.LayoutParams.MATCH_PARENT);
+        }
+    }
 }
diff --git a/src/com/android/launcher2/PagedViewGridLayout.java b/src/com/android/launcher2/PagedViewGridLayout.java
new file mode 100644
index 0000000..cedf71c
--- /dev/null
+++ b/src/com/android/launcher2/PagedViewGridLayout.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+/**
+ * The grid based layout used strictly for the widget/wallpaper tab of the AppsCustomize pane
+ */
+public class PagedViewGridLayout extends FrameLayout implements Page {
+    static final String TAG = "PagedViewGridLayout";
+
+    private int mCellCountX;
+    private int mCellCountY;
+
+    public PagedViewGridLayout(Context context, int cellCountX, int cellCountY) {
+        super(context, null, 0);
+        mCellCountX = cellCountX;
+        mCellCountY = cellCountY;
+    }
+
+    int getCellCountX() {
+        return mCellCountX;
+    }
+    int getCellCountY() {
+        return mCellCountY;
+    }
+
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // PagedView currently has issues with different-sized pages since it calculates the
+        // offset of each page to scroll to before it updates the actual size of each page
+        // (which can change depending on the content if the contents aren't a fixed size).
+        // We work around this by having a minimum size on each widget page).
+        int widthSpecSize = Math.max(getSuggestedMinimumWidth(),
+                MeasureSpec.getSize(widthMeasureSpec));
+        int widthSpecMode = MeasureSpec.AT_MOST;
+        super.onMeasure(MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode),
+                heightMeasureSpec);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        // We eat up the touch events here, since the PagedView (which uses the same swiping
+        // touch code as Workspace previously) uses onInterceptTouchEvent() to determine when
+        // the user is scrolling between pages.  This means that if the pages themselves don't
+        // handle touch events, it gets forwarded up to PagedView itself, and it's own
+        // onTouchEvent() handling will prevent further intercept touch events from being called
+        // (it's the same view in that case).  This is not ideal, but to prevent more changes,
+        // we just always mark the touch event as handled.
+        return super.onTouchEvent(event) || true;
+    }
+
+    @Override
+    protected boolean onSetAlpha(int alpha) {
+        return true;
+    }
+
+    @Override
+    public void setAlpha(float alpha) {
+        setChildrenAlpha(alpha);
+        super.setAlpha(alpha);
+    }
+
+    private void setChildrenAlpha(float alpha) {
+        final int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            getChildAt(i).setAlpha(alpha);
+        }
+    }
+
+    @Override
+    public void removeAllViewsOnPage() {
+        removeAllViews();
+    }
+
+    @Override
+    public void removeViewOnPageAt(int index) {
+        removeViewAt(index);
+    }
+
+    @Override
+    public int getPageChildCount() {
+        return getChildCount();
+    }
+
+    @Override
+    public View getChildOnPageAt(int i) {
+        return getChildAt(i);
+    }
+
+    @Override
+    public int indexOfChildOnPage(View v) {
+        return indexOfChild(v);
+    }
+
+    public static class LayoutParams extends FrameLayout.LayoutParams {
+        public LayoutParams(int width, int height) {
+            super(width, height);
+        }
+    }
+}
diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java
index 1366619..306ff9e 100644
--- a/src/com/android/launcher2/PagedViewIcon.java
+++ b/src/com/android/launcher2/PagedViewIcon.java
@@ -16,9 +16,8 @@
 
 package com.android.launcher2;
 
-import com.android.launcher.R;
-
 import android.animation.ObjectAnimator;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -31,9 +30,11 @@
 import android.os.HandlerThread;
 import android.os.Message;
 import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.View;
 import android.widget.Checkable;
-import android.widget.TextView;
 
+import com.android.launcher.R;
 
 
 /**
@@ -121,15 +122,15 @@
 
         // Set up fade in/out constants
         final Resources r = context.getResources();
-        final int alpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha);
+        final int alpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha);
         if (alpha > 0) {
-            mCheckedAlpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha) / 256.0f;
-            mCheckedFadeInDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeInTime);
-            mCheckedFadeOutDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeOutTime);
+            mCheckedAlpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha) / 256.0f;
+            mCheckedFadeInDuration =
+                r.getInteger(R.integer.config_dragAppsCustomizeIconFadeInDuration);
+            mCheckedFadeOutDuration =
+                r.getInteger(R.integer.config_dragAppsCustomizeIconFadeOutDuration);
         }
 
-        setFocusable(true);
-        setBackgroundDrawable(null);
         mHolographicOutlineView = new HolographicPagedViewIcon(context, this);
     }
 
@@ -141,34 +142,51 @@
         return mHolographicOutline;
     }
 
-    private void queueHolographicOutlineCreation() {
+    private boolean queueHolographicOutlineCreation() {
         // Generate the outline in the background
         if (mHolographicOutline == null) {
             Message m = sWorker.obtainMessage(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE);
             m.obj = this;
             sWorker.sendMessage(m);
+            return true;
         }
+        return false;
+    }
+
+    public void loadHolographicIcon() {
+        if (mHolographicOutline == null) {
+            mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
+            if (!queueHolographicOutlineCreation()) {
+                getHolographicOutlineView().invalidate();
+            }
+        }
+    }
+    public void clearHolographicIcon() {
+        mHolographicOutline = null;
+        getHolographicOutlineView().invalidate();
     }
 
     public void applyFromApplicationInfo(ApplicationInfo info, PagedViewIconCache cache,
             boolean scaleUp, boolean createHolographicOutlines) {
+        mIconCache = cache;
+        mIconCacheKey = new PagedViewIconCache.Key(info);
         mIcon = info.iconBitmap;
         setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
         setText(info.title);
         setTag(info);
 
         if (createHolographicOutlines) {
-            mIconCache = cache;
-            mIconCacheKey = new PagedViewIconCache.Key(info);
             mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
-            queueHolographicOutlineCreation();
+            if (!queueHolographicOutlineCreation()) {
+                getHolographicOutlineView().invalidate();
+            }
         }
     }
 
     public void applyFromResolveInfo(ResolveInfo info, PackageManager packageManager,
             PagedViewIconCache cache, IconCache modelIconCache, boolean createHolographicOutlines) {
-        mIcon = Utilities.createIconBitmap(
-                modelIconCache.getFullResIcon(info, packageManager), mContext);
+        ComponentName cn = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
+        mIcon = modelIconCache.getIcon(cn, info);
         setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
         setText(info.loadLabel(packageManager));
         setTag(info);
@@ -177,7 +195,9 @@
             mIconCache = cache;
             mIconCacheKey = new PagedViewIconCache.Key(info);
             mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
-            queueHolographicOutlineCreation();
+            if (!queueHolographicOutlineCreation()) {
+                getHolographicOutlineView().invalidate();
+            }
         }
     }
 
@@ -210,12 +230,7 @@
         Bitmap overlay = null;
 
         // draw any blended overlays
-        if (mCheckedOutline == null) {
-            if (mHolographicOutline != null && mHolographicAlpha > 0) {
-                mPaint.setAlpha(mHolographicAlpha);
-                overlay = mHolographicOutline;
-            }
-        } else {
+        if (mCheckedOutline != null) {
             mPaint.setAlpha(255);
             overlay = mCheckedOutline;
         }
@@ -239,12 +254,23 @@
     }
 
     @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
+                || super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        return FocusHelper.handlePagedViewIconKeyEvent(this, keyCode, event)
+                || super.onKeyUp(keyCode, event);
+    }
+
+    @Override
     public boolean isChecked() {
         return mIsChecked;
     }
 
-    @Override
-    public void setChecked(boolean checked) {
+    void setChecked(boolean checked, boolean animate) {
         if (mIsChecked != checked) {
             mIsChecked = checked;
 
@@ -262,15 +288,24 @@
             if (mCheckedAlphaAnimator != null) {
                 mCheckedAlphaAnimator.cancel();
             }
-            mCheckedAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), alpha);
-            mCheckedAlphaAnimator.setDuration(duration);
-            mCheckedAlphaAnimator.start();
+            if (animate) {
+                mCheckedAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), alpha);
+                mCheckedAlphaAnimator.setDuration(duration);
+                mCheckedAlphaAnimator.start();
+            } else {
+                setAlpha(alpha);
+            }
 
             invalidate();
         }
     }
 
     @Override
+    public void setChecked(boolean checked) {
+        setChecked(checked, true);
+    }
+
+    @Override
     public void toggle() {
         setChecked(!mIsChecked);
     }
diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java
index 9b83f48..2ffa398 100644
--- a/src/com/android/launcher2/PagedViewWidget.java
+++ b/src/com/android/launcher2/PagedViewWidget.java
@@ -27,11 +27,16 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.PorterDuff;
 import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
 import android.util.AttributeSet;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.Checkable;
@@ -52,9 +57,14 @@
     private Bitmap mHolographicOutline;
     private final Canvas mHolographicOutlineCanvas = new Canvas();
     private FastBitmapDrawable mPreview;
+    private ImageView mPreviewImageView;
+    private final RectF mTmpScaleRect = new RectF();
+    private final Rect mEraseStrokeRect = new Rect();
+    private final Paint mEraseStrokeRectPaint = new Paint();
 
     private PagedViewIconCache.Key mIconCacheKey;
     private PagedViewIconCache mIconCache;
+    private String mDimensionsFormatString;
 
     private int mAlpha = 255;
     private int mHolographicAlpha;
@@ -81,8 +91,11 @@
         public void handleMessage(Message msg) {
             final PagedViewWidget widget = (PagedViewWidget) msg.obj;
             final int prevAlpha = widget.mPreview.getAlpha();
-            final Bitmap outline = Bitmap.createBitmap(widget.getWidth(), widget.getHeight(),
-                    Bitmap.Config.ARGB_8888);
+            final int width = Math.max(widget.mPreview.getIntrinsicWidth(),
+                    widget.getMeasuredWidth());
+            final int height = Math.max(widget.mPreview.getIntrinsicHeight(),
+                    widget.getMeasuredHeight());
+            final Bitmap outline = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
 
             widget.mHolographicOutlineCanvas.setBitmap(outline);
             widget.mHolographicOutlineCanvas.save();
@@ -94,6 +107,12 @@
             widget.mHolographicOutlineCanvas.drawColor(Color.argb(156, 0, 0, 0), Mode.SRC_OVER);
             widget.mHolographicOutlineCanvas.restore();
 
+            // To account for the fact that some previews run up straight to the edge (we subtract
+            // the edge from the holographic preview (before we apply the holograph)
+            widget.mEraseStrokeRect.set(0, 0, width, height);
+            widget.mHolographicOutlineCanvas.drawRect(widget.mEraseStrokeRect,
+                    widget.mEraseStrokeRectPaint);
+
             sHolographicOutlineHelper.applyThickExpensiveOutlineWithBlur(outline,
                     widget.mHolographicOutlineCanvas, widget.mHoloBlurColor,
                     widget.mHoloOutlineColor);
@@ -123,6 +142,11 @@
                 defStyle, 0);
         mHoloBlurColor = a.getColor(R.styleable.PagedViewWidget_blurColor, 0);
         mHoloOutlineColor = a.getColor(R.styleable.PagedViewWidget_outlineColor, 0);
+        mEraseStrokeRectPaint.setStyle(Paint.Style.STROKE);
+        mEraseStrokeRectPaint.setStrokeWidth(HolographicOutlineHelper.MIN_OUTER_BLUR_RADIUS);
+        mEraseStrokeRectPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+        mEraseStrokeRectPaint.setFilterBitmap(true);
+        mEraseStrokeRectPaint.setAntiAlias(true);
         a.recycle();
 
         if (sHolographicOutlineHelper == null) {
@@ -131,14 +155,16 @@
 
         // Set up fade in/out constants
         final Resources r = context.getResources();
-        final int alpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha);
+        final int alpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha);
         if (alpha > 0) {
-            mCheckedAlpha = r.getInteger(R.integer.icon_allAppsCustomizeFadeAlpha) / 256.0f;
-            mCheckedFadeInDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeInTime);
-            mCheckedFadeOutDuration = r.getInteger(R.integer.icon_allAppsCustomizeFadeOutTime);
+            mCheckedAlpha = r.getInteger(R.integer.config_dragAppsCustomizeIconFadeAlpha) / 256.0f;
+            mCheckedFadeInDuration =
+                r.getInteger(R.integer.config_dragAppsCustomizeIconFadeInDuration);
+            mCheckedFadeOutDuration =
+                r.getInteger(R.integer.config_dragAppsCustomizeIconFadeOutDuration);
         }
+        mDimensionsFormatString = r.getString(R.string.widget_dims_format);
 
-        setFocusable(true);
         setWillNotDraw(false);
         setClipToPadding(false);
     }
@@ -156,13 +182,16 @@
             FastBitmapDrawable preview, int maxWidth, int[] cellSpan,
             PagedViewIconCache cache, boolean createHolographicOutline) {
         final ImageView image = (ImageView) findViewById(R.id.widget_preview);
-        image.setMaxWidth(maxWidth);
+        if (maxWidth > -1) {
+            image.setMaxWidth(maxWidth);
+        }
         image.setImageDrawable(preview);
+        mPreviewImageView = image;
         final TextView name = (TextView) findViewById(R.id.widget_name);
         name.setText(info.label);
         name.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
         final TextView dims = (TextView) findViewById(R.id.widget_dims);
-        dims.setText(mContext.getString(R.string.widget_dims_format, cellSpan[0], cellSpan[1]));
+        dims.setText(String.format(mDimensionsFormatString, cellSpan[0], cellSpan[1]));
         dims.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
 
         if (createHolographicOutline) {
@@ -173,12 +202,35 @@
         }
     }
 
+    public void applyFromResolveInfo(PackageManager pm, ResolveInfo info,
+            FastBitmapDrawable preview, PagedViewIconCache cache, boolean createHolographicOutline){
+        final ImageView image = (ImageView) findViewById(R.id.widget_preview);
+        image.setImageDrawable(preview);
+        mPreviewImageView = image;
+        final TextView name = (TextView) findViewById(R.id.widget_name);
+        name.setText(info.loadLabel(pm));
+        name.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+        final TextView dims = (TextView) findViewById(R.id.widget_dims);
+        if (dims != null) {
+            dims.setText(String.format(mDimensionsFormatString, 1, 1));
+            dims.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+        }
+
+        if (createHolographicOutline) {
+            mIconCache = cache;
+            mIconCacheKey = new PagedViewIconCache.Key(info);
+            mHolographicOutline = mIconCache.getOutline(mIconCacheKey);
+            mPreview = preview;
+        }
+    }
+
     public void applyFromWallpaperInfo(ResolveInfo info, PackageManager packageManager,
             FastBitmapDrawable preview, int maxWidth, PagedViewIconCache cache,
             boolean createHolographicOutline) {
         ImageView image = (ImageView) findViewById(R.id.wallpaper_preview);
         image.setMaxWidth(maxWidth);
         image.setImageDrawable(preview);
+        mPreviewImageView = image;
         TextView name = (TextView) findViewById(R.id.wallpaper_name);
         name.setText(info.loadLabel(packageManager));
         name.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
@@ -204,6 +256,28 @@
     }
 
     @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (LauncherApplication.isScreenLarge()) {
+            return FocusHelper.handlePagedViewWidgetKeyEvent(this, keyCode, event)
+                    || super.onKeyDown(keyCode, event);
+        } else {
+            return FocusHelper.handlePagedViewGridLayoutWidgetKeyEvent(this, keyCode, event)
+                    || super.onKeyDown(keyCode, event);
+        }
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (LauncherApplication.isScreenLarge()) {
+            return FocusHelper.handlePagedViewWidgetKeyEvent(this, keyCode, event)
+                    || super.onKeyUp(keyCode, event);
+        } else {
+            return FocusHelper.handlePagedViewGridLayoutWidgetKeyEvent(this, keyCode, event)
+                    || super.onKeyUp(keyCode, event);
+        }
+    }
+
+    @Override
     protected void onDraw(Canvas canvas) {
         if (mAlpha > 0) {
             super.onDraw(canvas);
@@ -211,8 +285,15 @@
 
         // draw any blended overlays
         if (mHolographicOutline != null && mHolographicAlpha > 0) {
+            // Calculate how much to scale the holographic preview
+            mTmpScaleRect.set(0,0,1,1);
+            mPreviewImageView.getImageMatrix().mapRect(mTmpScaleRect);
+
             mPaint.setAlpha(mHolographicAlpha);
+            canvas.save();
+            canvas.scale(mTmpScaleRect.right, mTmpScaleRect.bottom);
             canvas.drawBitmap(mHolographicOutline, 0, 0, mPaint);
+            canvas.restore();
         }
     }
 
@@ -257,8 +338,7 @@
         sWorker.removeMessages(MESSAGE_CREATE_HOLOGRAPHIC_OUTLINE, this);
     }
 
-    @Override
-    public void setChecked(boolean checked) {
+    void setChecked(boolean checked, boolean animate) {
         if (mIsChecked != checked) {
             mIsChecked = checked;
 
@@ -276,15 +356,24 @@
             if (mCheckedAlphaAnimator != null) {
                 mCheckedAlphaAnimator.cancel();
             }
-            mCheckedAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), alpha);
-            mCheckedAlphaAnimator.setDuration(duration);
-            mCheckedAlphaAnimator.start();
+            if (animate) {
+                mCheckedAlphaAnimator = ObjectAnimator.ofFloat(this, "alpha", getAlpha(), alpha);
+                mCheckedAlphaAnimator.setDuration(duration);
+                mCheckedAlphaAnimator.start();
+            } else {
+                setAlpha(alpha);
+            }
 
             invalidate();
         }
     }
 
     @Override
+    public void setChecked(boolean checked) {
+        setChecked(checked, true);
+    }
+
+    @Override
     public boolean isChecked() {
         return mIsChecked;
     }
diff --git a/src/com/android/launcher2/ShortcutInfo.java b/src/com/android/launcher2/ShortcutInfo.java
index 72f2d51..c0f80ae 100644
--- a/src/com/android/launcher2/ShortcutInfo.java
+++ b/src/com/android/launcher2/ShortcutInfo.java
@@ -148,12 +148,6 @@
         return "ShortcutInfo(title=" + title.toString() + ")";
     }
 
-    @Override
-    void unbind() {
-        super.unbind();
-    }
-
-
     public static void dumpShortcutInfoList(String tag, String label,
             ArrayList<ShortcutInfo> list) {
         Log.d(tag, label + " size=" + list.size());
diff --git a/src/com/android/launcher2/ShortcutsAdapter.java b/src/com/android/launcher2/ShortcutsAdapter.java
index 93c500a..de73c3e 100644
--- a/src/com/android/launcher2/ShortcutsAdapter.java
+++ b/src/com/android/launcher2/ShortcutsAdapter.java
@@ -30,7 +30,7 @@
 /**
  * GridView adapter to show the list of applications and shortcuts
  */
-public class ShortcutsAdapter  extends ArrayAdapter<ShortcutInfo> {
+public class ShortcutsAdapter extends ArrayAdapter<ShortcutInfo> {
     private final LayoutInflater mInflater;
     private final IconCache mIconCache;
 
diff --git a/src/com/android/launcher2/StrokedTextView.java b/src/com/android/launcher2/StrokedTextView.java
new file mode 100644
index 0000000..20f9f48
--- /dev/null
+++ b/src/com/android/launcher2/StrokedTextView.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import com.android.launcher.R;
+
+/**
+ * This class adds a stroke to the generic TextView allowing the text to stand out better against
+ * the background (ie. in the AllApps button).
+ */
+public class StrokedTextView extends TextView {
+    private final Canvas mCanvas = new Canvas();
+    private final Paint mPaint = new Paint();
+    private Bitmap mCache;
+    private boolean mUpdateCachedBitmap;
+    private int mStrokeColor;
+    private float mStrokeWidth;
+    private int mTextColor;
+
+    public StrokedTextView(Context context) {
+        super(context);
+        init(context, null, 0);
+    }
+
+    public StrokedTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context, attrs, 0);
+    }
+
+    public StrokedTextView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(context, attrs, defStyle);
+    }
+
+    private void init(Context context, AttributeSet attrs, int defStyle) {
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StrokedTextView,
+                defStyle, 0);
+        mStrokeColor = a.getColor(R.styleable.StrokedTextView_strokeColor, 0xFF000000);
+        mStrokeWidth = a.getFloat(R.styleable.StrokedTextView_strokeWidth, 0.0f);
+        mTextColor = a.getColor(R.styleable.StrokedTextView_strokeTextColor, 0xFFFFFFFF);
+        a.recycle();
+        mUpdateCachedBitmap = true;
+
+        // Setup the text paint
+        mPaint.setAntiAlias(true);
+        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+    }
+
+    protected void onTextChanged(CharSequence text, int start, int before, int after) {
+        super.onTextChanged(text, start, before, after);
+        mUpdateCachedBitmap = true;
+    }
+
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        if (w > 0 && h > 0) {
+            mUpdateCachedBitmap = true;
+            mCache = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        } else {
+            mCache = null;
+        }
+    }
+
+    protected void onDraw(Canvas canvas) {
+        if (mCache != null) {
+            if (mUpdateCachedBitmap) {
+                final int gap = getCompoundDrawablePadding();
+                final int w = getMeasuredWidth();
+                final int h = getMeasuredHeight();
+                final String text = getText().toString();
+                final Rect textBounds = new Rect();
+                final Paint textPaint = getPaint();
+                final int textWidth = (int) textPaint.measureText(text);
+                textPaint.getTextBounds("x", 0, 1, textBounds);
+
+                // Clear the old cached image
+                mCanvas.setBitmap(mCache);
+                mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
+
+                // Draw the drawable
+                final int drawableLeft = getPaddingLeft();
+                final int drawableTop = getPaddingTop();
+                final Drawable[] drawables = getCompoundDrawables();
+                for (int i = 0; i < drawables.length; ++i) {
+                    if (drawables[i] != null) {
+                        drawables[i].setBounds(drawableLeft, drawableTop,
+                                drawableLeft + drawables[i].getIntrinsicWidth(),
+                                drawableTop + drawables[i].getIntrinsicHeight());
+                        drawables[i].draw(mCanvas);
+                    }
+                }
+
+                final int left = w - getPaddingRight() - textWidth;
+                final int bottom = (h + textBounds.height()) / 2;
+
+                // Draw the outline of the text
+                mPaint.setStrokeWidth(mStrokeWidth);
+                mPaint.setColor(mStrokeColor);
+                mPaint.setTextSize(getTextSize());
+                mCanvas.drawText(text, left, bottom, mPaint);
+
+                // Draw the text itself
+                mPaint.setStrokeWidth(0);
+                mPaint.setColor(mTextColor);
+                mCanvas.drawText(text, left, bottom, mPaint);
+
+                mUpdateCachedBitmap = false;
+            }
+            canvas.drawBitmap(mCache, 0, 0, mPaint);
+        } else {
+            super.onDraw(canvas);
+        }
+    }
+}
diff --git a/src/com/android/launcher2/UserFolder.java b/src/com/android/launcher2/UserFolder.java
deleted file mode 100644
index b362fbd..0000000
--- a/src/com/android/launcher2/UserFolder.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.android.launcher2;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.launcher.R;
-
-/**
- * Folder which contains applications or shortcuts chosen by the user.
- *
- */
-public class UserFolder extends Folder implements DropTarget {
-    private static final String TAG = "Launcher.UserFolder";
-
-    public UserFolder(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-    
-    /**
-     * Creates a new UserFolder, inflated from R.layout.user_folder.
-     *
-     * @param context The application's context.
-     *
-     * @return A new UserFolder.
-     */
-    static UserFolder fromXml(Context context) {
-        return (UserFolder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
-    }
-
-    public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-        final ItemInfo item = (ItemInfo) dragInfo;
-        final int itemType = item.itemType;
-        return (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
-                    itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT)
-                && item.container != mInfo.id;
-    }
-
-    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-        ShortcutInfo item;
-        if (dragInfo instanceof ApplicationInfo) {
-            // Came from all apps -- make a copy
-            item = ((ApplicationInfo)dragInfo).makeShortcut();
-        } else {
-            item = (ShortcutInfo)dragInfo;
-        }
-        ((ShortcutsAdapter)mContent.getAdapter()).add(item);
-        LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, 0, 0);
-    }
-
-    public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-    }
-
-    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-    }
-
-    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-    }
-
-    @Override
-    public void onDropCompleted(View target, boolean success) {
-        if (success) {
-            ShortcutsAdapter adapter = (ShortcutsAdapter)mContent.getAdapter();
-            adapter.remove(mDragItem);
-        }
-    }
-
-    public boolean isDropEnabled() {
-        return true;
-    }
-
-    void bind(FolderInfo info) {
-        super.bind(info);
-        setContentAdapter(new ShortcutsAdapter(mContext, ((UserFolderInfo) info).contents));
-    }
-
-    // When the folder opens, we need to refresh the GridView's selection by
-    // forcing a layout
-    @Override
-    void onOpen() {
-        super.onOpen();
-        requestFocus();
-    }
-
-    @Override
-    public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
-            DragView dragView, Object dragInfo) {
-        return null;
-    }
-}
diff --git a/src/com/android/launcher2/UserFolderInfo.java b/src/com/android/launcher2/UserFolderInfo.java
deleted file mode 100644
index 0b8841c..0000000
--- a/src/com/android/launcher2/UserFolderInfo.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.launcher2;
-
-import android.content.ContentValues;
-
-import java.util.ArrayList;
-
-/**
- * Represents a folder containing shortcuts or apps.
- */
-class UserFolderInfo extends FolderInfo {
-    /**
-     * The apps and shortcuts 
-     */
-    ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
-    
-    UserFolderInfo() {
-        itemType = LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER;
-    }
-    
-    /**
-     * Add an app or shortcut
-     * 
-     * @param item
-     */
-    public void add(ShortcutInfo item) {
-        contents.add(item);
-    }
-    
-    /**
-     * Remove an app or shortcut. Does not change the DB.
-     * 
-     * @param item
-     */
-    public void remove(ShortcutInfo item) {
-        contents.remove(item);
-    }
-    
-    @Override
-    void onAddToDatabase(ContentValues values) { 
-        super.onAddToDatabase(values);
-        values.put(LauncherSettings.Favorites.TITLE, title.toString());
-    }
-}
diff --git a/src/com/android/launcher2/Utilities.java b/src/com/android/launcher2/Utilities.java
index 60f71f5..ba25893 100644
--- a/src/com/android/launcher2/Utilities.java
+++ b/src/com/android/launcher2/Utilities.java
@@ -16,6 +16,8 @@
 
 package com.android.launcher2;
 
+import java.util.Random;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -51,6 +53,7 @@
 
     private static int sIconWidth = -1;
     private static int sIconHeight = -1;
+    private static int sIconContentSize = -1;
     private static int sIconTextureWidth = -1;
     private static int sIconTextureHeight = -1;
 
@@ -90,6 +93,10 @@
     static int sColors[] = { 0xffff0000, 0xff00ff00, 0xff0000ff };
     static int sColorIndex = 0;
 
+    static int getIconContentSize() {
+        return sIconContentSize;
+    }
+
     /**
      * Returns a bitmap suitable for the all apps view.  The bitmap will be a power
      * of two sized ARGB_8888 bitmap that can be used as a gl texture.
@@ -236,6 +243,9 @@
         final float density = metrics.density;
 
         sIconWidth = sIconHeight = (int) resources.getDimension(R.dimen.app_icon_size);
+        if (LauncherApplication.isScreenLarge()) {
+            sIconContentSize = (int) resources.getDimension(R.dimen.app_icon_content_size);
+        }
         sIconTextureWidth = sIconTextureHeight = sIconWidth + 2;
 
         sBlurPaint.setMaskFilter(new BlurMaskFilter(5 * density, BlurMaskFilter.Blur.NORMAL));
@@ -381,4 +391,8 @@
         }
         return n;
     }
+
+    static int generateRandomId() {
+        return new Random(System.currentTimeMillis()).nextInt(1 << 24);
+    }
 }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 0daed37..bc15b32 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -16,14 +16,14 @@
 
 package com.android.launcher2;
 
-import com.android.launcher.R;
-import com.android.launcher2.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.animation.Animator.AnimatorListener;
@@ -38,7 +38,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.content.pm.ProviderInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
@@ -50,10 +49,10 @@
 import android.graphics.RectF;
 import android.graphics.Region.Op;
 import android.graphics.drawable.Drawable;
-import android.net.Uri;
 import android.os.IBinder;
 import android.os.Parcelable;
 import android.util.AttributeSet;
+import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Pair;
 import android.view.Display;
@@ -62,12 +61,13 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.animation.DecelerateInterpolator;
+import android.widget.TabHost;
+import android.widget.TabWidget;
 import android.widget.TextView;
 import android.widget.Toast;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
+import com.android.launcher.R;
+import com.android.launcher2.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
 
 /**
  * The workspace is a wide area with a wallpaper and a finite number of pages.
@@ -75,7 +75,8 @@
  * interact with. A workspace is meant to be used with a fixed width only.
  */
 public class Workspace extends SmoothPagedView
-        implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
+        implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
+        View.OnClickListener {
     @SuppressWarnings({"UnusedDeclaration"})
     private static final String TAG = "Launcher.Workspace";
 
@@ -108,10 +109,11 @@
     private float mChildrenOutlineAlpha = 0;
 
     // These properties refer to the background protection gradient used for AllApps and Customize
-    private ObjectAnimator mBackgroundFadeInAnimation;
-    private ObjectAnimator mBackgroundFadeOutAnimation;
+    private ValueAnimator mBackgroundFadeInAnimation;
+    private ValueAnimator mBackgroundFadeOutAnimation;
     private Drawable mBackground;
     private Drawable mCustomizeTrayBackground;
+    boolean mDrawBackground = true;
     private boolean mDrawCustomizeTrayBackground;
     private float mBackgroundAlpha = 0;
     private float mOverScrollMaxBackgroundAlpha = 0.0f;
@@ -123,10 +125,12 @@
     private float[] mCustomizationDrawerTransformedPos = new float[2];
 
     private final WallpaperManager mWallpaperManager;
+    private IBinder mWindowToken;
 
     private int mDefaultPage;
 
     private boolean mIsDragInProcess = false;
+    private boolean mIsDraggingOverIcon = false;
 
     /**
      * CellInfo for the cell that is currently being dragged
@@ -151,12 +155,13 @@
     // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
     private int[] mTempCell = new int[2];
     private int[] mTempEstimate = new int[2];
-    private float[] mTempOriginXY = new float[2];
+    private float[] mDragViewVisualCenter = new float[2];
     private float[] mTempDragCoordinates = new float[2];
     private float[] mTempTouchCoordinates = new float[2];
     private float[] mTempCellLayoutCenterCoordinates = new float[2];
     private float[] mTempDragBottomRightCoordinates = new float[2];
     private Matrix mTempInverseMatrix = new Matrix();
+    private int[] mTempLocation = new int[2];
 
     private SpringLoadedDragController mSpringLoadedDragController;
 
@@ -209,6 +214,7 @@
     WallpaperOffsetInterpolator mWallpaperOffset;
     boolean mUpdateWallpaperOffsetImmediately = false;
     boolean mSyncWallpaperOffsetWithScroll = true;
+    private Runnable mDelayedResizeRunnable;
 
     // info about the last drag
     private DragView mLastDragView;
@@ -217,6 +223,8 @@
     private int mLastDragXOffset;
     private int mLastDragYOffset;
 
+    private ArrayList<FolderIcon> mFolderOuterRings = new ArrayList<FolderIcon>();
+
     // Variables relating to touch disambiguation (scrolling workspace vs. scrolling a widget)
     private float mXDown;
     private float mYDown;
@@ -224,9 +232,6 @@
     final static float MAX_SWIPE_ANGLE = (float) Math.PI / 3;
     final static float TOUCH_SLOP_DAMPING_FACTOR = 4;
 
-    int mSpringLoadedDropX;
-    int mSpringLoadedDropY;
-
     /**
      * Used to inflate the Workspace from XML.
      *
@@ -248,16 +253,60 @@
         super(context, attrs, defStyle);
         mContentIsRefreshable = false;
 
-        if (!LauncherApplication.isScreenXLarge()) {
+        if (!LauncherApplication.isScreenLarge()) {
             mFadeInAdjacentScreens = false;
         }
 
         mWallpaperManager = WallpaperManager.getInstance(context);
 
+        int cellCountX = DEFAULT_CELL_COUNT_X;
+        int cellCountY = DEFAULT_CELL_COUNT_Y;
+
         TypedArray a = context.obtainStyledAttributes(attrs,
                 R.styleable.Workspace, defStyle, 0);
-        int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X);
-        int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y);
+
+        if (LauncherApplication.isScreenLarge()) {
+            final Resources res = context.getResources();
+            final DisplayMetrics dm = res.getDisplayMetrics();
+            float widthDp = dm.widthPixels / dm.density;
+            float heightDp = dm.heightPixels / dm.density;
+
+            final float statusBarHeight = res.getDimension(R.dimen.status_bar_height);
+            TypedArray actionBarSizeTypedArray =
+                context.obtainStyledAttributes(new int[] { android.R.attr.actionBarSize });
+            float actionBarHeight = actionBarSizeTypedArray.getDimension(0, 0f);
+
+            if (heightDp > widthDp) {
+                float temp = widthDp;
+                widthDp = heightDp;
+                heightDp = temp;
+            }
+            int cellCountXLand = 1;
+            int cellCountXPort = 1;
+            while (2*mPageSpacing + CellLayout.widthInLandscape(res, cellCountXLand + 1) <= widthDp) {
+                cellCountXLand++;
+            }
+            while (CellLayout.widthInPortrait(res, cellCountXPort + 1) <= heightDp) {
+                cellCountXPort++;
+            }
+            cellCountX = Math.min(cellCountXLand, cellCountXPort);
+
+            int cellCountYLand = 1;
+            int cellCountYPort = 1;
+            while (statusBarHeight + actionBarHeight +
+                    CellLayout.heightInLandscape(res, cellCountYLand + 1) <= heightDp) {
+                cellCountYLand++;
+            }
+            while (statusBarHeight + actionBarHeight +
+                    CellLayout.heightInPortrait(res, cellCountYPort + 1) <= widthDp) {
+                cellCountYPort++;
+            }
+            cellCountY = Math.min(cellCountYLand, cellCountYPort);
+        }
+
+        // if the value is manually specified, use that instead
+        cellCountX = a.getInt(R.styleable.Workspace_cellCountX, cellCountX);
+        cellCountY = a.getInt(R.styleable.Workspace_cellCountY, cellCountY);
         mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
         a.recycle();
 
@@ -265,6 +314,9 @@
         setHapticFeedbackEnabled(false);
 
         initWorkspace();
+
+        // Disable multitouch across the workspace/all apps/customize tray
+        setMotionEventSplittingEnabled(true);
     }
 
     /**
@@ -329,55 +381,51 @@
 
     @Override
     protected int getScrollMode() {
-        if (LauncherApplication.isScreenXLarge()) {
+        if (LauncherApplication.isScreenLarge()) {
             return SmoothPagedView.X_LARGE_MODE;
         } else {
             return SmoothPagedView.DEFAULT_MODE;
         }
     }
 
-    @Override
-    public void addView(View child, int index, LayoutParams params) {
+    private void onAddView(View child) {
         if (!(child instanceof CellLayout)) {
             throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
         }
-        ((CellLayout) child).setOnInterceptTouchListener(this);
+        CellLayout cl = ((CellLayout) child);
+        cl.setOnInterceptTouchListener(this);
+        cl.setOnClickListener(this);
+        cl.setClickable(true);
+        cl.enableHardwareLayers();
+    }
+
+    @Override
+    public void addView(View child, int index, LayoutParams params) {
+        onAddView(child);
         super.addView(child, index, params);
     }
 
     @Override
     public void addView(View child) {
-        if (!(child instanceof CellLayout)) {
-            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
-        }
-        ((CellLayout) child).setOnInterceptTouchListener(this);
+        onAddView(child);
         super.addView(child);
     }
 
     @Override
     public void addView(View child, int index) {
-        if (!(child instanceof CellLayout)) {
-            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
-        }
-        ((CellLayout) child).setOnInterceptTouchListener(this);
+        onAddView(child);
         super.addView(child, index);
     }
 
     @Override
     public void addView(View child, int width, int height) {
-        if (!(child instanceof CellLayout)) {
-            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
-        }
-        ((CellLayout) child).setOnInterceptTouchListener(this);
+        onAddView(child);
         super.addView(child, width, height);
     }
 
     @Override
     public void addView(View child, LayoutParams params) {
-        if (!(child instanceof CellLayout)) {
-            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
-        }
-        ((CellLayout) child).setOnInterceptTouchListener(this);
+        onAddView(child);
         super.addView(child, params);
     }
 
@@ -418,8 +466,8 @@
         return folders;
     }
 
-    boolean isDefaultPageShowing() {
-        return mCurrentPage == mDefaultPage;
+    boolean isTouchActive() {
+        return mTouchState != TOUCH_STATE_REST;
     }
 
     /**
@@ -471,6 +519,10 @@
             lp.cellVSpan = spanY;
         }
 
+        if (spanX < 0 && spanY < 0) {
+            lp.isLockedToGrid = false;
+        }
+
         // Get the canonical child id to uniquely represent this view in this screen
         int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
         boolean markCellsAsOccupied = !(child instanceof Folder);
@@ -520,16 +572,25 @@
         return hitsPage(current + 1, x, y);
     }
 
+    /**
+     * Called directly from a CellLayout (not by the framework), after we've been added as a
+     * listener via setOnInterceptTouchEventListener(). This allows us to tell the CellLayout
+     * that it should intercept touch events, which is not something that is normally supported.
+     */
+    @Override
     public boolean onTouch(View v, MotionEvent event) {
-        // this is an intercepted event being forwarded from a cell layout
-        if (mIsSmall || mIsInUnshrinkAnimation) {
-            // Only allow clicks on a CellLayout if it is visible
-            if (mShrinkState != ShrinkState.BOTTOM_HIDDEN) {
-                mLauncher.onWorkspaceClick((CellLayout) v);
-            }
-            return true;
+        return (mIsSmall || mIsInUnshrinkAnimation);
+    }
+
+    /**
+     * Handle a click event on a CellLayout.
+     */
+    @Override
+    public void onClick(View cellLayout) {
+        // Only allow clicks on a CellLayout if it is shrunken and visible.
+        if ((mIsSmall || mIsInUnshrinkAnimation) && mShrinkState != ShrinkState.BOTTOM_HIDDEN) {
+            mLauncher.onWorkspaceClick((CellLayout) cellLayout);
         }
-        return false;
     }
 
     protected void onWindowVisibilityChanged (int visibility) {
@@ -553,8 +614,7 @@
         }
 
         if (mIsSmall || mIsInUnshrinkAnimation) {
-            if (mLauncher.isAllAppsVisible() &&
-                    mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
+            if (mLauncher.isAllAppsVisible() && mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
                 // Intercept this event so we can show the workspace in full view
                 // when it is clicked on and it is small
                 AllAppsPagedView allApps = (AllAppsPagedView)
@@ -623,6 +683,11 @@
         }
         mOverScrollMaxBackgroundAlpha = 0.0f;
         mOverScrollPageIndex = -1;
+
+        if (mDelayedResizeRunnable != null) {
+            mDelayedResizeRunnable.run();
+            mDelayedResizeRunnable = null;
+        }
     }
 
     @Override
@@ -689,7 +754,11 @@
         // parallax effects
         mWallpaperWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
         mWallpaperHeight = (int)(maxDim * wallpaperTravelToScreenHeightRatio(maxDim, minDim));
-        mWallpaperManager.suggestDesiredDimensions(mWallpaperWidth, mWallpaperHeight);
+        new Thread("setWallpaperDimension") {
+            public void run() {
+                mWallpaperManager.suggestDesiredDimensions(mWallpaperWidth, mWallpaperHeight);
+            }
+        }.start();
     }
 
     public void setVerticalWallpaperOffset(float offset) {
@@ -707,11 +776,15 @@
 
     private float wallpaperOffsetForCurrentScroll() {
         Display display = mLauncher.getWindowManager().getDefaultDisplay();
+        final boolean isStaticWallpaper = (mWallpaperManager.getWallpaperInfo() == null);
         // The wallpaper travel width is how far, from left to right, the wallpaper will move
         // at this orientation (for example, in portrait mode we don't move all the way to the
         // edges of the wallpaper, or otherwise the parallax effect would be too strong)
         int wallpaperTravelWidth = (int) (display.getWidth() *
                 wallpaperTravelToScreenWidthRatio(display.getWidth(), display.getHeight()));
+        if (!isStaticWallpaper) {
+            wallpaperTravelWidth = mWallpaperWidth;
+        }
 
         // Set wallpaper offset steps (1 / (number of screens - 1))
         // We have 3 vertical offset states (centered, and then top/bottom aligned
@@ -725,7 +798,6 @@
         // you overscroll as far as you can in landscape mode. Only do this for static wallpapers
         // because live wallpapers (and probably 3rd party wallpaper providers) rely on the offset
         // being even intervals from 0 to 1 (eg [0, 0.25, 0.5, 0.75, 1])
-        final boolean isStaticWallpaper = (mWallpaperManager.getWallpaperInfo() == null);
         if (isStaticWallpaper) {
             int overscrollOffset = (int) (maxOverScroll() * display.getWidth());
             scrollProgressOffset += overscrollOffset / (float) getScrollRange();
@@ -735,12 +807,13 @@
         float scrollProgress =
             mScrollX / (float) scrollRange + scrollProgressOffset;
         float offsetInDips = wallpaperTravelWidth * scrollProgress +
-            (mWallpaperWidth - wallpaperTravelWidth) / 2;
+            (mWallpaperWidth - wallpaperTravelWidth) / 2; // center it
         float offset = offsetInDips / (float) mWallpaperWidth;
         return offset;
     }
     private void syncWallpaperOffsetWithScroll() {
-        if (LauncherApplication.isScreenXLarge()) {
+        final boolean enableWallpaperEffects = isHardwareAccelerated();
+        if (enableWallpaperEffects) {
             mWallpaperOffset.setFinalX(wallpaperOffsetForCurrentScroll());
         }
     }
@@ -761,14 +834,13 @@
             updateNow = keepUpdating = mWallpaperOffset.computeScrollOffset();
         }
         if (updateNow) {
-            IBinder token = getWindowToken();
-            if (token != null) {
-                mWallpaperManager.setWallpaperOffsets(getWindowToken(),
+            if (mWindowToken != null) {
+                mWallpaperManager.setWallpaperOffsets(mWindowToken,
                         mWallpaperOffset.getCurrX(), mWallpaperOffset.getCurrY());
             }
         }
         if (keepUpdating) {
-            invalidate();
+            fastInvalidate();
         }
     }
 
@@ -891,7 +963,7 @@
         }
     }
 
-    public void showOutlines() {
+    void showOutlines() {
         if (!mIsSmall && !mIsInUnshrinkAnimation) {
             if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
             if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
@@ -901,7 +973,7 @@
         }
     }
 
-    public void hideOutlines() {
+    void hideOutlines() {
         if (!mIsSmall && !mIsInUnshrinkAnimation) {
             if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
             if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
@@ -912,6 +984,12 @@
         }
     }
 
+    public void showOutlinesTemporarily() {
+        if (!mIsPageMoving && !isTouchActive()) {
+            snapToPage(mCurrentPage);
+        }
+    }
+
     public void setChildrenOutlineAlpha(float alpha) {
         mChildrenOutlineAlpha = alpha;
         for (int i = 0; i < getChildCount(); i++) {
@@ -924,6 +1002,13 @@
         return mChildrenOutlineAlpha;
     }
 
+    void disableBackground() {
+        mDrawBackground = false;
+    }
+    void enableBackground() {
+        mDrawBackground = true;
+    }
+
     private void showBackgroundGradientForAllApps() {
         showBackgroundGradient();
         mDrawCustomizeTrayBackground = false;
@@ -938,7 +1023,12 @@
         if (mBackground == null) return;
         if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
         if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
-        mBackgroundFadeInAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 1.0f);
+        mBackgroundFadeInAnimation = ValueAnimator.ofFloat(getBackgroundAlpha(), 1f);
+        mBackgroundFadeInAnimation.addUpdateListener(new AnimatorUpdateListener() {
+            public void onAnimationUpdate(ValueAnimator animation) {
+                setBackgroundAlpha(((Float) animation.getAnimatedValue()).floatValue());
+            }
+        });
         mBackgroundFadeInAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
         mBackgroundFadeInAnimation.setDuration(BACKGROUND_FADE_IN_DURATION);
         mBackgroundFadeInAnimation.start();
@@ -948,15 +1038,22 @@
         if (mBackground == null) return;
         if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
         if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
-        mBackgroundFadeOutAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 0.0f);
+        mBackgroundFadeOutAnimation = ValueAnimator.ofFloat(getBackgroundAlpha(), 0f);
+        mBackgroundFadeOutAnimation.addUpdateListener(new AnimatorUpdateListener() {
+            public void onAnimationUpdate(ValueAnimator animation) {
+                setBackgroundAlpha(((Float) animation.getAnimatedValue()).floatValue());
+            }
+        });
         mBackgroundFadeOutAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
         mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
         mBackgroundFadeOutAnimation.start();
     }
 
     public void setBackgroundAlpha(float alpha) {
-        mBackgroundAlpha = alpha;
-        invalidate();
+        if (alpha != mBackgroundAlpha) {
+            mBackgroundAlpha = alpha;
+            invalidate();
+        }
     }
 
     public float getBackgroundAlpha() {
@@ -1014,6 +1111,11 @@
 
     @Override
     protected void screenScrolled(int screenCenter) {
+        // If the screen is not xlarge, then don't rotate the CellLayouts
+        // NOTE: If we don't update the side pages alpha, then we should not hide the side pages.
+        //       see unshrink().
+        if (!LauncherApplication.isScreenLarge()) return;
+
         final int halfScreenSize = getMeasuredWidth() / 2;
 
         for (int i = 0; i < getChildCount(); i++) {
@@ -1050,8 +1152,13 @@
 
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
+        mWindowToken = getWindowToken();
         computeScroll();
-        mDragController.setWindowToken(getWindowToken());
+        mDragController.setWindowToken(mWindowToken);
+    }
+
+    protected void onDetachedFromWindow() {
+        mWindowToken = null;
     }
 
     @Override
@@ -1081,12 +1188,22 @@
         }
     }
 
+    public void showFolderAccept(FolderIcon fi) {
+        mFolderOuterRings.add(fi);
+    }
+
+    public void hideFolderAccept(FolderIcon fi) {
+        if (mFolderOuterRings.contains(fi)) {
+            mFolderOuterRings.remove(fi);
+        }
+    }
+
     @Override
     protected void onDraw(Canvas canvas) {
         updateWallpaperOffsets();
 
         // Draw the background gradient if necessary
-        if (mBackground != null && mBackgroundAlpha > 0.0f) {
+        if (mBackground != null && mBackgroundAlpha > 0.0f && mDrawBackground) {
             int alpha = (int) (mBackgroundAlpha * 255);
             if (mDrawCustomizeTrayBackground) {
                 // Find out where to offset the gradient for the customization tray content
@@ -1116,6 +1233,30 @@
                 mBackground.draw(canvas);
             }
         }
+
+        // The folder outer / inner ring image(s)
+        for (int i = 0; i < mFolderOuterRings.size(); i++) {
+
+            // Draw outer ring
+            FolderIcon fi = mFolderOuterRings.get(i);
+            Drawable d = FolderIcon.sFolderOuterRingDrawable;
+            int width = (int) (d.getIntrinsicWidth() * fi.getOuterRingScale());
+            int height = (int) (d.getIntrinsicHeight() * fi.getOuterRingScale());
+            fi.getFolderLocation(mTempLocation);
+            int x = mTempLocation[0] + mScrollX - width / 2;
+            int y = mTempLocation[1] + mScrollY - height / 2;
+            d.setBounds(x, y, x + width, y + height);
+            d.draw(canvas);
+
+            // Draw inner ring
+            d = FolderIcon.sFolderInnerRingDrawable;
+            width = (int) (fi.getMeasuredWidth() * fi.getInnerRingScale());
+            height = (int) (fi.getMeasuredHeight() * fi.getInnerRingScale());
+            x = mTempLocation[0] + mScrollX - width / 2;
+            y = mTempLocation[1] + mScrollY - height / 2;
+            d.setBounds(x, y, x + width, y + height);
+            d.draw(canvas);
+        }
         super.onDraw(canvas);
     }
 
@@ -1126,9 +1267,11 @@
             final int pageCount = getChildCount();
             final long drawingTime = getDrawingTime();
             for (int i = 0; i < pageCount; i++) {
-                final View page = (View) getChildAt(i);
-
-                drawChild(canvas, page, drawingTime);
+                final CellLayout page = (CellLayout) getChildAt(i);
+                if (page.getVisibility() == VISIBLE
+                        && (page.getAlpha() != 0f || page.getBackgroundAlpha() != 0f)) {
+                    drawChild(canvas, page, drawingTime);
+                }
             }
         } else {
             super.dispatchDraw(canvas);
@@ -1184,6 +1327,14 @@
     }
 
     @Override
+    public int getDescendantFocusability() {
+        if (mIsSmall) {
+            return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
+        }
+        return super.getDescendantFocusability();
+    }
+
+    @Override
     public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
         if (!mLauncher.isAllAppsVisible()) {
             final Folder openFolder = getOpenFolder();
@@ -1195,19 +1346,6 @@
         }
     }
 
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
-            // ie when you click on a mini-screen, it zooms back to that screen)
-            if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
-                return false;
-            }
-        }
-
-        return super.dispatchTouchEvent(ev);
-    }
-
     void enableChildrenCache(int fromPage, int toPage) {
         if (fromPage > toPage) {
             final int temp = fromPage;
@@ -1237,27 +1375,32 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        AllAppsPagedView allApps = (AllAppsPagedView)
-                mLauncher.findViewById(R.id.all_apps_paged_view);
-
-        if (mLauncher.isAllAppsVisible() && mShrinkState == ShrinkState.BOTTOM_HIDDEN
-                && allApps != null) {
-            if (ev.getAction() == MotionEvent.ACTION_UP &&
-                    allApps.getTouchState() == TOUCH_STATE_REST) {
-
-                // Cancel any scrolling that is in progress.
-                if (!mScroller.isFinished()) {
-                    mScroller.abortAnimation();
-                }
-                setCurrentPage(mCurrentPage);
-
-                if (mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
-                    mLauncher.showWorkspace(true);
-                }
-                allApps.onTouchEvent(ev);
-                return true;
+        if (mLauncher.isAllAppsVisible() && mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
+            PagedView appsPane;
+            if (LauncherApplication.isScreenLarge()) {
+                appsPane = (PagedView) mLauncher.findViewById(R.id.all_apps_paged_view);
             } else {
-                return allApps.onTouchEvent(ev);
+                appsPane = (PagedView) mLauncher.findViewById(R.id.apps_customize_pane_content);
+            }
+
+            if (appsPane != null) {
+                if (ev.getAction() == MotionEvent.ACTION_UP &&
+                        appsPane.getTouchState() == TOUCH_STATE_REST) {
+
+                    // Cancel any scrolling that is in progress.
+                    if (!mScroller.isFinished()) {
+                        mScroller.abortAnimation();
+                    }
+                    setCurrentPage(mCurrentPage);
+
+                    if (mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
+                        mLauncher.showWorkspace(true);
+                    }
+                    appsPane.onTouchEvent(ev);
+                    return true;
+                } else {
+                    return appsPane.onTouchEvent(ev);
+                }
             }
         }
         return super.onTouchEvent(ev);
@@ -1317,16 +1460,21 @@
         shrink(shrinkState, true);
     }
 
+    private int getCustomizeDrawerHeight() {
+        TabHost customizationDrawer = mLauncher.getCustomizationDrawer();
+        int height = customizationDrawer.getHeight();
+        TabWidget tabWidget = (TabWidget)
+            customizationDrawer.findViewById(com.android.internal.R.id.tabs);
+        if (tabWidget.getTabCount() > 0) {
+            TextView tabText = (TextView) tabWidget.getChildTabViewAt(0);
+            // subtract the empty space above the tab text
+            height -= ((tabWidget.getHeight() - tabText.getLineHeight())) / 2;
+        }
+        return height;
+    }
+
     // we use this to shrink the workspace for the all apps view and the customize view
     public void shrink(ShrinkState shrinkState, boolean animated) {
-        // In the launcher interaction model, we're never in the state where we're shrunken and
-        // visible in the bottom of the screen, and then want to fade to being invisible.
-        // After spring loaded mode ends, this method was getting called twice, the first time
-        // with BOTTOM_VISIBLE (what we want) and a second time with BOTTOM_INVISIBLE (not
-        // what we want). As a temporary solution, we just change the second call to BOTTOM_VISIBLE
-        if (mIsSmall && mShrinkState == ShrinkState.BOTTOM_VISIBLE) {
-            shrinkState = ShrinkState.BOTTOM_VISIBLE;
-        }
         if (mFirstLayout) {
             // (mFirstLayout == "first layout has not happened yet")
             // if we get a call to shrink() as part of our initialization (for example, if
@@ -1393,14 +1541,12 @@
             y = screenHeight / 2 - scaledPageHeight / 2;
             finalAlpha = 1.0f;
         } else if (shrinkState == ShrinkState.TOP) {
-            y = (isPortrait ?
-                getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginPortrait) :
-                getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginLandscape));
+            y = (screenHeight - getCustomizeDrawerHeight() - scaledPageHeight) / 2;
         }
 
         int duration;
         if (shrinkState == ShrinkState.BOTTOM_HIDDEN || shrinkState == ShrinkState.BOTTOM_VISIBLE) {
-            duration = res.getInteger(R.integer.config_allAppsWorkspaceShrinkTime);
+            duration = res.getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime);
         } else {
             duration = res.getInteger(R.integer.config_customizeWorkspaceShrinkTime);
         }
@@ -1446,6 +1592,11 @@
 
             oldAlphas[i] = cl.getAlpha();
             newAlphas[i] = finalAlpha;
+            if (animated && (oldAlphas[i] != 0f || newAlphas[i] != 0f)) {
+                // if the CellLayout will be visible during the animation, force building its
+                // hardware layer immediately so we don't see a blip later in the animation
+                cl.buildChildrenLayer();
+            }
             if (animated) {
                 oldXs[i] = cl.getX();
                 oldYs[i] = cl.getY();
@@ -1480,30 +1631,35 @@
         float offsetFromCenter = (wallpaperTravelHeight / (float) mWallpaperHeight) / 2f;
         boolean isLandscape = display.getWidth() > display.getHeight();
 
-        switch (shrinkState) {
-            // animating in
-            case TOP:
-                // customize
-                wallpaperOffset = 0.5f + offsetFromCenter;
-                mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.46f : 0.44f);
-                break;
-            case MIDDLE:
-            case SPRING_LOADED:
-                wallpaperOffset = 0.5f;
-                mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.34f : 0.32f);
-                break;
-            case BOTTOM_HIDDEN:
-            case BOTTOM_VISIBLE:
-                // allapps
-                wallpaperOffset = 0.5f - offsetFromCenter;
-                mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.34f : 0.32f);
-                break;
+        final boolean enableWallpaperEffects = isHardwareAccelerated();
+        if (enableWallpaperEffects) {
+            switch (shrinkState) {
+                // animating in
+                case TOP:
+                    // customize
+                    wallpaperOffset = 0.5f + offsetFromCenter;
+                    mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.46f : 0.44f);
+                    break;
+                case MIDDLE:
+                case SPRING_LOADED:
+                    wallpaperOffset = 0.5f;
+                    mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.34f : 0.32f);
+                    break;
+                case BOTTOM_HIDDEN:
+                case BOTTOM_VISIBLE:
+                    // allapps
+                    wallpaperOffset = 0.5f - offsetFromCenter;
+                    mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.34f : 0.32f);
+                    break;
+            }
         }
 
         setLayoutScale(1.0f);
         if (animated) {
-            mWallpaperOffset.setHorizontalCatchupConstant(0.46f);
-            mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
+            if (enableWallpaperEffects) {
+                mWallpaperOffset.setHorizontalCatchupConstant(0.46f);
+                mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
+            }
 
             mSyncWallpaperOffsetWithScroll = false;
 
@@ -1515,15 +1671,19 @@
             final float oldVerticalWallpaperOffset = getVerticalWallpaperOffset();
             final float newHorizontalWallpaperOffset = 0.5f;
             final float newVerticalWallpaperOffset = wallpaperOffset;
-            animWithInterpolator.addUpdateListener(new AnimatorUpdateListener() {
-                public void onAnimationUpdate(ValueAnimator animation) {
+            animWithInterpolator.addUpdateListener(new LauncherAnimatorUpdateListener() {
+                public void onAnimationUpdate(float a, float b) {
+                    if (b == 0f) {
+                        // an optimization, and required for correct behavior.
+                        return;
+                    }
                     fastInvalidate();
-                    final float b = (Float) animation.getAnimatedValue();
-                    final float a = 1f - b;
-                    setHorizontalWallpaperOffset(
+                    if (enableWallpaperEffects) {
+                        setHorizontalWallpaperOffset(
                             a * oldHorizontalWallpaperOffset + b * newHorizontalWallpaperOffset);
-                    setVerticalWallpaperOffset(
+                        setVerticalWallpaperOffset(
                             a * oldVerticalWallpaperOffset + b * newVerticalWallpaperOffset);
+                    }
                     for (int i = 0; i < screenCount; i++) {
                         final CellLayout cl = (CellLayout) getChildAt(i);
                         cl.fastInvalidate();
@@ -1541,7 +1701,7 @@
             mAnimator.playTogether(animWithInterpolator);
             mAnimator.addListener(mShrinkAnimationListener);
             mAnimator.start();
-        } else {
+        } else if (enableWallpaperEffects) {
             setVerticalWallpaperOffset(wallpaperOffset);
             setHorizontalWallpaperOffset(0.5f);
             updateWallpaperOffsetImmediately();
@@ -1628,39 +1788,57 @@
         for (int i = 0; i < screenCount; i++) {
             CellLayout cl = (CellLayout) getChildAt(i);
             cl.setIsDragOccuring(isDragHappening);
-            switch (state) {
-                case TOP:
-                    cl.setIsDefaultDropTarget(i == mCurrentPage);
-                case BOTTOM_HIDDEN:
-                case BOTTOM_VISIBLE:
-                case SPRING_LOADED:
-                    if (state != ShrinkState.TOP) {
-                        cl.setIsDefaultDropTarget(false);
-                    }
-                    if (!isDragHappening) {
-                        // even if a drag isn't happening, we don't want to show a screen as
-                        // accepting drops if it doesn't have at least one free cell
-                        spanX = 1;
-                        spanY = 1;
-                    }
-                    // the page accepts drops if we can find at least one empty spot
-                    cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
-                    break;
-                default:
-                     throw new RuntimeException("Unhandled ShrinkState " + state);
+            if (state == null) {
+                // If we are not in a shrunken state, mark all cell layouts as droppable (if they
+                // have the space)
+                cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
+            } else {
+                switch (state) {
+                    case TOP:
+                        cl.setIsDefaultDropTarget(i == mCurrentPage);
+                    case BOTTOM_HIDDEN:
+                    case BOTTOM_VISIBLE:
+                    case SPRING_LOADED:
+                        if (state != ShrinkState.TOP) {
+                            cl.setIsDefaultDropTarget(false);
+                        }
+                        if (!isDragHappening) {
+                            // even if a drag isn't happening, we don't want to show a screen as
+                            // accepting drops if it doesn't have at least one free cell
+                            spanX = 1;
+                            spanY = 1;
+                        }
+                        // the page accepts drops if we can find at least one empty spot
+                        cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
+                        break;
+                    default:
+                         throw new RuntimeException("Unhandled ShrinkState " + state);
+                }
             }
         }
     }
 
     /*
-     *
-     * We call these methods (onDragStartedWithItemSpans/onDragStartedWithItemMinSize) whenever we
-     * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
-     *
-     * These methods mark the appropriate pages as accepting drops (which alters their visual
-     * appearance).
-     *
-     */
+    *
+    * We call these methods (onDragStartedWithItemSpans/onDragStartedWithSize) whenever we
+    * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
+    *
+    * These methods mark the appropriate pages as accepting drops (which alters their visual
+    * appearance).
+    *
+    */
+    public void onDragStartedWithItem(View v) {
+        mIsDragInProcess = true;
+
+        final Canvas canvas = new Canvas();
+
+        // We need to add extra padding to the bitmap to make room for the glow effect
+        final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
+
+        // The outline is used to visualize where the item will land if dropped
+        mDragOutline = createDragOutline(v, canvas, bitmapPadding);
+    }
+
     public void onDragStartedWithItemSpans(int spanX, int spanY, Bitmap b) {
         mIsDragInProcess = true;
 
@@ -1670,9 +1848,11 @@
         final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
 
         CellLayout cl = (CellLayout) getChildAt(0);
-        int[] desiredSize = cl.cellSpansToSize(spanX, spanY);
+
+        int[] size = cl.cellSpansToSize(spanX, spanY);
+
         // The outline is used to visualize where the item will land if dropped
-        mDragOutline = createDragOutline(b, canvas, bitmapPadding, desiredSize[0], desiredSize[1]);
+        mDragOutline = createDragOutline(b, canvas, bitmapPadding, size[0], size[1]);
 
         updateWhichPagesAcceptDropsDuringDrag(mShrinkState, spanX, spanY);
     }
@@ -1719,6 +1899,11 @@
         }
     }
 
+    public void exitWidgetResizeMode() {
+        DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
+        dragLayer.clearAllResizeFrames();
+    }
+
     void unshrink(boolean animated) {
         unshrink(animated, false);
     }
@@ -1762,20 +1947,34 @@
 
             for (int i = 0; i < screenCount; i++) {
                 final CellLayout cl = (CellLayout)getChildAt(i);
-                float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
+                float finalAlphaValue = 0f;
+                float rotation = 0f;
+                if (LauncherApplication.isScreenLarge()) {
+                    finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
+
+                    if (i < mCurrentPage) {
+                        rotation = WORKSPACE_ROTATION;
+                    } else if (i > mCurrentPage) {
+                        rotation = -WORKSPACE_ROTATION;
+                    }
+                } else {
+                    // Don't hide the side panes on the phone if we don't also update the side pages
+                    // alpha.  See screenScrolled().
+                    finalAlphaValue = 1f;
+                }
                 float finalAlphaMultiplierValue =
                         ((i == mCurrentPage) && (mShrinkState != ShrinkState.SPRING_LOADED)) ?
                         0.0f : 1.0f;
-                float rotation = 0.0f;
 
-                if (i < mCurrentPage) {
-                    rotation = WORKSPACE_ROTATION;
-                } else if (i > mCurrentPage) {
-                    rotation = -WORKSPACE_ROTATION;
+                float translation = 0f;
+
+                // If the screen is not xlarge, then don't rotate the CellLayouts
+                // NOTE: If we don't update the side pages alpha, then we should not hide the side
+                //       pages. see unshrink().
+                if (LauncherApplication.isScreenLarge()) {
+                    translation = getOffsetXForRotation(rotation, cl.getWidth(), cl.getHeight());
                 }
 
-                float translation = getOffsetXForRotation(rotation, cl.getWidth(), cl.getHeight());
-
                 oldAlphas[i] = cl.getAlpha();
                 newAlphas[i] = finalAlphaValue;
                 if (animated) {
@@ -1808,52 +2007,62 @@
             }
             Display display = mLauncher.getWindowManager().getDefaultDisplay();
             boolean isLandscape = display.getWidth() > display.getHeight();
-            switch (mShrinkState) {
-                // animating out
-                case TOP:
-                    // customize
-                    if (animated) {
-                        mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.65f : 0.62f);
-                        mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.65f : 0.62f);
-                        mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
-                    }
-                    break;
-                case MIDDLE:
-                case SPRING_LOADED:
-                    if (animated) {
-                        mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.49f : 0.46f);
-                        mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.49f : 0.46f);
-                        mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
-                    }
-                    break;
-                case BOTTOM_HIDDEN:
-                case BOTTOM_VISIBLE:
-                    // all apps
-                    if (animated) {
-                        mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.65f : 0.65f);
-                        mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.65f : 0.65f);
-                        mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
-                    }
-                    break;
+            final boolean enableWallpaperEffects = isHardwareAccelerated();
+            if (enableWallpaperEffects) {
+                switch (mShrinkState) {
+                    // animating out
+                    case TOP:
+                        // customize
+                        if (animated) {
+                            mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.65f : 0.62f);
+                            mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.65f : 0.62f);
+                            mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
+                        }
+                        break;
+                    case MIDDLE:
+                    case SPRING_LOADED:
+                        if (animated) {
+                            mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.49f : 0.46f);
+                            mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.49f : 0.46f);
+                            mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
+                        }
+                        break;
+                    case BOTTOM_HIDDEN:
+                    case BOTTOM_VISIBLE:
+                        // all apps
+                        if (animated) {
+                            mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.65f : 0.65f);
+                            mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.65f : 0.65f);
+                            mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
+                        }
+                        break;
+                }
             }
             if (animated) {
                 ValueAnimator animWithInterpolator =
                     ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
                 animWithInterpolator.setInterpolator(mZoomInInterpolator);
 
-                final float oldHorizontalWallpaperOffset = getHorizontalWallpaperOffset();
-                final float oldVerticalWallpaperOffset = getVerticalWallpaperOffset();
-                final float newHorizontalWallpaperOffset = wallpaperOffsetForCurrentScroll();
-                final float newVerticalWallpaperOffset = 0.5f;
-                animWithInterpolator.addUpdateListener(new AnimatorUpdateListener() {
-                    public void onAnimationUpdate(ValueAnimator animation) {
+                final float oldHorizontalWallpaperOffset = enableWallpaperEffects ?
+                        getHorizontalWallpaperOffset() : 0;
+                final float oldVerticalWallpaperOffset = enableWallpaperEffects ?
+                        getVerticalWallpaperOffset() : 0;
+                final float newHorizontalWallpaperOffset = enableWallpaperEffects ?
+                        wallpaperOffsetForCurrentScroll() : 0;
+                final float newVerticalWallpaperOffset = enableWallpaperEffects ? 0.5f : 0;
+                animWithInterpolator.addUpdateListener(new LauncherAnimatorUpdateListener() {
+                    public void onAnimationUpdate(float a, float b) {
+                        if (b == 0f) {
+                            // an optimization, but not required
+                            return;
+                        }
                         fastInvalidate();
-                        final float b = (Float) animation.getAnimatedValue();
-                        final float a = 1f - b;
-                        setHorizontalWallpaperOffset(
-                                a * oldHorizontalWallpaperOffset + b * newHorizontalWallpaperOffset);
-                        setVerticalWallpaperOffset(
-                                a * oldVerticalWallpaperOffset + b * newVerticalWallpaperOffset);
+                        if (enableWallpaperEffects) {
+                            setHorizontalWallpaperOffset(a * oldHorizontalWallpaperOffset
+                                    + b * newHorizontalWallpaperOffset);
+                            setVerticalWallpaperOffset(a * oldVerticalWallpaperOffset
+                                    + b * newVerticalWallpaperOffset);
+                        }
                         for (int i = 0; i < screenCount; i++) {
                             final CellLayout cl = (CellLayout) getChildAt(i);
                             cl.fastInvalidate();
@@ -1875,11 +2084,13 @@
                 ValueAnimator rotationAnim =
                     ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
                 rotationAnim.setInterpolator(new DecelerateInterpolator(2.0f));
-                rotationAnim.addUpdateListener(new AnimatorUpdateListener() {
-                    public void onAnimationUpdate(ValueAnimator animation) {
+                rotationAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+                    public void onAnimationUpdate(float a, float b) {
                         // don't invalidate workspace because we did it above
-                        final float b = (Float) animation.getAnimatedValue();
-                        final float a = 1f - b;
+                        if (b == 0f) {
+                            // an optimization, but not required
+                            return;
+                        }
                         for (int i = 0; i < screenCount; i++) {
                             final CellLayout cl = (CellLayout) getChildAt(i);
                             cl.setFastRotationY(a * oldRotationYs[i] + b * newRotationYs[i]);
@@ -1893,9 +2104,11 @@
                 mAnimator.addListener(mUnshrinkAnimationListener);
                 mAnimator.start();
             } else {
-                setHorizontalWallpaperOffset(wallpaperOffsetForCurrentScroll());
-                setVerticalWallpaperOffset(0.5f);
-                updateWallpaperOffsetImmediately();
+                if (enableWallpaperEffects) {
+                    setHorizontalWallpaperOffset(wallpaperOffsetForCurrentScroll());
+                    setVerticalWallpaperOffset(0.5f);
+                    updateWallpaperOffsetImmediately();
+                }
             }
         }
 
@@ -1916,7 +2129,8 @@
         v.getDrawingRect(clipRect);
 
         // For a TextView, adjust the clip rect so that we don't include the text label
-        if (v instanceof BubbleTextView) {
+        if (v instanceof FolderIcon) {
+        } else if (v instanceof BubbleTextView) {
             final BubbleTextView tv = (BubbleTextView) v;
             clipRect.bottom = tv.getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V +
                     tv.getLayout().getLineTop(0);
@@ -2047,12 +2261,24 @@
 
         final int bmpWidth = b.getWidth();
         final int bmpHeight = b.getHeight();
+
         child.getLocationOnScreen(mTempXY);
         final int screenX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
         final int screenY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
+
+        Rect dragRect = null;
+        if ((child instanceof BubbleTextView) && !(child instanceof FolderIcon)) {
+            int iconSize = getResources().getDimensionPixelSize(R.dimen.app_icon_size);
+            int top = child.getPaddingTop();
+            int left = (bmpWidth - iconSize) / 2;
+            int right = left + iconSize;
+            int bottom = top + iconSize;
+            dragRect = new Rect(left, top, right, bottom);
+        }
+
         mLauncher.lockScreenOrientation();
-        mDragController.startDrag(b, screenX, screenY, 0, 0, bmpWidth, bmpHeight, this,
-                child.getTag(), DragController.DRAG_ACTION_MOVE, null);
+        mDragController.startDrag(b, screenX, screenY, this, child.getTag(),
+                DragController.DRAG_ACTION_MOVE, dragRect);
         b.recycle();
     }
 
@@ -2074,15 +2300,15 @@
         final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
 
         // Based on the position of the drag view, find the top left of the original view
-        int viewX = dragViewX + (dragView.getWidth() - child.getWidth()) / 2;
-        int viewY = dragViewY + (dragView.getHeight() - child.getHeight()) / 2;
-        viewX += getResources().getInteger(R.integer.config_dragViewOffsetX);
-        viewY += getResources().getInteger(R.integer.config_dragViewOffsetY);
+        int viewX = dragViewX + (dragView.getWidth() - child.getMeasuredWidth()) / 2;
+        int viewY = dragViewY + (dragView.getHeight() - child.getMeasuredHeight()) / 2;
+
+        CellLayout layout = (CellLayout) parent;
 
         // Set its old pos (in the new parent's coordinates); it will be animated
         // in animateViewIntoPosition after the next layout pass
-        lp.oldX = viewX - (parent.getLeft() - mScrollX);
-        lp.oldY = viewY - (parent.getTop() - mScrollY);
+        lp.oldX = viewX - (layout.getLeft() + layout.getLeftPadding() - mScrollX);
+        lp.oldY = viewY - (layout.getTop() + layout.getTopPadding() - mScrollY);
     }
 
     /*
@@ -2094,8 +2320,8 @@
         final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
 
         // Convert the animation params to be relative to the Workspace, not the CellLayout
-        final int fromX = lp.oldX + parent.getLeft();
-        final int fromY = lp.oldY + parent.getTop();
+        final int fromX = lp.oldX + parent.getLeft() + parent.getLeftPadding();
+        final int fromY = lp.oldY + parent.getTop() + parent.getTopPadding();
 
         final int dx = lp.x - lp.oldX;
         final int dy = lp.y - lp.oldY;
@@ -2178,19 +2404,80 @@
         return true;
     }
 
+    boolean willCreateUserFolder(ItemInfo info, CellLayout target, int originX, int originY) {
+        mTargetCell = findNearestArea(originX, originY,
+                1, 1, target,
+                mTargetCell);
+
+        View v = target.getChildAt(mTargetCell[0], mTargetCell[1]);
+        boolean hasntMoved = mDragInfo != null && (mDragInfo.cellX == mTargetCell[0] &&
+                mDragInfo.cellY == mTargetCell[1]);
+
+        if (v == null || hasntMoved) return false;
+
+        boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);
+        boolean willBecomeShortcut =
+            (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
+            info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT);
+
+        return (aboveShortcut && willBecomeShortcut);
+    }
+
+    boolean createUserFolderIfNecessary(View newView, CellLayout target, int originX,
+            int originY, boolean external) {
+        int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
+        int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
+
+        // First we find the cell nearest to point at which the item is dropped, without
+        // any consideration to whether there is an item there.
+        mTargetCell = findNearestArea(originX, originY,
+                spanX, spanY, target,
+                mTargetCell);
+
+        View v = target.getChildAt(mTargetCell[0], mTargetCell[1]);
+        boolean hasntMoved = mDragInfo != null && (mDragInfo.cellX == mTargetCell[0] &&
+                mDragInfo.cellY == mTargetCell[1]);
+
+        if (v == null || hasntMoved) return false;
+
+        final int screen = (mTargetCell == null) ?
+                mDragInfo.screen : indexOfChild(target);
+
+        boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);
+        boolean willBecomeShortcut = (newView.getTag() instanceof ShortcutInfo);
+
+        if (aboveShortcut && willBecomeShortcut) {
+            ShortcutInfo sourceInfo = (ShortcutInfo) newView.getTag();
+            ShortcutInfo destInfo = (ShortcutInfo) v.getTag();
+            // if the drag started here, we need to remove it from the workspace
+            if (!external) {
+                int fromScreen = mDragInfo.screen;
+                CellLayout sourceLayout = (CellLayout) getChildAt(fromScreen);
+                sourceLayout.removeView(newView);
+            }
+
+            target.removeView(v);
+            FolderIcon fi = mLauncher.addFolder(screen, mTargetCell[0], mTargetCell[1]);
+            destInfo.cellX = -1;
+            destInfo.cellY = -1;
+            sourceInfo.cellX = -1;
+            sourceInfo.cellY = -1;
+            fi.addItem(destInfo);
+            fi.addItem(sourceInfo);
+            return true;
+        }
+        return false;
+    }
+
     public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
             DragView dragView, Object dragInfo) {
 
-        int originX = x - xOffset;
-        int originY = y - yOffset;
+        mDragViewVisualCenter = getDragViewVisualCenter(x, y, xOffset, yOffset, dragView,
+                mDragViewVisualCenter);
 
-        if (mIsSmall || mIsInUnshrinkAnimation) {
-            // get originX and originY in the local coordinate system of the screen
-            mTempOriginXY[0] = originX;
-            mTempOriginXY[1] = originY;
-            mapPointFromSelfToChild(mDragTargetLayout, mTempOriginXY);
-            originX = (int)mTempOriginXY[0];
-            originY = (int)mTempOriginXY[1];
+        // We want the point to be mapped to the dragTarget.
+        if (mDragTargetLayout != null) {
+            mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
         }
 
         // When you are in customization mode and drag to a particular screen, make that the
@@ -2203,20 +2490,25 @@
         }
 
         if (source != this) {
-            if (!mIsSmall || mWasSpringLoadedOnDragExit) {
-                onDropExternal(originX, originY, dragInfo, mDragTargetLayout, false);
-            } else {
-                // if we drag and drop to small screens, don't pass the touch x/y coords (when we
-                // enable spring-loaded adding, however, we do want to pass the touch x/y coords)
-                onDropExternal(-1, -1, dragInfo, mDragTargetLayout, false);
+            final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
+                    (int) mDragViewVisualCenter[1] };
+            if (LauncherApplication.isScreenLarge() && (mIsSmall || mIsInUnshrinkAnimation)
+                    && !mLauncher.isAllAppsVisible()) {
+                // When the workspace is shrunk and the drop comes from customize, don't actually
+                // add the item to the screen -- customize will do this itself
+                ((ItemInfo) dragInfo).dropPos = touchXY;
+                return;
             }
+            onDropExternal(touchXY, dragInfo, mDragTargetLayout, false, dragView);
         } else if (mDragInfo != null) {
             final View cell = mDragInfo.cell;
             CellLayout dropTargetLayout = mDragTargetLayout;
+            boolean dropInscrollArea = false;
 
             // Handle the case where the user drops when in the scroll area.
             // This is treated as a drop on the adjacent page.
             if (dropTargetLayout == null && mInScrollArea) {
+                dropInscrollArea = true;
                 if (mPendingScrollDirection == DragController.SCROLL_LEFT) {
                     dropTargetLayout = (CellLayout) getChildAt(mCurrentPage - 1);
                 } else if (mPendingScrollDirection == DragController.SCROLL_RIGHT) {
@@ -2226,13 +2518,22 @@
 
             if (dropTargetLayout != null) {
                 // Move internally
-                mTargetCell = findNearestVacantArea(originX, originY,
-                        mDragInfo.spanX, mDragInfo.spanY, cell, dropTargetLayout,
-                        mTargetCell);
-
                 final int screen = (mTargetCell == null) ?
                         mDragInfo.screen : indexOfChild(dropTargetLayout);
 
+                // If the item being dropped is a shortcut and the nearest drop cell also contains
+                // a shortcut, then create a folder with the two shortcuts.
+                if (!dropInscrollArea && createUserFolderIfNecessary(cell, dropTargetLayout,
+                        (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], false)) {
+                    return;
+                }
+
+                // Aside from the special case where we're dropping a shortcut onto a shortcut,
+                // we need to find the nearest cell location that is vacant
+                mTargetCell = findNearestVacantArea((int) mDragViewVisualCenter[0],
+                        (int) mDragViewVisualCenter[1], mDragInfo.spanX, mDragInfo.spanY, cell,
+                        dropTargetLayout, mTargetCell);
+
                 if (screen != mCurrentPage) {
                     snapToPage(screen);
                 }
@@ -2254,6 +2555,34 @@
                     cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
                             mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
 
+                    if (cell instanceof LauncherAppWidgetHostView) {
+                        final CellLayout cellLayout = dropTargetLayout;
+                        // We post this call so that the widget has a chance to be placed
+                        // in its final location
+
+                        final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
+                        AppWidgetProviderInfo pinfo = hostView.getAppWidgetInfo();
+                        if (pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
+                            final Runnable resizeRunnable = new Runnable() {
+                                public void run() {
+                                    DragLayer dragLayer = (DragLayer)
+                                            mLauncher.findViewById(R.id.drag_layer);
+                                    dragLayer.addResizeFrame(info, hostView,
+                                            cellLayout);
+                                }
+                            };
+                            post(new Runnable() {
+                                public void run() {
+                                    if (!isPageMoving()) {
+                                        resizeRunnable.run();
+                                    } else {
+                                        mDelayedResizeRunnable = resizeRunnable;
+                                    }
+                                }
+                            });
+                        }
+                    }
+
                     LauncherModel.moveItemInDatabase(mLauncher, info,
                             LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
                             lp.cellX, lp.cellY);
@@ -2262,14 +2591,30 @@
 
             final CellLayout parent = (CellLayout) cell.getParent().getParent();
 
+            int loc[] = new int[2];
+            getViewLocationRelativeToSelf(dragView, loc);
+
             // Prepare it to be animated into its new position
             // This must be called after the view has been re-parented
-            setPositionForDropAnimation(dragView, originX, originY, parent, cell);
+            setPositionForDropAnimation(dragView, loc[0], loc[1], parent, cell);
             boolean animateDrop = !mWasSpringLoadedOnDragExit;
             parent.onDropChild(cell, animateDrop);
         }
     }
 
+    private void getViewLocationRelativeToSelf(View v, int[] location) {
+        getLocationOnScreen(location);
+        int x = location[0];
+        int y = location[1];
+
+        v.getLocationOnScreen(location);
+        int vX = location[0];
+        int vY = location[1];
+
+        location[0] = vX - x;
+        location[1] = vY - y;
+    }
+
     public void onDragEnter(DragSource source, int x, int y, int xOffset,
             int yOffset, DragView dragView, Object dragInfo) {
         mDragTargetLayout = null; // Reset the drag state
@@ -2292,7 +2637,7 @@
         // would land in a cell occupied by a DragTarget (e.g. a Folder),
         // then drag events should be handled by that child.
 
-        ItemInfo item = (ItemInfo)dragInfo;
+        ItemInfo item = (ItemInfo) dragInfo;
         CellLayout currentLayout = getCurrentDropLayout();
 
         int dragPointX, dragPointY;
@@ -2418,7 +2763,7 @@
                 if (isShortcut) {
                     final Intent intent = data.getItemAt(index).getIntent();
                     Object info = model.infoFromShortcutIntent(mContext, intent, data.getIcon());
-                    onDropExternal(x, y, info, layout, false);
+                    onDropExternal(new int[] { x, y }, info, layout, false);
                 } else {
                     if (widgets.size() == 1) {
                         // If there is only one item, then go ahead and add and configure
@@ -2498,11 +2843,11 @@
        xy[1] -= (mScrollY - v.getTop());
    }
 
-    static private float squaredDistance(float[] point1, float[] point2) {
+   static private float squaredDistance(float[] point1, float[] point2) {
         float distanceX = point1[0] - point2[0];
         float distanceY = point2[1] - point2[1];
         return distanceX * distanceX + distanceY * distanceY;
-    }
+   }
 
     /*
      *
@@ -2600,32 +2945,79 @@
         return bestMatchingScreen;
     }
 
+    // This is used to compute the visual center of the dragView. This point is then
+    // used to visualize drop locations and determine where to drop an item. The idea is that
+    // the visual center represents the user's interpretation of where the item is, and hence
+    // is the appropriate point to use when determining drop location.
+    private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset,
+            DragView dragView, float[] recycle) {
+        float res[];
+        if (recycle == null) {
+            res = new float[2];
+        } else {
+            res = recycle;
+        }
+
+        // First off, the drag view has been shifted in a way that is not represented in the
+        // x and y values or the x/yOffsets. Here we account for that shift.
+        x += getResources().getDimensionPixelSize(R.dimen.dragViewOffsetX);
+        y += getResources().getDimensionPixelSize(R.dimen.dragViewOffsetY);
+
+        // These represent the visual top and left of drag view if a dragRect was provided.
+        // If a dragRect was not provided, then they correspond to the actual view left and
+        // top, as the dragRect is in that case taken to be the entire dragView.
+        // R.dimen.dragViewOffsetY.
+        int left = x - xOffset;
+        int top = y - yOffset;
+
+        // In order to find the visual center, we shift by half the dragRect
+        res[0] = left + dragView.getDragRegion().width() / 2;
+        res[1] = top + dragView.getDragRegion().height() / 2;
+
+        return res;
+    }
+
     public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
             DragView dragView, Object dragInfo) {
         // When touch is inside the scroll area, skip dragOver actions for the current screen
         if (!mInScrollArea) {
             CellLayout layout;
-            int originX = x - xOffset;
-            int originY = y - yOffset;
+            int left = x - xOffset;
+            int top = y - yOffset;
+
+            mDragViewVisualCenter = getDragViewVisualCenter(x, y, xOffset, yOffset, dragView,
+                    mDragViewVisualCenter);
+
             boolean shrunken = mIsSmall || mIsInUnshrinkAnimation;
             if (shrunken) {
                 mLastDragView = dragView;
-                mLastDragOriginX = originX;
-                mLastDragOriginY = originY;
+                mLastDragOriginX = left;
+                mLastDragOriginY = top;
                 mLastDragXOffset = xOffset;
                 mLastDragYOffset = yOffset;
-                layout = findMatchingPageForDragOver(dragView, originX, originY, xOffset, yOffset);
+                layout = findMatchingPageForDragOver(dragView, left, top, xOffset, yOffset);
 
-                if (layout != mDragTargetLayout) {
+                if (layout != null && layout != mDragTargetLayout) {
                     if (mDragTargetLayout != null) {
                         mDragTargetLayout.setIsDragOverlapping(false);
                         mSpringLoadedDragController.onDragExit();
                     }
                     mDragTargetLayout = layout;
-                    if (mDragTargetLayout != null && mDragTargetLayout.getAcceptsDrops()) {
-                        mDragTargetLayout.setIsDragOverlapping(true);
-                        mSpringLoadedDragController.onDragEnter(
-                                mDragTargetLayout, mShrinkState == ShrinkState.SPRING_LOADED);
+
+                    // Workaround the fact that we don't actually want spring-loaded mode in phone
+                    // UI yet.
+                    if (LauncherApplication.isScreenLarge()) {
+                        // In spring-loaded mode, we still want the user to be able to hover over a
+                        // full screen (which is traditionally set to not accept drops) if they want
+                        // to get to pages beyond the screen that is full.
+                        boolean allowDragOver = (mDragTargetLayout != null) &&
+                                (mDragTargetLayout.getAcceptsDrops() ||
+                                        (mShrinkState == ShrinkState.SPRING_LOADED));
+                        if (allowDragOver) {
+                            mDragTargetLayout.setIsDragOverlapping(true);
+                            mSpringLoadedDragController.onDragEnter(
+                                    mDragTargetLayout, mShrinkState == ShrinkState.SPRING_LOADED);
+                        }
                     }
                 }
             } else {
@@ -2654,37 +3046,23 @@
                     }
                 }
 
-                if (source instanceof AllAppsPagedView) {
-                    // This is a hack to fix the point used to determine which cell an icon from
-                    // the all apps screen is over
-                    if (item != null && item.spanX == 1 && layout != null) {
-                        int dragRegionLeft = (dragView.getWidth() - layout.getCellWidth()) / 2;
-
-                        originX += dragRegionLeft - dragView.getDragRegionLeft();
-                        if (dragView.getDragRegionWidth() != layout.getCellWidth()) {
-                            dragView.setDragRegion(dragView.getDragRegionLeft(),
-                                    dragView.getDragRegionTop(),
-                                    layout.getCellWidth(),
-                                    dragView.getDragRegionHeight());
-                        }
-                    }
-                } else if (source == this) {
-                    // When dragging from the workspace, the drag view is slightly bigger than
-                    // the original view, and offset vertically. Adjust to account for this.
-                    final View origView = mDragInfo.cell;
-                    originX += (dragView.getMeasuredWidth() - origView.getWidth()) / 2;
-                    originY += (dragView.getMeasuredHeight() - origView.getHeight()) / 2
-                            + dragView.getOffsetY();
-                }
-
                 if (mDragTargetLayout != null) {
                     final View child = (mDragInfo == null) ? null : mDragInfo.cell;
-                    float[] localOrigin = { originX, originY };
-                    mapPointFromSelfToChild(mDragTargetLayout, localOrigin, null);
-                    mSpringLoadedDropX = (int) localOrigin[0];
-                    mSpringLoadedDropY = (int) localOrigin[1];
-                    mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
-                            (int) localOrigin[0], (int) localOrigin[1], item.spanX, item.spanY);
+                    // We want the point to be mapped to the dragTarget.
+                    mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
+                    ItemInfo info = (ItemInfo) dragInfo;
+
+                    if (!willCreateUserFolder(info, mDragTargetLayout,
+                            (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1])) {
+                        mIsDraggingOverIcon = false;
+                        mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
+                                (int) mDragViewVisualCenter[0],
+                                (int) mDragViewVisualCenter[1],
+                                item.spanX, item.spanY);
+                    } else if (!mIsDraggingOverIcon) {
+                        mIsDraggingOverIcon = true;
+                        mDragTargetLayout.clearDragOutlines();
+                    }
                 }
             }
         }
@@ -2723,13 +3101,18 @@
      */
     public boolean addExternalItemToScreen(ItemInfo dragInfo, CellLayout layout) {
         if (layout.findCellForSpan(mTempEstimate, dragInfo.spanX, dragInfo.spanY)) {
-            onDropExternal(-1, -1, (ItemInfo) dragInfo, (CellLayout) layout, false);
+            onDropExternal(dragInfo.dropPos, (ItemInfo) dragInfo, (CellLayout) layout, false);
             return true;
         }
         mLauncher.showOutOfSpaceMessage();
         return false;
     }
 
+    private void onDropExternal(int[] touchXY, Object dragInfo,
+            CellLayout cellLayout, boolean insertAtFirst) {
+        onDropExternal(touchXY, dragInfo, cellLayout, insertAtFirst, null);
+    }
+
     /**
      * Drop an item that didn't originate on one of the workspace screens.
      * It may have come from Launcher (e.g. from all apps or customize), or it may have
@@ -2738,24 +3121,17 @@
      * NOTE: This can also be called when we are outside of a drag event, when we want
      * to add an item to one of the workspace screens.
      */
-    private void onDropExternal(int x, int y, Object dragInfo,
-            CellLayout cellLayout, boolean insertAtFirst) {
+    private void onDropExternal(int[] touchXY, Object dragInfo,
+            CellLayout cellLayout, boolean insertAtFirst, DragView dragView) {
         int screen = indexOfChild(cellLayout);
         if (dragInfo instanceof PendingAddItemInfo) {
             PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
             // When dragging and dropping from customization tray, we deal with creating
             // widgets/shortcuts/folders in a slightly different way
-            // Only set touchXY if you are supporting spring loaded adding of items
-            int[] touchXY = new int[2];
-            touchXY[0] = mSpringLoadedDropX;
-            touchXY[1] = mSpringLoadedDropY;
             switch (info.itemType) {
                 case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
                     mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) info, screen, touchXY);
                     break;
-                case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
-                    mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
-                    break;
                 case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                     mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
                     break;
@@ -2778,23 +3154,26 @@
                 view = mLauncher.createShortcut(R.layout.application, cellLayout,
                         (ShortcutInfo) info);
                 break;
-            case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
+            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                 view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
-                        cellLayout, (UserFolderInfo) info, mIconCache);
+                        cellLayout, (FolderInfo) info, mIconCache);
                 break;
             default:
                 throw new IllegalStateException("Unknown item type: " + info.itemType);
             }
 
-            mTargetCell = new int[2];
-            if (x != -1 && y != -1) {
-                // when dragging and dropping, just find the closest free spot
+            // If the item being dropped is a shortcut and the nearest drop cell also contains
+            // a shortcut, then create a folder with the two shortcuts.
+            if (touchXY != null && createUserFolderIfNecessary(view, cellLayout, touchXY[0],
+                  touchXY[1], true)) {
+                return;
+            }
 
-                // When we get a drop in Spring Loaded mode, at this point we've already called
-                // onDragExit, which starts us shrinking again and screws up the transforms we
-                // need to get the right value. Instead, as a temporary solution, we've saved the
-                // proper point, mSpringLoadedDropX/Y, from the last onDragOver
-                cellLayout.findNearestVacantArea(mSpringLoadedDropX, mSpringLoadedDropY, 1, 1, mTargetCell);
+            mTargetCell = new int[2];
+            if (touchXY != null) {
+                // when dragging and dropping, just find the closest free spot
+                mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, null, cellLayout,
+                        mTargetCell);
             } else {
                 cellLayout.findCellForSpan(mTargetCell, 1, 1);
             }
@@ -2804,6 +3183,15 @@
             cellLayout.onDropChild(view, animateDrop);
             cellLayout.animateDrop();
             CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
+            cellLayout.getChildrenLayout().measureChild(view);
+
+            if (dragView != null) {
+                // we have the visual center of the drag view, we need to find the actual
+                // left and top of the dragView.
+                int loc[] = new int[2];
+                getViewLocationRelativeToSelf(dragView, loc);
+                setPositionForDropAnimation(dragView, loc[0], loc[1], cellLayout, view);
+            }
 
             LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
                     LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
@@ -2815,11 +3203,8 @@
      * Return the current {@link CellLayout}, correctly picking the destination
      * screen while a scroll is in progress.
      */
-    private CellLayout getCurrentDropLayout() {
-        // if we're currently small, use findMatchingPageForDragOver instead
-        if (mIsSmall) return null;
-        int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
-        return (CellLayout) getChildAt(index);
+    public CellLayout getCurrentDropLayout() {
+        return (CellLayout) getChildAt(mNextPage == INVALID_PAGE ? mCurrentPage : mNextPage);
     }
 
     /**
@@ -2834,16 +3219,24 @@
 
     /**
      * Calculate the nearest cell where the given object would be dropped.
+     *
+     * pixelX and pixelY should be in the coordinate system of layout
      */
     private int[] findNearestVacantArea(int pixelX, int pixelY,
             int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
-
-        int localPixelX = pixelX - (layout.getLeft() - mScrollX);
-        int localPixelY = pixelY - (layout.getTop() - mScrollY);
-
-        // Find the best target drop location
         return layout.findNearestVacantArea(
-                localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
+                pixelX, pixelY, spanX, spanY, ignoreView, recycle);
+    }
+
+    /**
+     * Calculate the nearest cell where the given object would be dropped.
+     *
+     * pixelX and pixelY should be in the coordinate system of layout
+     */
+    private int[] findNearestArea(int pixelX, int pixelY,
+            int spanX, int spanY, CellLayout layout, int[] recycle) {
+        return layout.findNearestArea(
+                pixelX, pixelY, spanX, spanY, recycle);
     }
 
     void setLauncher(Launcher launcher) {
@@ -2864,7 +3257,7 @@
     /**
      * Called at the end of a drag which originated on the workspace.
      */
-    public void onDropCompleted(View target, boolean success) {
+    public void onDropCompleted(View target, Object dragInfo, boolean success) {
         if (success) {
             if (target != this && mDragInfo != null) {
                 final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
@@ -2931,6 +3324,10 @@
                     mDragTargetLayout.onDragExit();
                     mDragTargetLayout = null;
                 }
+                // In portrait, need to redraw the edge glow when entering the scroll area
+                if (getHeight() > getWidth()) {
+                    invalidate();
+                }
             }
         }
     }
@@ -2941,6 +3338,12 @@
             ((CellLayout) getChildAt(i)).setIsDragOverlapping(false);
         }
         mSpringLoadedDragController.onDragExit();
+
+        // In portrait, workspace is responsible for drawing the edge glow on adjacent pages,
+        // so we need to redraw the workspace when this may have changed.
+        if (getHeight() > getWidth()) {
+            invalidate();
+        }
     }
 
     @Override
@@ -2986,6 +3389,21 @@
         return null;
     }
 
+    void clearDropTargets() {
+        final int screenCount = getChildCount();
+
+        for (int i = 0; i < screenCount; i++) {
+            final CellLayout layoutParent = (CellLayout) getChildAt(i);
+            final ViewGroup layout = layoutParent.getChildrenLayout();
+            int childCount = layout.getChildCount();
+            for (int j = 0; j < childCount; j++) {
+                View v = layout.getChildAt(j);
+                if (v instanceof DropTarget) {
+                    mDragController.removeDropTarget((DropTarget) v);
+                }
+            }
+        }
+    }
 
     void removeItems(final ArrayList<ApplicationInfo> apps) {
         final int screenCount = getChildCount();
@@ -3026,8 +3444,8 @@
                                     }
                                 }
                             }
-                        } else if (tag instanceof UserFolderInfo) {
-                            final UserFolderInfo info = (UserFolderInfo) tag;
+                        } else if (tag instanceof FolderInfo) {
+                            final FolderInfo info = (FolderInfo) tag;
                             final ArrayList<ShortcutInfo> contents = info.contents;
                             final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
                             final int contentsCount = contents.size();
@@ -3055,20 +3473,6 @@
                                 if (folder != null)
                                     folder.notifyDataSetChanged();
                             }
-                        } else if (tag instanceof LiveFolderInfo) {
-                            final LiveFolderInfo info = (LiveFolderInfo) tag;
-                            final Uri uri = info.uri;
-                            final ProviderInfo providerInfo = manager.resolveContentProvider(
-                                    uri.getAuthority(), 0);
-
-                            if (providerInfo != null) {
-                                for (String packageName: packageNames) {
-                                    if (packageName.equals(providerInfo.packageName)) {
-                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
-                                        childrenToRemove.add(view);
-                                    }
-                                }
-                            }
                         } else if (tag instanceof LauncherAppWidgetInfo) {
                             final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
                             final AppWidgetProviderInfo provider =
diff --git a/src/com/android/launcher2/allapps.rs b/src/com/android/launcher2/allapps.rs
index bebc04d..4ea1aee 100644
--- a/src/com/android/launcher2/allapps.rs
+++ b/src/com/android/launcher2/allapps.rs
@@ -298,7 +298,7 @@
                     vpConstants->ImgSize.y = rsAllocationGetDimY(gSelectedIconTexture);
                     vpConstants->Position.y = y - (rsAllocationGetDimY(gSelectedIconTexture)
                                                 - rsAllocationGetDimY(gIcons[iconNum])) * 0.5f;
-                    rsAllocationMarkDirty(g_VPConstAlloc);
+                    rsgAllocationSyncAll(g_VPConstAlloc);
                     rsgDrawMesh(gSMCell);
                 }
 
@@ -306,7 +306,7 @@
                 vpConstants->ImgSize.x = rsAllocationGetDimX(gIcons[iconNum]);
                 vpConstants->ImgSize.y = rsAllocationGetDimY(gIcons[iconNum]);
                 vpConstants->Position.y = y - 0.2f;
-                rsAllocationMarkDirty(g_VPConstAlloc);
+                rsgAllocationSyncAll(g_VPConstAlloc);
                 rsgBindTexture(gPFTexMip, 0, gIcons[iconNum]);
                 rsgDrawMesh(gSMCell);
 
@@ -314,7 +314,7 @@
                 vpConstants->ImgSize.x = rsAllocationGetDimX(gLabels[iconNum]);
                 vpConstants->ImgSize.y = rsAllocationGetDimY(gLabels[iconNum]);
                 vpConstants->Position.y = y - 64.f - 0.2f;
-                rsAllocationMarkDirty(g_VPConstAlloc);
+                rsgAllocationSyncAll(g_VPConstAlloc);
                 rsgBindTexture(gPFTexMipAlpha, 0, gLabels[iconNum]);
                 rsgDrawMesh(gSMCell);
             }