Merge branch 'master' into honeycomb-release
diff --git a/res/drawable-hdpi/default_widget_preview.9.png b/res/drawable-hdpi/default_widget_preview.9.png
index 6596f07..ecc02de 100644
--- a/res/drawable-hdpi/default_widget_preview.9.png
+++ b/res/drawable-hdpi/default_widget_preview.9.png
Binary files differ
diff --git a/res/drawable-hdpi/focused_application_background.9.png b/res/drawable-hdpi/focused_application_background.9.png
index 1b11492..7bf37ef 100644
--- a/res/drawable-hdpi/focused_application_background.9.png
+++ b/res/drawable-hdpi/focused_application_background.9.png
Binary files differ
diff --git a/res/drawable-hdpi/gardening_crosshairs.png b/res/drawable-hdpi/gardening_crosshairs.png
new file mode 100644
index 0000000..3c0484c
--- /dev/null
+++ b/res/drawable-hdpi/gardening_crosshairs.png
Binary files differ
diff --git a/res/drawable-hdpi/home_screen_bg.9.png b/res/drawable-hdpi/home_screen_bg.9.png
new file mode 100644
index 0000000..413e492
--- /dev/null
+++ b/res/drawable-hdpi/home_screen_bg.9.png
Binary files differ
diff --git a/res/drawable-hdpi/home_screen_bg_hover.9.png b/res/drawable-hdpi/home_screen_bg_hover.9.png
new file mode 100644
index 0000000..73696bf
--- /dev/null
+++ b/res/drawable-hdpi/home_screen_bg_hover.9.png
Binary files differ
diff --git a/res/drawable-hdpi/mini_home_screen_bg.9.png b/res/drawable-hdpi/mini_home_screen_bg.9.png
new file mode 100644
index 0000000..4602609
--- /dev/null
+++ b/res/drawable-hdpi/mini_home_screen_bg.9.png
Binary files differ
diff --git a/res/drawable-hdpi/mini_home_screen_bg_accepts_drops.9.png b/res/drawable-hdpi/mini_home_screen_bg_accepts_drops.9.png
new file mode 100644
index 0000000..b1aa98b
--- /dev/null
+++ b/res/drawable-hdpi/mini_home_screen_bg_accepts_drops.9.png
Binary files differ
diff --git a/res/drawable-hdpi/mini_home_screen_bg_hover.9.png b/res/drawable-hdpi/mini_home_screen_bg_hover.9.png
new file mode 100644
index 0000000..a30e992
--- /dev/null
+++ b/res/drawable-hdpi/mini_home_screen_bg_hover.9.png
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_left.9.png b/res/drawable-hdpi/page_hover_left.9.png
new file mode 100644
index 0000000..1bf1565
--- /dev/null
+++ b/res/drawable-hdpi/page_hover_left.9.png
Binary files differ
diff --git a/res/drawable-hdpi/page_hover_right.9.png b/res/drawable-hdpi/page_hover_right.9.png
new file mode 100644
index 0000000..7995f69
--- /dev/null
+++ b/res/drawable-hdpi/page_hover_right.9.png
Binary files differ
diff --git a/res/drawable-hdpi/pressed_application_background.9.png b/res/drawable-hdpi/pressed_application_background.9.png
index ece27fd..291af02 100644
--- a/res/drawable-hdpi/pressed_application_background.9.png
+++ b/res/drawable-hdpi/pressed_application_background.9.png
Binary files differ
diff --git a/res/drawable-hdpi/rounded_rect_green.9.png b/res/drawable-hdpi/rounded_rect_green.9.png
new file mode 100644
index 0000000..50268fb
--- /dev/null
+++ b/res/drawable-hdpi/rounded_rect_green.9.png
Binary files differ
diff --git a/res/drawable-hdpi/rounded_rect_red.9.png b/res/drawable-hdpi/rounded_rect_red.9.png
new file mode 100644
index 0000000..ef68d4d
--- /dev/null
+++ b/res/drawable-hdpi/rounded_rect_red.9.png
Binary files differ
diff --git a/res/drawable-hdpi/widget_divider.png b/res/drawable-hdpi/widget_divider.png
new file mode 100644
index 0000000..2f92d60
--- /dev/null
+++ b/res/drawable-hdpi/widget_divider.png
Binary files differ
diff --git a/res/drawable-mdpi/all_apps_button_focused.png b/res/drawable-mdpi/all_apps_button_focused.png
index a9d5a3f..dd77f80 100644
--- a/res/drawable-mdpi/all_apps_button_focused.png
+++ b/res/drawable-mdpi/all_apps_button_focused.png
Binary files differ
diff --git a/res/drawable-mdpi/all_apps_button_normal.png b/res/drawable-mdpi/all_apps_button_normal.png
index 227215b..2419f97 100644
--- a/res/drawable-mdpi/all_apps_button_normal.png
+++ b/res/drawable-mdpi/all_apps_button_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/all_apps_button_pressed.png b/res/drawable-mdpi/all_apps_button_pressed.png
index e243252..3e6c850 100644
--- a/res/drawable-mdpi/all_apps_button_pressed.png
+++ b/res/drawable-mdpi/all_apps_button_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/bg_appwidget_error.9.png b/res/drawable-mdpi/bg_appwidget_error.9.png
index 5077424..f222f94 100644
--- a/res/drawable-mdpi/bg_appwidget_error.9.png
+++ b/res/drawable-mdpi/bg_appwidget_error.9.png
Binary files differ
diff --git a/res/drawable-mdpi/box_launcher_bottom.9.png b/res/drawable-mdpi/box_launcher_bottom.9.png
index 1c99c50..e7dac0d 100644
--- a/res/drawable-mdpi/box_launcher_bottom.9.png
+++ b/res/drawable-mdpi/box_launcher_bottom.9.png
Binary files differ
diff --git a/res/drawable-mdpi/box_launcher_top_normal.9.png b/res/drawable-mdpi/box_launcher_top_normal.9.png
index 30b17b2..8adf2cf 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 033cd48..7a20c54 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 3ef394c..9e636f0 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/default_widget_preview.9.png b/res/drawable-mdpi/default_widget_preview.9.png
index 0d3af8b..5fedcc8 100644
--- a/res/drawable-mdpi/default_widget_preview.9.png
+++ b/res/drawable-mdpi/default_widget_preview.9.png
Binary files differ
diff --git a/res/drawable-mdpi/focused_application_background.9.png b/res/drawable-mdpi/focused_application_background.9.png
index b27d693..17ee6ea 100644
--- a/res/drawable-mdpi/focused_application_background.9.png
+++ b/res/drawable-mdpi/focused_application_background.9.png
Binary files differ
diff --git a/res/drawable/gardening_crosshairs.png b/res/drawable-mdpi/gardening_crosshairs.png
similarity index 100%
rename from res/drawable/gardening_crosshairs.png
rename to res/drawable-mdpi/gardening_crosshairs.png
Binary files differ
diff --git a/res/drawable-mdpi/home_button_focused.png b/res/drawable-mdpi/home_button_focused.png
index 701772b..4d62c1b 100644
--- a/res/drawable-mdpi/home_button_focused.png
+++ b/res/drawable-mdpi/home_button_focused.png
Binary files differ
diff --git a/res/drawable-mdpi/home_button_normal.png b/res/drawable-mdpi/home_button_normal.png
index cc7e3b0..37eccc0 100644
--- a/res/drawable-mdpi/home_button_normal.png
+++ b/res/drawable-mdpi/home_button_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/home_button_pressed.png b/res/drawable-mdpi/home_button_pressed.png
index ee8ddbe..4b77d6d 100644
--- a/res/drawable-mdpi/home_button_pressed.png
+++ b/res/drawable-mdpi/home_button_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/home_screen_bg.9.png b/res/drawable-mdpi/home_screen_bg.9.png
new file mode 100644
index 0000000..023e8da
--- /dev/null
+++ b/res/drawable-mdpi/home_screen_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/home_screen_bg_hover.9.png b/res/drawable-mdpi/home_screen_bg_hover.9.png
new file mode 100644
index 0000000..3443fd4
--- /dev/null
+++ b/res/drawable-mdpi/home_screen_bg_hover.9.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_bg_center.9.png b/res/drawable-mdpi/hotseat_bg_center.9.png
index a9a05ba..c846d54 100644
--- a/res/drawable-mdpi/hotseat_bg_center.9.png
+++ b/res/drawable-mdpi/hotseat_bg_center.9.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_bg_left.9.png b/res/drawable-mdpi/hotseat_bg_left.9.png
index 35dfead..92d583f 100644
--- a/res/drawable-mdpi/hotseat_bg_left.9.png
+++ b/res/drawable-mdpi/hotseat_bg_left.9.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_bg_right.9.png b/res/drawable-mdpi/hotseat_bg_right.9.png
index 9adfa31..5181b00 100644
--- a/res/drawable-mdpi/hotseat_bg_right.9.png
+++ b/res/drawable-mdpi/hotseat_bg_right.9.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_browser_focused.png b/res/drawable-mdpi/hotseat_browser_focused.png
index 5b85840..0ad0878 100644
--- a/res/drawable-mdpi/hotseat_browser_focused.png
+++ b/res/drawable-mdpi/hotseat_browser_focused.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_browser_normal.png b/res/drawable-mdpi/hotseat_browser_normal.png
index 4a4a6e3..52abe8c 100644
--- a/res/drawable-mdpi/hotseat_browser_normal.png
+++ b/res/drawable-mdpi/hotseat_browser_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_browser_pressed.png b/res/drawable-mdpi/hotseat_browser_pressed.png
index ed10c18..e1d35d1 100644
--- a/res/drawable-mdpi/hotseat_browser_pressed.png
+++ b/res/drawable-mdpi/hotseat_browser_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_phone_focused.png b/res/drawable-mdpi/hotseat_phone_focused.png
index 15ec1c6..3b2d361 100644
--- a/res/drawable-mdpi/hotseat_phone_focused.png
+++ b/res/drawable-mdpi/hotseat_phone_focused.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_phone_normal.png b/res/drawable-mdpi/hotseat_phone_normal.png
index 7f20428..750960b 100644
--- a/res/drawable-mdpi/hotseat_phone_normal.png
+++ b/res/drawable-mdpi/hotseat_phone_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_phone_pressed.png b/res/drawable-mdpi/hotseat_phone_pressed.png
index fcdf073..8ad9d5a 100644
--- a/res/drawable-mdpi/hotseat_phone_pressed.png
+++ b/res/drawable-mdpi/hotseat_phone_pressed.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_1_focus.png b/res/drawable-mdpi/ic_home_arrows_1_focus.png
index 01817a4..c0c2720 100644
--- a/res/drawable-mdpi/ic_home_arrows_1_focus.png
+++ b/res/drawable-mdpi/ic_home_arrows_1_focus.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_1_focus_right.png b/res/drawable-mdpi/ic_home_arrows_1_focus_right.png
index a37d179..89eb552 100644
--- a/res/drawable-mdpi/ic_home_arrows_1_focus_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_1_focus_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_1_normal.png b/res/drawable-mdpi/ic_home_arrows_1_normal.png
index 1393607..c3b6e1d 100644
--- a/res/drawable-mdpi/ic_home_arrows_1_normal.png
+++ b/res/drawable-mdpi/ic_home_arrows_1_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_1_normal_right.png b/res/drawable-mdpi/ic_home_arrows_1_normal_right.png
index 1d5d587..705cf0f 100644
--- a/res/drawable-mdpi/ic_home_arrows_1_normal_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_1_normal_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_1_press.png b/res/drawable-mdpi/ic_home_arrows_1_press.png
index 1132b3c..b5d6e3e 100644
--- a/res/drawable-mdpi/ic_home_arrows_1_press.png
+++ b/res/drawable-mdpi/ic_home_arrows_1_press.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_1_press_right.png b/res/drawable-mdpi/ic_home_arrows_1_press_right.png
index 57f2133..694db41 100644
--- a/res/drawable-mdpi/ic_home_arrows_1_press_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_1_press_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_2_focus.png b/res/drawable-mdpi/ic_home_arrows_2_focus.png
index 0cf274d..fc64540 100644
--- a/res/drawable-mdpi/ic_home_arrows_2_focus.png
+++ b/res/drawable-mdpi/ic_home_arrows_2_focus.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_2_focus_right.png b/res/drawable-mdpi/ic_home_arrows_2_focus_right.png
index 16c008d..0e25d39 100644
--- a/res/drawable-mdpi/ic_home_arrows_2_focus_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_2_focus_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_2_normal.png b/res/drawable-mdpi/ic_home_arrows_2_normal.png
index 3c37560..712c57d 100644
--- a/res/drawable-mdpi/ic_home_arrows_2_normal.png
+++ b/res/drawable-mdpi/ic_home_arrows_2_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_2_normal_right.png b/res/drawable-mdpi/ic_home_arrows_2_normal_right.png
index 23172d8..5a4a26c 100644
--- a/res/drawable-mdpi/ic_home_arrows_2_normal_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_2_normal_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_2_press.png b/res/drawable-mdpi/ic_home_arrows_2_press.png
index 2ae042a..db8422d 100644
--- a/res/drawable-mdpi/ic_home_arrows_2_press.png
+++ b/res/drawable-mdpi/ic_home_arrows_2_press.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_2_press_right.png b/res/drawable-mdpi/ic_home_arrows_2_press_right.png
index 0fad08c..d55ea40 100644
--- a/res/drawable-mdpi/ic_home_arrows_2_press_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_2_press_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_3_focus.png b/res/drawable-mdpi/ic_home_arrows_3_focus.png
index 151b2f6..51f317c 100644
--- a/res/drawable-mdpi/ic_home_arrows_3_focus.png
+++ b/res/drawable-mdpi/ic_home_arrows_3_focus.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_3_focus_right.png b/res/drawable-mdpi/ic_home_arrows_3_focus_right.png
index 1072ee2..b61cf1c 100644
--- a/res/drawable-mdpi/ic_home_arrows_3_focus_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_3_focus_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_3_normal.png b/res/drawable-mdpi/ic_home_arrows_3_normal.png
index 92e6277..24f0c82 100644
--- a/res/drawable-mdpi/ic_home_arrows_3_normal.png
+++ b/res/drawable-mdpi/ic_home_arrows_3_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_3_normal_right.png b/res/drawable-mdpi/ic_home_arrows_3_normal_right.png
index 52c2ac7..8b41770 100644
--- a/res/drawable-mdpi/ic_home_arrows_3_normal_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_3_normal_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_3_press.png b/res/drawable-mdpi/ic_home_arrows_3_press.png
index 612b698..7ba3951 100644
--- a/res/drawable-mdpi/ic_home_arrows_3_press.png
+++ b/res/drawable-mdpi/ic_home_arrows_3_press.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_3_press_right.png b/res/drawable-mdpi/ic_home_arrows_3_press_right.png
index f8571f1..b5ceff4 100644
--- a/res/drawable-mdpi/ic_home_arrows_3_press_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_3_press_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_4_focus.png b/res/drawable-mdpi/ic_home_arrows_4_focus.png
index f3fffbe0..0265c6b 100644
--- a/res/drawable-mdpi/ic_home_arrows_4_focus.png
+++ b/res/drawable-mdpi/ic_home_arrows_4_focus.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_4_focus_right.png b/res/drawable-mdpi/ic_home_arrows_4_focus_right.png
index f01de46..e65ed85 100644
--- a/res/drawable-mdpi/ic_home_arrows_4_focus_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_4_focus_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_4_normal.png b/res/drawable-mdpi/ic_home_arrows_4_normal.png
index 2ad2745..f3a19a7 100644
--- a/res/drawable-mdpi/ic_home_arrows_4_normal.png
+++ b/res/drawable-mdpi/ic_home_arrows_4_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_4_normal_right.png b/res/drawable-mdpi/ic_home_arrows_4_normal_right.png
index e519de2..24ec6e7 100644
--- a/res/drawable-mdpi/ic_home_arrows_4_normal_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_4_normal_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_4_press.png b/res/drawable-mdpi/ic_home_arrows_4_press.png
index 9cbc554..9623df4 100644
--- a/res/drawable-mdpi/ic_home_arrows_4_press.png
+++ b/res/drawable-mdpi/ic_home_arrows_4_press.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_home_arrows_4_press_right.png b/res/drawable-mdpi/ic_home_arrows_4_press_right.png
index a60c8d5..8a577fa 100644
--- a/res/drawable-mdpi/ic_home_arrows_4_press_right.png
+++ b/res/drawable-mdpi/ic_home_arrows_4_press_right.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_application.png b/res/drawable-mdpi/ic_launcher_application.png
index 9777d11..18ea7a5 100644
--- a/res/drawable-mdpi/ic_launcher_application.png
+++ b/res/drawable-mdpi/ic_launcher_application.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_appwidget.png b/res/drawable-mdpi/ic_launcher_appwidget.png
index e9371d2..f369ccd 100644
--- a/res/drawable-mdpi/ic_launcher_appwidget.png
+++ b/res/drawable-mdpi/ic_launcher_appwidget.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_folder.png b/res/drawable-mdpi/ic_launcher_folder.png
index 14e0839..08b4aad 100644
--- a/res/drawable-mdpi/ic_launcher_folder.png
+++ b/res/drawable-mdpi/ic_launcher_folder.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_folder_open.png b/res/drawable-mdpi/ic_launcher_folder_open.png
index 6a61ca6..b7640cb 100644
--- a/res/drawable-mdpi/ic_launcher_folder_open.png
+++ b/res/drawable-mdpi/ic_launcher_folder_open.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_home.png b/res/drawable-mdpi/ic_launcher_home.png
index 95a50e6..893d7c7 100644
--- a/res/drawable-mdpi/ic_launcher_home.png
+++ b/res/drawable-mdpi/ic_launcher_home.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_shortcut.png b/res/drawable-mdpi/ic_launcher_shortcut.png
index 05bc055..ba91360 100644
--- a/res/drawable-mdpi/ic_launcher_shortcut.png
+++ b/res/drawable-mdpi/ic_launcher_shortcut.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_launcher_wallpaper.png b/res/drawable-mdpi/ic_launcher_wallpaper.png
index 982fd88..7e7c6b8 100644
--- a/res/drawable-mdpi/ic_launcher_wallpaper.png
+++ b/res/drawable-mdpi/ic_launcher_wallpaper.png
Binary files differ
diff --git a/res/drawable-mdpi/mini_home_screen_bg.9.png b/res/drawable-mdpi/mini_home_screen_bg.9.png
new file mode 100644
index 0000000..a567457
--- /dev/null
+++ b/res/drawable-mdpi/mini_home_screen_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/mini_home_screen_bg_accepts_drops.9.png b/res/drawable-mdpi/mini_home_screen_bg_accepts_drops.9.png
new file mode 100644
index 0000000..53048ec
--- /dev/null
+++ b/res/drawable-mdpi/mini_home_screen_bg_accepts_drops.9.png
Binary files differ
diff --git a/res/drawable-mdpi/mini_home_screen_bg_hover.9.png b/res/drawable-mdpi/mini_home_screen_bg_hover.9.png
new file mode 100644
index 0000000..ff8b28d
--- /dev/null
+++ b/res/drawable-mdpi/mini_home_screen_bg_hover.9.png
Binary files differ
diff --git a/res/drawable/page_hover_left.9.png b/res/drawable-mdpi/page_hover_left.9.png
similarity index 100%
rename from res/drawable/page_hover_left.9.png
rename to res/drawable-mdpi/page_hover_left.9.png
Binary files differ
diff --git a/res/drawable/page_hover_right.9.png b/res/drawable-mdpi/page_hover_right.9.png
similarity index 100%
rename from res/drawable/page_hover_right.9.png
rename to res/drawable-mdpi/page_hover_right.9.png
Binary files differ
diff --git a/res/drawable-mdpi/pressed_application_background.9.png b/res/drawable-mdpi/pressed_application_background.9.png
index 1fd727e..b09f595 100644
--- a/res/drawable-mdpi/pressed_application_background.9.png
+++ b/res/drawable-mdpi/pressed_application_background.9.png
Binary files differ
diff --git a/res/drawable-mdpi/preview_bg.9.png b/res/drawable-mdpi/preview_bg.9.png
index 5647144..82c951d 100644
--- a/res/drawable-mdpi/preview_bg.9.png
+++ b/res/drawable-mdpi/preview_bg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/preview_bg_focus.9.png b/res/drawable-mdpi/preview_bg_focus.9.png
index 31200fd..f64f6a0 100644
--- a/res/drawable-mdpi/preview_bg_focus.9.png
+++ b/res/drawable-mdpi/preview_bg_focus.9.png
Binary files differ
diff --git a/res/drawable-mdpi/preview_bg_press.9.png b/res/drawable-mdpi/preview_bg_press.9.png
index 9cb1266..151cab6 100644
--- a/res/drawable-mdpi/preview_bg_press.9.png
+++ b/res/drawable-mdpi/preview_bg_press.9.png
Binary files differ
diff --git a/res/drawable/rounded_rect_green.9.png b/res/drawable-mdpi/rounded_rect_green.9.png
similarity index 100%
rename from res/drawable/rounded_rect_green.9.png
rename to res/drawable-mdpi/rounded_rect_green.9.png
Binary files differ
diff --git a/res/drawable/rounded_rect_red.9.png b/res/drawable-mdpi/rounded_rect_red.9.png
similarity index 100%
rename from res/drawable/rounded_rect_red.9.png
rename to res/drawable-mdpi/rounded_rect_red.9.png
Binary files differ
diff --git a/res/drawable-mdpi/trashcan.png b/res/drawable-mdpi/trashcan.png
index 4f01d76..f32bf27 100644
--- a/res/drawable-mdpi/trashcan.png
+++ b/res/drawable-mdpi/trashcan.png
Binary files differ
diff --git a/res/drawable-mdpi/trashcan_hover.png b/res/drawable-mdpi/trashcan_hover.png
index fb7474a..bffa33f 100644
--- a/res/drawable-mdpi/trashcan_hover.png
+++ b/res/drawable-mdpi/trashcan_hover.png
Binary files differ
diff --git a/res/drawable-mdpi/wallpaper_nexuswallpaper1.png b/res/drawable-mdpi/wallpaper_nexuswallpaper1.png
index 2cc6e00..20c74a1 100644
--- a/res/drawable-mdpi/wallpaper_nexuswallpaper1.png
+++ b/res/drawable-mdpi/wallpaper_nexuswallpaper1.png
Binary files differ
diff --git a/res/drawable/widget_divider.png b/res/drawable-mdpi/widget_divider.png
similarity index 100%
rename from res/drawable/widget_divider.png
rename to res/drawable-mdpi/widget_divider.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/all_apps_button_normal.9.png b/res/drawable-xlarge-hdpi/all_apps_button_normal.9.png
index 9893ca8..8aea26e 100644
--- a/res/drawable-xlarge-hdpi/all_apps_button_normal.9.png
+++ b/res/drawable-xlarge-hdpi/all_apps_button_normal.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/all_apps_button_pressed.9.png b/res/drawable-xlarge-hdpi/all_apps_button_pressed.9.png
index e2ba861..587f1f1 100644
--- a/res/drawable-xlarge-hdpi/all_apps_button_pressed.9.png
+++ b/res/drawable-xlarge-hdpi/all_apps_button_pressed.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/app_market_generic.png b/res/drawable-xlarge-hdpi/app_market_generic.png
index c093e24..2a2381f 100644
--- a/res/drawable-xlarge-hdpi/app_market_generic.png
+++ b/res/drawable-xlarge-hdpi/app_market_generic.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/configure_button_normal.png b/res/drawable-xlarge-hdpi/configure_button_normal.png
index 068f84d..48ae0b2 100644
--- a/res/drawable-xlarge-hdpi/configure_button_normal.png
+++ b/res/drawable-xlarge-hdpi/configure_button_normal.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/configure_button_pressed.png b/res/drawable-xlarge-hdpi/configure_button_pressed.png
index 348a04f..54dea70 100644
--- a/res/drawable-xlarge-hdpi/configure_button_pressed.png
+++ b/res/drawable-xlarge-hdpi/configure_button_pressed.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/home_press.9.png b/res/drawable-xlarge-hdpi/home_press.9.png
index 4beec62..743880b 100644
--- a/res/drawable-xlarge-hdpi/home_press.9.png
+++ b/res/drawable-xlarge-hdpi/home_press.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/home_screen_bg.9.png b/res/drawable-xlarge-hdpi/home_screen_bg.9.png
index 9f98252..0a4ee8d 100644
--- a/res/drawable-xlarge-hdpi/home_screen_bg.9.png
+++ b/res/drawable-xlarge-hdpi/home_screen_bg.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/home_screen_bg_hover.9.png b/res/drawable-xlarge-hdpi/home_screen_bg_hover.9.png
index e03b440..2822639 100644
--- a/res/drawable-xlarge-hdpi/home_screen_bg_hover.9.png
+++ b/res/drawable-xlarge-hdpi/home_screen_bg_hover.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/ic_no_applications.png b/res/drawable-xlarge-hdpi/ic_no_applications.png
index 5592e6e..933d091 100644
--- a/res/drawable-xlarge-hdpi/ic_no_applications.png
+++ b/res/drawable-xlarge-hdpi/ic_no_applications.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/ic_voice_search.png b/res/drawable-xlarge-hdpi/ic_voice_search.png
index 66d14ae..f659877 100644
--- a/res/drawable-xlarge-hdpi/ic_voice_search.png
+++ b/res/drawable-xlarge-hdpi/ic_voice_search.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/info_button.png b/res/drawable-xlarge-hdpi/info_button.png
index 1707a4f..e9ed1b1 100644
--- a/res/drawable-xlarge-hdpi/info_button.png
+++ b/res/drawable-xlarge-hdpi/info_button.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/mini_home_screen_bg.9.png b/res/drawable-xlarge-hdpi/mini_home_screen_bg.9.png
index 65db5f5..e255178 100644
--- a/res/drawable-xlarge-hdpi/mini_home_screen_bg.9.png
+++ b/res/drawable-xlarge-hdpi/mini_home_screen_bg.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/mini_home_screen_bg_accepts_drops.9.png b/res/drawable-xlarge-hdpi/mini_home_screen_bg_accepts_drops.9.png
index f56bbeb..c9834fa 100644
--- a/res/drawable-xlarge-hdpi/mini_home_screen_bg_accepts_drops.9.png
+++ b/res/drawable-xlarge-hdpi/mini_home_screen_bg_accepts_drops.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/mini_home_screen_bg_hover.9.png b/res/drawable-xlarge-hdpi/mini_home_screen_bg_hover.9.png
index f5036fc..83afcc0 100644
--- a/res/drawable-xlarge-hdpi/mini_home_screen_bg_hover.9.png
+++ b/res/drawable-xlarge-hdpi/mini_home_screen_bg_hover.9.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/search_button_normal.png b/res/drawable-xlarge-hdpi/search_button_normal.png
index f201b65..b1df556 100644
--- a/res/drawable-xlarge-hdpi/search_button_normal.png
+++ b/res/drawable-xlarge-hdpi/search_button_normal.png
Binary files differ
diff --git a/res/drawable-xlarge-hdpi/search_button_pressed.png b/res/drawable-xlarge-hdpi/search_button_pressed.png
index 0fbb6c2..1013383 100644
--- a/res/drawable-xlarge-hdpi/search_button_pressed.png
+++ b/res/drawable-xlarge-hdpi/search_button_pressed.png
Binary files differ
diff --git a/res/drawable-xlarge-mdpi/all_apps_button_focused.png b/res/drawable-xlarge-mdpi/all_apps_button_focused.png
deleted file mode 100644
index a9d5a3f..0000000
--- a/res/drawable-xlarge-mdpi/all_apps_button_focused.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xlarge/all_apps_bg_gradient.9.png b/res/drawable-xlarge-nodpi/all_apps_bg_gradient.9.png
similarity index 100%
rename from res/drawable-xlarge/all_apps_bg_gradient.9.png
rename to res/drawable-xlarge-nodpi/all_apps_bg_gradient.9.png
Binary files differ
diff --git a/res/drawable-xlarge/customize_bg_gradient.png b/res/drawable-xlarge-nodpi/customize_bg_gradient.png
similarity index 100%
rename from res/drawable-xlarge/customize_bg_gradient.png
rename to res/drawable-xlarge-nodpi/customize_bg_gradient.png
Binary files differ
diff --git a/res/drawable/default_widget_preview.9.png b/res/drawable/default_widget_preview.9.png
deleted file mode 100644
index 5fedcc8..0000000
--- a/res/drawable/default_widget_preview.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/pressed_application_background.9.png b/res/drawable/pressed_application_background.9.png
deleted file mode 100644
index 754af48..0000000
--- a/res/drawable/pressed_application_background.9.png
+++ /dev/null
Binary files differ
diff --git a/src/com/android/launcher2/Alarm.java b/src/com/android/launcher2/Alarm.java
new file mode 100644
index 0000000..38ff367
--- /dev/null
+++ b/src/com/android/launcher2/Alarm.java
@@ -0,0 +1,76 @@
+/*
+ * 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 android.os.Handler;
+
+public class Alarm implements Runnable{
+    // if we reach this time and the alarm hasn't been cancelled, call the listener
+    private long mAlarmTriggerTime;
+
+    // if we've scheduled a call to run() (ie called mHandler.postDelayed), this variable is true.
+    // We use this to avoid having multiple pending callbacks
+    private boolean mWaitingForCallback;
+
+    private Handler mHandler;
+    private OnAlarmListener mAlarmListener;
+
+    public Alarm() {
+        mHandler = new Handler();
+    }
+
+    public void setOnAlarmListener(OnAlarmListener alarmListener) {
+        mAlarmListener = alarmListener;
+    }
+
+    // Sets the alarm to go off in a certain number of milliseconds. If the alarm is already set,
+    // it's overwritten and only the new alarm setting is used
+    public void setAlarm(long millisecondsInFuture) {
+        long currentTime = System.currentTimeMillis();
+        mAlarmTriggerTime = currentTime + millisecondsInFuture;
+        if (!mWaitingForCallback) {
+            mHandler.postDelayed(this, mAlarmTriggerTime - currentTime);
+            mWaitingForCallback = true;
+        }
+    }
+
+    public void cancelAlarm() {
+        mAlarmTriggerTime = 0;
+    }
+
+    // this is called when our timer runs out
+    public void run() {
+        mWaitingForCallback = false;
+        if (mAlarmTriggerTime != 0) {
+            long currentTime = System.currentTimeMillis();
+            if (mAlarmTriggerTime > currentTime) {
+                // We still need to wait some time to trigger spring loaded mode--
+                // post a new callback
+                mHandler.postDelayed(this, Math.max(0, mAlarmTriggerTime - currentTime));
+                mWaitingForCallback = true;
+            } else {
+                if (mAlarmListener != null) {
+                    mAlarmListener.onAlarm(this);
+                }
+            }
+        }
+    }
+}
+
+interface OnAlarmListener {
+    public void onAlarm(Alarm alarm);
+}
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index ecdb7b3..2fd0b65 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -16,21 +16,25 @@
 
 package com.android.launcher2;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
+import com.android.launcher.R;
 
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.animation.AnimationUtils;
 import android.widget.Checkable;
 import android.widget.TextView;
 
-import com.android.launcher.R;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
 
 /**
  * An implementation of PagedView that populates the pages of the workspace
@@ -43,9 +47,6 @@
     private static final String TAG = "AllAppsPagedView";
     private static final boolean DEBUG = false;
 
-    private static final int MENU_DELETE_APP = 1;
-    private static final int MENU_APP_INFO = 2;
-
     private Launcher mLauncher;
     private DragController mDragController;
 
@@ -199,7 +200,7 @@
     }
 
     private void setupDragMode() {
-        mLauncher.getWorkspace().shrinkToBottomVisible();
+        mLauncher.getWorkspace().shrink(Workspace.ShrinkState.BOTTOM_VISIBLE);
 
         ApplicationInfoDropTarget infoButton =
                 (ApplicationInfoDropTarget) mLauncher.findViewById(R.id.info_button);
@@ -261,8 +262,14 @@
         ApplicationInfo app = (ApplicationInfo) v.getTag();
         app = new ApplicationInfo(app);
 
-        mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1);
-        mDragController.startDrag(v, this, app, DragController.DRAG_ACTION_COPY);
+        // get icon (top compound drawable, index is 1)
+        final Drawable icon = ((TextView) v).getCompoundDrawables()[1];
+        Bitmap b = Bitmap.createBitmap(icon.getIntrinsicWidth(), icon.getIntrinsicHeight(),
+                Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas(b);
+        icon.draw(c);
+        mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
+        mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, null);
         return true;
     }
 
diff --git a/src/com/android/launcher2/CacheableTextView.java b/src/com/android/launcher2/CacheableTextView.java
index 50da7cd..873cd4e 100644
--- a/src/com/android/launcher2/CacheableTextView.java
+++ b/src/com/android/launcher2/CacheableTextView.java
@@ -46,6 +46,7 @@
     float mRectLeft, mRectTop;
     private float mPaddingH = 0;
     private float mPaddingV = 0;
+    private CharSequence mText;
 
     public CacheableTextView(Context context) {
         super(context);
@@ -128,10 +129,15 @@
             // potential issues with text measurement, like line height, etc.) so that the text view
             // doesn't draw it anymore, since it's been cached. We have to manually rebuild
             // the cache whenever the text is changed (which is never in Launcher)
+            mText = getText();
             setText(" ");
         }
     }
 
+    public CharSequence getText() {
+        return (mText == null) ? super.getText() : mText;
+    }
+
     public void draw(Canvas canvas) {
         if (mWaitingToGenerateCache && !mIsBuildingCache) {
             buildAndEnableCache(true);
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 8fe489d..a104c55 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -801,7 +801,10 @@
                             cellXY[0] + childLeft + lp.width / 2,
                             cellXY[1] + childTop + lp.height / 2, 0, null);
 
-                    ((Workspace) mParent).animateViewIntoPosition(child);
+                    if (lp.animateDrop) {
+                        lp.animateDrop = false;
+                        ((Workspace) mParent).animateViewIntoPosition(child);
+                    }
                 }
             }
         }
@@ -1224,11 +1227,12 @@
      *
      * @param child The child that is being dropped
      */
-    void onDropChild(View child) {
+    void onDropChild(View child, boolean animate) {
         if (child != null) {
             LayoutParams lp = (LayoutParams) child.getLayoutParams();
             lp.isDragging = false;
             lp.dropped = true;
+            lp.animateDrop = animate;
             child.setVisibility(View.VISIBLE);
             child.requestLayout();
         }
@@ -1466,6 +1470,8 @@
 
         boolean dropped;
 
+        boolean animateDrop;
+
         public LayoutParams(Context c, AttributeSet attrs) {
             super(c, attrs);
             cellHSpan = 1;
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 50ec64b..342974a 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -21,24 +21,34 @@
 import java.util.Comparator;
 import java.util.List;
 
+import org.xmlpull.v1.XmlPullParser;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.TimeInterpolator;
+import android.animation.Animator.AnimatorListener;
+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.Color;
-import android.graphics.Rect;
-import android.graphics.Region.Op;
+import android.graphics.Bitmap.Config;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Slog;
+import android.util.TypedValue;
+import android.util.Xml;
 import android.view.ActionMode;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -46,12 +56,15 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.launcher.R;
 
+
 public class CustomizePagedView extends PagedView
     implements View.OnLongClickListener, View.OnClickListener, View.OnTouchListener,
                 DragSource, ActionMode.Callback {
@@ -90,9 +103,6 @@
     // The size of the items on the wallpaper tab
     private int mWallpaperCellHSpan;
 
-    // The max dimensions for the ImageView we use for displaying a wallpaper
-    private int mMaxWallpaperWidth;
-
     // The raw sources of data for each of the different tabs of the customization page
     private List<AppWidgetProviderInfo> mWidgetList;
     private List<ResolveInfo> mShortcutList;
@@ -110,6 +120,12 @@
     private final Canvas mCanvas = new Canvas();
     private final LayoutInflater mInflater;
 
+    private final float mTmpFloatPos[] = new float[2];
+    private final float ANIMATION_SCALE = 0.5f;
+    private final int ANIMATION_DURATION = 400;
+    private TimeInterpolator mQuintEaseOutInterpolator = new DecelerateInterpolator(2.5f);
+    private ScaleAlphaInterpolator mScaleAlphaInterpolator = new ScaleAlphaInterpolator();
+
     public CustomizePagedView(Context context) {
         this(context, null, 0);
     }
@@ -276,7 +292,8 @@
 
         // get the list of wallpapers
         Intent wallpapersIntent = new Intent(Intent.ACTION_SET_WALLPAPER);
-        mWallpaperList = mPackageManager.queryIntentActivities(wallpapersIntent, 0);
+        mWallpaperList = mPackageManager.queryIntentActivities(wallpapersIntent,
+                PackageManager.GET_META_DATA);
         Collections.sort(mWallpaperList, resolveInfoComparator);
 
         invalidatePageDataAndIconCache();
@@ -315,8 +332,84 @@
     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);
+            }
+        }
+    }
+
+    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;
+        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;
+            }
+        }
+
+        float toX = mTmpFloatPos[0] - dragView.getMeasuredWidth() / 2 + widthOffset;
+        float toY = mTmpFloatPos[1] - dragView.getMeasuredHeight() / 2 + heightOffset;
+
+        ObjectAnimator posAnim = ObjectAnimator.ofPropertyValuesHolder(dragCopy,
+                PropertyValuesHolder.ofFloat("x", toX),
+                PropertyValuesHolder.ofFloat("y", toY));
+        posAnim.setInterpolator(mQuintEaseOutInterpolator);
+        posAnim.setDuration(ANIMATION_DURATION);
+
+        posAnim.addListener(new AnimatorListener() {
+            public void onAnimationCancel(Animator animation) {}
+            public void onAnimationRepeat(Animator animation) {}
+            public void onAnimationStart(Animator animation) {}
+
+            public void onAnimationEnd(Animator animation) {
+                dragLayer.removeView(dragCopy);
+                mLauncher.addExternalItemToScreen(info, layout);
+                post(new Runnable() {
+                    public void run() {
+                        layout.animateDrop();
+                    }
+                });
+            }
+        });
+
+        ObjectAnimator scaleAlphaAnim = ObjectAnimator.ofPropertyValuesHolder(dragCopy,
+                PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.0f),
+                PropertyValuesHolder.ofFloat("scaleX", ANIMATION_SCALE),
+                PropertyValuesHolder.ofFloat("scaleY", ANIMATION_SCALE));
+        scaleAlphaAnim.setInterpolator(mScaleAlphaInterpolator);
+        scaleAlphaAnim.setDuration(ANIMATION_DURATION);
+
+        posAnim.start();
+        scaleAlphaAnim.start();
+    }
+
     @Override
-    public void onClick(View v) {
+    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
@@ -348,11 +441,12 @@
             Workspace w = mLauncher.getWorkspace();
             int currentWorkspaceScreen = mLauncher.getCurrentWorkspaceScreen();
             final CellLayout cl = (CellLayout)w.getChildAt(currentWorkspaceScreen);
+            final View dragView = getDragView(v);
 
             animateClickFeedback(v, new Runnable() {
                 @Override
                 public void run() {
-                    mLauncher.addExternalItemToScreen(itemInfo, cl);
+                    animateItemOntoScreen(dragView, cl, itemInfo);
                 }
             });
             return;
@@ -473,6 +567,19 @@
         return super.onTouchEvent(ev);
     }
 
+    Bitmap drawableToBitmap(Drawable d) {
+        Bitmap b = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(),
+                Bitmap.Config.ARGB_8888);
+        Canvas c = new Canvas(b);
+        d.draw(c);
+        return b;
+    }
+
+    private View getDragView(View v) {
+        return (mCustomizationType == CustomizationType.WidgetCustomization) ?
+                v.findViewById(R.id.widget_preview) : v;
+    }
+
     private boolean beginDragging(View v) {
         // End the current choice mode before we start dragging anything
         if (isChoiceMode(CHOICE_MODE_SINGLE)) {
@@ -480,39 +587,48 @@
         }
         mIsDragging = true;
 
-        PendingAddItemInfo createItemInfo;
         switch (mCustomizationType) {
-        case WidgetCustomization:
-            // Get the icon as the drag representation
+        case WidgetCustomization: {
+            // Get the widget preview as the drag representation
             final LinearLayout l = (LinearLayout) v;
             final Drawable icon = ((ImageView) l.findViewById(R.id.widget_preview)).getDrawable();
-            Bitmap b = Bitmap.createBitmap(icon.getIntrinsicWidth(), icon.getIntrinsicHeight(),
-                    Bitmap.Config.ARGB_8888);
-            Canvas c = new Canvas(b);
-            icon.draw(c);
+            Bitmap b = drawableToBitmap(icon);
             PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) v.getTag();
+            final View dragView = v.findViewById(R.id.widget_preview);
 
-            mLauncher.getWorkspace().onDragStartedWithItemMinSize(
-                    createWidgetInfo.minWidth, createWidgetInfo.minHeight);
-            mDragController.startDrag(v, b, this, createWidgetInfo, DragController.DRAG_ACTION_COPY, 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(
+                    v, b, this, createWidgetInfo, DragController.DRAG_ACTION_COPY, null);
 
-            // Cleanup the icon
-            b.recycle();
             return true;
-        case ShortcutCustomization:
-            createItemInfo = (PendingAddItemInfo) v.getTag();
-            mDragController.startDrag(v, this, createItemInfo, DragController.DRAG_ACTION_COPY);
-            mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1);
+        }
+        case ShortcutCustomization: {
+            // get icon (top compound drawable, index is 1)
+            final Drawable icon = ((TextView) v).getCompoundDrawables()[1];
+            Bitmap b = drawableToBitmap(icon);
+            PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
+            mDragController.startDrag(
+                    v, b, this, createItemInfo, DragController.DRAG_ACTION_COPY, null);
+            mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
             return true;
-        case ApplicationCustomization:
+        }
+        case ApplicationCustomization: {
             // Pick up the application for dropping
+            // get icon (top compound drawable, index is 1)
+            final Drawable icon = ((TextView) v).getCompoundDrawables()[1];
+            Bitmap b = drawableToBitmap(icon);
             ApplicationInfo app = (ApplicationInfo) v.getTag();
             app = new ApplicationInfo(app);
 
-            mDragController.startDrag(v, this, app, DragController.DRAG_ACTION_COPY);
-            mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1);
+            mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, null);
+            mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
             return true;
         }
+        }
         return false;
     }
 
@@ -565,6 +681,63 @@
         mCanvas.restore();
     }
 
+    /*
+     * 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(ComponentName component, ResolveInfo ri) {
+        Drawable d = null;
+
+        ActivityInfo activityInfo = ri.activityInfo;
+        XmlResourceParser parser = null;
+        try {
+            parser = activityInfo.loadXmlMetaData(mPackageManager,
+                    WallpaperManager.WALLPAPER_PREVIEW_META_DATA);
+            if (parser == null) {
+                Slog.w(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(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(TAG, "XML parsing failed for wallpaper provider '" + component + '\'', e);
+            return null;
+        } finally {
+            if (parser != null) parser.close();
+        }
+    }
+
     /**
      * This method will extract the preview image specified by the wallpaper source provider (if it
      * exists) otherwise, it will try to generate a default image preview.
@@ -580,21 +753,31 @@
         int width = (int) (dim * sScaleFactor);
         int height = (int) (dim * sScaleFactor);
         final Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
-        final Drawable background = resources.getDrawable(R.drawable.default_widget_preview);
+
+        Drawable background = parseWallpaperPreviewXml(
+                new ComponentName(info.activityInfo.packageName, info.activityInfo.name), info);
+        boolean foundCustomDrawable = background != null;
+
+        if (!foundCustomDrawable) {
+            background = resources.getDrawable(R.drawable.default_widget_preview);
+        }
+
         renderDrawableToBitmap(background, bitmap, 0, 0, width, height);
 
-        // Draw the icon flush left
-        try {
-            final IconCache iconCache =
-                ((LauncherApplication) mLauncher.getApplication()).getIconCache();
-            Drawable icon = new FastBitmapDrawable(Utilities.createIconBitmap(
-                    iconCache.getFullResIcon(info, mPackageManager), mContext));
+        // If we don't have a custom icon, we use the app icon on the default background
+        if (!foundCustomDrawable) {
+            try {
+                final IconCache iconCache =
+                    ((LauncherApplication) mLauncher.getApplication()).getIconCache();
+                Drawable icon = new FastBitmapDrawable(Utilities.createIconBitmap(
+                        iconCache.getFullResIcon(info, mPackageManager), mContext));
 
-            final int iconSize = minDim / 2;
-            final int offset = iconSize / 4;
-            renderDrawableToBitmap(icon, null, offset, offset, iconSize, iconSize);
-        } catch (Resources.NotFoundException e) {
-            // if we can't find the icon, then just don't draw it
+                final int iconSize = minDim / 2;
+                final int offset = iconSize / 4;
+                renderDrawableToBitmap(icon, null, offset, offset, iconSize, iconSize);
+            } catch (Resources.NotFoundException e) {
+                // if we can't find the icon, then just don't draw it
+            }
         }
 
         FastBitmapDrawable drawable = new FastBitmapDrawable(bitmap);
@@ -692,7 +875,6 @@
         mWorkspaceWidgetLayout.setPadding(20, 10, 20, 0);
 
         mMaxWidgetWidth = mWorkspaceWidgetLayout.estimateCellWidth(sMaxWidgetCellHSpan);
-        mMaxWallpaperWidth = mWorkspaceWidgetLayout.estimateCellWidth(mWallpaperCellHSpan);
     }
 
     private void syncWidgetPages() {
@@ -807,7 +989,7 @@
             PagedViewIcon icon = (PagedViewIcon) mInflater.inflate(
                     R.layout.customize_paged_view_item, layout, false);
             icon.applyFromResolveInfo(info, mPackageManager, mPageViewIconCache,
-                    ((LauncherApplication)mLauncher.getApplication()).getIconCache());
+                    ((LauncherApplication) mLauncher.getApplication()).getIconCache());
             switch (mCustomizationType) {
             case WallpaperCustomization:
                 icon.setOnClickListener(this);
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index a0a44a5..876ad87 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher2;
 
-import com.android.launcher.R;
+import java.util.ArrayList;
 
 import android.content.Context;
 import android.graphics.Bitmap;
@@ -34,7 +34,7 @@
 import android.view.WindowManager;
 import android.view.inputmethod.InputMethodManager;
 
-import java.util.ArrayList;
+import com.android.launcher.R;
 
 /**
  * Class for initiating a drag within a view or across multiple views.
@@ -340,7 +340,7 @@
     /**
      * Draw the view into a bitmap.
      */
-    private Bitmap getViewBitmap(View v) {
+    Bitmap getViewBitmap(View v) {
         v.clearFocus();
         v.setPressed(false);
 
@@ -351,6 +351,8 @@
         // for the duration of this operation
         int color = v.getDrawingCacheBackgroundColor();
         v.setDrawingCacheBackgroundColor(0);
+        float alpha = v.getAlpha();
+        v.setAlpha(1.0f);
 
         if (color != 0) {
             v.destroyDrawingCache();
@@ -366,6 +368,7 @@
 
         // Restore the view
         v.destroyDrawingCache();
+        v.setAlpha(alpha);
         v.setWillNotCacheDrawing(willNotCache);
         v.setDrawingCacheBackgroundColor(color);
 
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index ab71670..b418a79 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -17,17 +17,20 @@
 package com.android.launcher2;
 
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
 
 /**
  * A ViewGroup that coordinates dragging across its descendants
  */
 public class DragLayer extends FrameLayout {
-    DragController mDragController;
+    private DragController mDragController;
+    private int[] mTmpXY = new int[2];
 
     /**
      * Used to create a new DragLayer from XML.
@@ -62,4 +65,19 @@
     public boolean dispatchUnhandledMove(View focused, int direction) {
         return mDragController.dispatchUnhandledMove(focused, direction);
     }
+
+    public View createDragView(Bitmap b, int xPos, int yPos) {
+        ImageView imageView = new ImageView(mContext);
+        imageView.setImageBitmap(b);
+        imageView.setX(xPos);
+        imageView.setY(yPos);
+        addView(imageView, b.getWidth(), b.getHeight());
+
+        return imageView;
+    }
+
+    public View createDragView(View v) {
+        v.getLocationOnScreen(mTmpXY);
+        return createDragView(mDragController.getViewBitmap(v), mTmpXY[0], mTmpXY[1]);
+    }
 }
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index 947184f..a8dad7a 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -17,8 +17,6 @@
 
 package com.android.launcher2;
 
-import com.android.launcher.R;
-
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
@@ -36,6 +34,8 @@
 import android.view.WindowManagerImpl;
 import android.view.animation.DecelerateInterpolator;
 
+import com.android.launcher.R;
+
 public class DragView extends View {
     private Bitmap mBitmap;
     private Paint mPaint;
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index bbb5967..0cb0e13 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -17,13 +17,9 @@
 
 package com.android.launcher2;
 
-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;
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
@@ -59,7 +55,6 @@
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
@@ -104,8 +99,13 @@
 import android.widget.TabHost.OnTabChangeListener;
 import android.widget.TabHost.TabContentFactory;
 
-import com.android.common.Search;
-import com.android.launcher.R;
+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;
 
 
 /**
@@ -176,7 +176,8 @@
     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, ALL_APPS, CUSTOMIZE, OVERVIEW,
+        CUSTOMIZE_SPRING_LOADED, ALL_APPS_SPRING_LOADED };
     private State mState = State.WORKSPACE;
     private AnimatorSet mStateAnimation;
 
@@ -1112,7 +1113,23 @@
         final int[] cellXY = mTmpAddItemCellCoordinates;
         final CellLayout layout = (CellLayout) mWorkspace.getChildAt(screen);
 
-        if (!layout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectCellX, intersectCellY)) {
+        int[] touchXY = null;
+        if (mAddDropPosition != null && mAddDropPosition[0] > -1 && mAddDropPosition[1] > -1) {
+            touchXY = mAddDropPosition;
+        }
+        boolean foundCellSpan = false;
+        if (touchXY != null) {
+            // when dragging and dropping, just find the closest free spot
+            CellLayout screenLayout = (CellLayout) mWorkspace.getChildAt(screen);
+            int[] result = screenLayout.findNearestVacantArea(
+                    touchXY[0], touchXY[1], 1, 1, cellXY);
+            foundCellSpan = (result != null);
+        } else {
+            foundCellSpan = layout.findCellForSpanThatIntersects(
+                    cellXY, 1, 1, intersectCellX, intersectCellY);
+        }
+
+        if (!foundCellSpan) {
             showOutOfSpaceMessage();
             return;
         }
@@ -1151,15 +1168,13 @@
         if (mAddDropPosition != null && mAddDropPosition[0] > -1 && mAddDropPosition[1] > -1) {
             touchXY = mAddDropPosition;
         }
-        boolean findNearestVacantAreaFailed = false;
         boolean foundCellSpan = false;
         if (touchXY != null) {
             // when dragging and dropping, just find the closest free spot
             CellLayout screenLayout = (CellLayout) mWorkspace.getChildAt(screen);
             int[] result = screenLayout.findNearestVacantArea(
                     touchXY[0], touchXY[1], spanXY[0], spanXY[1], cellXY);
-            findNearestVacantAreaFailed = (result == null);
-            foundCellSpan = !findNearestVacantAreaFailed;
+            foundCellSpan = (result != null);
         } else {
             // if we long pressed on an empty cell to bring up a menu,
             // make sure we intersect the empty cell
@@ -1626,8 +1641,6 @@
     void addAppWidgetFromDrop(PendingAddWidgetInfo info, int screen, int[] position) {
         resetAddInfo();
         mAddScreen = screen;
-
-        // only set mAddDropPosition if we dropped on home screen in "spring-loaded" manner
         mAddDropPosition = position;
 
         int appWidgetId = getAppWidgetHost().allocateAppWidgetId();
@@ -2621,9 +2634,9 @@
         setPivotsForZoom(toView, toState, scale);
 
         if (toAllApps) {
-            mWorkspace.shrinkToBottomHidden(animated);
+            mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
         } else {
-            mWorkspace.shrinkToTop(animated);
+            mWorkspace.shrink(ShrinkState.TOP, animated);
         }
 
         if (animated) {
@@ -2685,6 +2698,10 @@
      * @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();
         int duration = res.getInteger(R.integer.config_allAppsZoomOutTime);
         float scaleFactor = (float) res.getInteger(R.integer.config_allAppsZoomScaleFactor);
@@ -2696,7 +2713,9 @@
 
         setPivotsForZoom(fromView, fromState, scaleFactor);
 
-        mWorkspace.unshrink(animated);
+        if (!springLoaded) {
+            mWorkspace.unshrink(animated);
+        }
 
         if (animated) {
             if (mStateAnimation != null) mStateAnimation.cancel();
@@ -2719,7 +2738,9 @@
 
             AnimatorSet toolbarHideAnim = new AnimatorSet();
             AnimatorSet toolbarShowAnim = new AnimatorSet();
-            hideAndShowToolbarButtons(State.WORKSPACE, toolbarShowAnim, toolbarHideAnim);
+            if (!springLoaded) {
+                hideAndShowToolbarButtons(State.WORKSPACE, toolbarShowAnim, toolbarHideAnim);
+            }
 
             mStateAnimation.playTogether(scaleAnim, toolbarHideAnim, alphaAnim);
 
@@ -2730,7 +2751,9 @@
             mStateAnimation.start();
         } else {
             fromView.setVisibility(View.GONE);
-            hideAndShowToolbarButtons(State.WORKSPACE, null, null);
+            if (!springLoaded) {
+                hideAndShowToolbarButtons(State.WORKSPACE, null, null);
+            }
         }
     }
 
@@ -2760,9 +2783,9 @@
         mAllAppsPagedView.endChoiceMode();
 
         if (toState == State.ALL_APPS) {
-            mWorkspace.shrinkToBottomHidden(animated);
+            mWorkspace.shrink(Workspace.ShrinkState.BOTTOM_HIDDEN, animated);
         } else {
-            mWorkspace.shrinkToTop(animated);
+            mWorkspace.shrink(Workspace.ShrinkState.TOP, animated);
         }
 
         if (animated) {
@@ -2859,6 +2882,33 @@
         mState = State.WORKSPACE;
     }
 
+    void enterSpringLoadedDragMode(CellLayout layout) {
+        mWorkspace.enterSpringLoadedDragMode(layout);
+        if (mState == State.ALL_APPS) {
+            cameraZoomIn(State.ALL_APPS, true, true);
+            mState = State.ALL_APPS_SPRING_LOADED;
+        } else if (mState == State.CUSTOMIZE) {
+            cameraZoomIn(State.CUSTOMIZE, true, true);
+            mState = State.CUSTOMIZE_SPRING_LOADED;
+        }/* else {
+            // we're already in spring loaded mode; don't do anything
+        }*/
+    }
+
+    void exitSpringLoadedDragMode() {
+        if (mState == State.ALL_APPS_SPRING_LOADED) {
+            mWorkspace.exitSpringLoadedDragMode(Workspace.ShrinkState.BOTTOM_VISIBLE);
+            cameraZoomOut(State.ALL_APPS, true);
+            mState = State.ALL_APPS;
+        } else if (mState == State.CUSTOMIZE_SPRING_LOADED) {
+            mWorkspace.exitSpringLoadedDragMode(Workspace.ShrinkState.TOP);
+            cameraZoomOut(State.CUSTOMIZE, true);
+            mState = State.CUSTOMIZE;
+        }/* else {
+            // we're not in spring loaded mode; don't do anything
+        }*/
+    }
+
     /**
      * Things to test when changing this code.
      *   - Home from workspace
@@ -2899,7 +2949,7 @@
      *          - From another workspace
      */
     void closeAllApps(boolean animated) {
-        if (mState == State.ALL_APPS) {
+        if (mState == State.ALL_APPS || mState == State.ALL_APPS_SPRING_LOADED) {
             mWorkspace.setVisibility(View.VISIBLE);
             if (LauncherApplication.isScreenXLarge()) {
                 cameraZoomIn(State.ALL_APPS, animated);
@@ -2932,7 +2982,7 @@
 
     // Hide the customization drawer (only exists in x-large configuration)
     void hideCustomizationDrawer(boolean animated) {
-        if (mState == State.CUSTOMIZE) {
+        if (mState == State.CUSTOMIZE || mState == State.CUSTOMIZE_SPRING_LOADED) {
             cameraZoomIn(State.CUSTOMIZE, animated);
         }
     }
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 257531e..856507d 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -16,8 +16,7 @@
 
 package com.android.launcher2;
 
-import java.util.ArrayList;
-import java.util.HashMap;
+import com.android.launcher.R;
 
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -41,7 +40,8 @@
 import android.widget.Checkable;
 import android.widget.Scroller;
 
-import com.android.launcher.R;
+import java.util.ArrayList;
+import java.util.HashMap;
 
 /**
  * An abstraction of the original Workspace which supports browsing through a
@@ -110,6 +110,9 @@
     protected boolean mAllowOverScroll = true;
     protected int mUnboundedScrollX;
 
+    // parameter that adjusts the layout to be optimized for CellLayouts with that scale factor
+    protected float mLayoutScale = 1.0f;
+
     protected static final int INVALID_POINTER = -1;
 
     protected int mActivePointerId = INVALID_POINTER;
@@ -268,7 +271,9 @@
         if (!mScroller.isFinished()) {
             mScroller.abortAnimation();
         }
-        if (getChildCount() == 0 || currentPage == mCurrentPage) {
+        // don't introduce any checks like mCurrentPage == currentPage here-- if we change the
+        // the default
+        if (getChildCount() == 0) {
             return;
         }
 
@@ -433,6 +438,44 @@
         setMeasuredDimension(widthSize, heightSize);
     }
 
+    protected void moveToNewPageWithoutMovingCellLayouts(int newCurrentPage) {
+        int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
+        int delta = newX - mScrollX;
+
+        final int screenCount = getChildCount();
+        for (int i = 0; i < screenCount; i++) {
+            CellLayout cl = (CellLayout) getChildAt(i);
+            cl.setX(cl.getX() + delta);
+        }
+        setCurrentPage(newCurrentPage);
+    }
+
+    // A layout scale of 1.0f assumes that the CellLayouts, in their unshrunken state, have a
+    // scale of 1.0f. A layout scale of 0.8f assumes the CellLayouts have a scale of 0.8f, and
+    // tightens the layout accordingly
+    public void setLayoutScale(float childrenScale) {
+        mLayoutScale = childrenScale;
+
+        // Now we need to do a re-layout, but preserving absolute X and Y coordinates
+        int childCount = getChildCount();
+        float childrenX[] = new float[childCount];
+        float childrenY[] = new float[childCount];
+        for (int i = 0; i < childCount; i++) {
+            final View child = getChildAt(i);
+            childrenX[i] = child.getX();
+            childrenY[i] = child.getY();
+        }
+        onLayout(false, mLeft, mTop, mRight, mBottom);
+        for (int i = 0; i < childCount; i++) {
+            final View child = getChildAt(i);
+            child.setX(childrenX[i]);
+            child.setY(childrenY[i]);
+        }
+        // Also, the page offset has changed  (since the pages are now smaller);
+        // update the page offset, but again preserving absolute X and Y coordinates
+        moveToNewPageWithoutMovingCellLayouts(mCurrentPage);
+    }
+
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
@@ -454,17 +497,21 @@
         for (int i = 0; i < childCount; i++) {
             final View child = getChildAt(i);
             if (child.getVisibility() != View.GONE) {
-                final int childWidth = child.getMeasuredWidth();
+                final int childWidth = getScaledMeasuredWidth(child);
                 final int childHeight = child.getMeasuredHeight();
                 int childTop = mPaddingTop;
                 if (mCenterPagesVertically) {
                     childTop += ((getMeasuredHeight() - verticalPadding) - childHeight) / 2;
                 }
+
                 child.layout(childLeft, childTop,
-                        childLeft + childWidth, childTop + childHeight);
+                        childLeft + child.getMeasuredWidth(), childTop + childHeight);
                 childLeft += childWidth + mPageSpacing;
             }
         }
+        if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
+            mFirstLayout = false;
+        }
     }
 
     protected void updateAdjacentPagesAlpha() {
@@ -475,7 +522,7 @@
                 final int childCount = getChildCount();
                 for (int i = 0; i < childCount; ++i) {
                     View layout = (View) getChildAt(i);
-                    int childWidth = layout.getMeasuredWidth();
+                    int childWidth = getScaledMeasuredWidth(layout);
                     int halfChildWidth = (childWidth / 2);
                     int childCenter = getChildOffset(i) + halfChildWidth;
 
@@ -491,11 +538,11 @@
                     int distanceFromScreenCenter = childCenter - screenCenter;
                     if (distanceFromScreenCenter > 0) {
                         if (i > 0) {
-                            d += getChildAt(i - 1).getMeasuredWidth() / 2;
+                            d += getScaledMeasuredWidth(getChildAt(i - 1)) / 2;
                         }
                     } else {
                         if (i < childCount - 1) {
-                            d += getChildAt(i + 1).getMeasuredWidth() / 2;
+                            d += getScaledMeasuredWidth(getChildAt(i + 1)) / 2;
                         }
                     }
                     d += mPageSpacing;
@@ -541,7 +588,7 @@
         // page.
         final int pageCount = getChildCount();
         if (pageCount > 0) {
-            final int pageWidth = getChildAt(0).getMeasuredWidth();
+            final int pageWidth = getScaledMeasuredWidth(getChildAt(0));
             final int screenWidth = getMeasuredWidth();
             int x = getRelativeChildOffset(0) + pageWidth;
             int leftScreen = 0;
@@ -551,7 +598,7 @@
                 x += pageWidth + mPageSpacing;
                 // replace above line with this if you don't assume all pages have same width as 0th
                 // page:
-                // x += getChildAt(leftScreen).getMeasuredWidth();
+                // x += getScaledMeasuredWidth(getChildAt(leftScreen));
             }
             rightScreen = leftScreen;
             while (x < mScrollX + screenWidth) {
@@ -560,7 +607,7 @@
                 // replace above line with this if you don't assume all pages have same width as 0th
                 // page:
                 //if (rightScreen < pageCount) {
-                //    x += getChildAt(rightScreen).getMeasuredWidth();
+                //    x += getScaledMeasuredWidth(getChildAt(rightScreen));
                 //}
             }
             rightScreen = Math.min(getChildCount() - 1, rightScreen);
@@ -1037,7 +1084,7 @@
         int right;
         for (int i = 0; i < childCount; ++i) {
             left = getRelativeChildOffset(i);
-            right = (left + getChildAt(i).getMeasuredWidth());
+            right = (left + getScaledMeasuredWidth(getChildAt(i)));
             if (left <= relativeOffset && relativeOffset <= right) {
                 return i;
             }
@@ -1055,11 +1102,15 @@
 
         int offset = getRelativeChildOffset(0);
         for (int i = 0; i < index; ++i) {
-            offset += getChildAt(i).getMeasuredWidth() + mPageSpacing;
+            offset += getScaledMeasuredWidth(getChildAt(i)) + mPageSpacing;
         }
         return offset;
     }
 
+    protected int getScaledMeasuredWidth(View child) {
+        return (int) (child.getMeasuredWidth() * mLayoutScale + 0.5f);
+    }
+
     int getPageNearestToCenterOfScreen() {
         int minDistanceFromScreenCenter = getMeasuredWidth();
         int minDistanceFromScreenCenterIndex = -1;
@@ -1067,7 +1118,7 @@
         final int childCount = getChildCount();
         for (int i = 0; i < childCount; ++i) {
             View layout = (View) getChildAt(i);
-            int childWidth = layout.getMeasuredWidth();
+            int childWidth = getScaledMeasuredWidth(layout);
             int halfChildWidth = (childWidth / 2);
             int childCenter = getChildOffset(i) + halfChildWidth;
             int distanceFromScreenCenter = Math.abs(childCenter - screenCenter);
diff --git a/src/com/android/launcher2/SpringLoadedDragController.java b/src/com/android/launcher2/SpringLoadedDragController.java
new file mode 100644
index 0000000..a734258
--- /dev/null
+++ b/src/com/android/launcher2/SpringLoadedDragController.java
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+public class SpringLoadedDragController implements OnAlarmListener {
+    // how long the user must hover over a mini-screen before it unshrinks
+    final long ENTER_SPRING_LOAD_HOVER_TIME = 1000;
+    final long EXIT_SPRING_LOAD_HOVER_TIME = 200;
+
+    Alarm mAlarm;
+
+    // the screen the user is currently hovering over, if any
+    private CellLayout mScreen;
+    private Launcher mLauncher;
+
+    public SpringLoadedDragController(Launcher launcher) {
+        mLauncher = launcher;
+        mAlarm = new Alarm();
+        mAlarm.setOnAlarmListener(this);
+    }
+
+    public void onDragEnter(CellLayout cl) {
+        mScreen = cl;
+        mAlarm.setAlarm(ENTER_SPRING_LOAD_HOVER_TIME);
+    }
+
+    public void onDragExit() {
+        if (mScreen != null) {
+            mScreen.onDragExit();
+        }
+        mScreen = null;
+        mAlarm.setAlarm(EXIT_SPRING_LOAD_HOVER_TIME);
+    }
+
+    // this is called when our timer runs out
+    public void onAlarm(Alarm alarm) {
+        if (mScreen != null) {
+            // we're currently hovering over a screen
+            mLauncher.enterSpringLoadedDragMode(mScreen);
+        } else {
+            mLauncher.exitSpringLoadedDragMode();
+        }
+    }
+}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 42dbc9a..b58faed 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -81,6 +81,9 @@
     // customization mode
     private static final float SHRINK_FACTOR = 0.16f;
 
+    // How much the screens shrink when we enter spring loaded drag mode
+    private static final float SPRING_LOADED_DRAG_SHRINK_FACTOR = 0.7f;
+
     // Y rotation to apply to the workspace screens
     private static final float WORKSPACE_ROTATION = 12.5f;
     private static final float WORKSPACE_TRANSLATION = 50.0f;
@@ -118,6 +121,7 @@
     private int mDefaultPage;
 
     private boolean mPageMoving = false;
+    private boolean mIsDragInProcess = false;
 
     /**
      * CellInfo for the cell that is currently being dragged
@@ -149,6 +153,8 @@
     private float[] mTempDragBottomRightCoordinates = new float[2];
     private Matrix mTempInverseMatrix = new Matrix();
 
+    private SpringLoadedDragController mSpringLoadedDragControllger;
+
     private static final int DEFAULT_CELL_COUNT_X = 4;
     private static final int DEFAULT_CELL_COUNT_Y = 4;
 
@@ -159,12 +165,12 @@
     // in all apps or customize mode)
     private boolean mIsSmall = false;
     private boolean mIsInUnshrinkAnimation = false;
-    private AnimatorListener mUnshrinkAnimationListener;
-    private enum ShrinkPosition {
-        SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM_HIDDEN, SHRINK_TO_BOTTOM_VISIBLE };
-    private ShrinkPosition mShrunkenState;
+    private AnimatorListener mShrinkAnimationListener, mUnshrinkAnimationListener;
+    enum ShrinkState { TOP, SPRING_LOADED, MIDDLE, BOTTOM_HIDDEN, BOTTOM_VISIBLE };
+    private ShrinkState mShrinkState;
+    private boolean mWasSpringLoadedOnDragExit = false;
     private boolean mWaitingToShrink = false;
-    private ShrinkPosition mWaitingToShrinkPosition;
+    private ShrinkState mWaitingToShrinkState;
     private AnimatorSet mAnimator;
 
     /** Is the user is dragging an item near the edge of a page? */
@@ -448,7 +454,7 @@
         // 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 (mShrunkenState != ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
+            if (mShrinkState != ShrinkState.BOTTOM_HIDDEN) {
                 mLauncher.onWorkspaceClick((CellLayout) v);
             }
             return true;
@@ -481,7 +487,7 @@
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (mIsSmall || mIsInUnshrinkAnimation) {
             if (mLauncher.isAllAppsVisible() &&
-                    mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
+                    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
                 return true;
@@ -678,7 +684,7 @@
         for (int i = 0; i < getChildCount(); i++) {
             CellLayout cl = (CellLayout) getChildAt(i);
             if (cl != null) {
-                int totalDistance = cl.getMeasuredWidth() + mPageSpacing;
+                int totalDistance = getScaledMeasuredWidth(cl) + mPageSpacing;
                 int delta = screenCenter - (getChildOffset(i) -
                         getRelativeChildOffset(i) + halfScreenSize);
 
@@ -721,7 +727,7 @@
         // if shrinkToBottom() is called on initialization, it has to be deferred
         // until after the first call to onLayout so that it has the correct width
         if (mWaitingToShrink) {
-            shrink(mWaitingToShrinkPosition, false);
+            shrink(mWaitingToShrinkState, false);
             mWaitingToShrink = false;
         }
 
@@ -876,7 +882,7 @@
             }
             setCurrentPage(mCurrentPage);
 
-            if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
+            if (mShrinkState == ShrinkState.BOTTOM_HIDDEN) {
                 mLauncher.showWorkspace(true);
                 // Let the events fall through to the CellLayouts because if they are not
                 // hit, then we get a crash due to a missing ACTION_DOWN touch event
@@ -907,30 +913,6 @@
         return mIsSmall;
     }
 
-    void shrinkToTop(boolean animated) {
-        shrink(ShrinkPosition.SHRINK_TO_TOP, animated);
-    }
-
-    void shrinkToMiddle() {
-        shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true);
-    }
-
-    void shrinkToBottomHidden() {
-        shrinkToBottomHidden(true);
-    }
-
-    void shrinkToBottomVisible() {
-        shrinkToBottomVisible(true);
-    }
-
-    void shrinkToBottomHidden(boolean animated) {
-        shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, animated);
-    }
-
-    void shrinkToBottomVisible(boolean animated) {
-        shrink(ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE, animated);
-    }
-
     private float getYScaleForScreen(int screen) {
         int x = Math.abs(screen - 2);
 
@@ -943,24 +925,29 @@
         return 1.0f;
     }
 
-    // we use this to shrink the workspace for the all apps view and the customize view
-    private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
+    public void shrink(ShrinkState shrinkState) {
+        shrink(shrinkState, true);
+    }
 
+    // we use this to shrink the workspace for the all apps view and the customize view
+    public void shrink(ShrinkState shrinkState, boolean animated) {
         if (mFirstLayout) {
             // (mFirstLayout == "first layout has not happened yet")
             // if we get a call to shrink() as part of our initialization (for example, if
             // Launcher is started in All Apps mode) then we need to wait for a layout call
             // to get our width so we can layout the mini-screen views correctly
             mWaitingToShrink = true;
-            mWaitingToShrinkPosition = shrinkPosition;
+            mWaitingToShrinkState = shrinkState;
             return;
         }
         mIsSmall = true;
-        mShrunkenState = shrinkPosition;
+        mShrinkState = shrinkState;
 
         // Stop any scrolling, move to the current page right away
         setCurrentPage((mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage);
-        updateWhichPagesAcceptDrops(mShrunkenState);
+        if (!mIsDragInProcess) {
+            updateWhichPagesAcceptDrops(mShrinkState);
+        }
 
         // we intercept and reject all touch events when we're small, so be sure to reset the state
         mTouchState = TOUCH_STATE_REST;
@@ -993,18 +980,18 @@
                 getResources().getDimension(R.dimen.allAppsSmallScreenVerticalMarginLandscape));
         float finalAlpha = 1.0f;
         float extraShrinkFactor = 1.0f;
-        if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
+        if (shrinkState == ShrinkState.BOTTOM_VISIBLE) {
              newY = screenHeight - newY - scaledPageHeight;
-        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
+        } else if (shrinkState == ShrinkState.BOTTOM_HIDDEN) {
 
             // We shrink and disappear to nothing in the case of all apps
             // (which is when we shrink to the bottom)
             newY = screenHeight - newY - scaledPageHeight;
             finalAlpha = 0.0f;
-        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) {
+        } else if (shrinkState == ShrinkState.MIDDLE) {
             newY = screenHeight / 2 - scaledPageHeight / 2;
             finalAlpha = 1.0f;
-        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_TOP) {
+        } else if (shrinkState == ShrinkState.TOP) {
             newY = (isPortrait ?
                 getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginPortrait) :
                 getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginLandscape));
@@ -1061,12 +1048,13 @@
             // increment newX for the next screen
             newX += scaledPageWidth + extraScaledSpacing;
         }
+        setLayoutScale(1.0f);
         if (animated) {
             mAnimator.start();
         }
         setChildrenDrawnWithCacheEnabled(true);
 
-        if (shrinkPosition == ShrinkPosition.SHRINK_TO_TOP) {
+        if (shrinkState == ShrinkState.TOP) {
             showBackgroundGradientForCustomizeTray();
         } else {
             showBackgroundGradient();
@@ -1132,30 +1120,30 @@
     private final ZoomOutInterpolator mZoomOutInterpolator = new ZoomOutInterpolator();
     private final ZoomInInterpolator mZoomInInterpolator = new ZoomInInterpolator();
 
-    private void updateWhichPagesAcceptDrops(ShrinkPosition state) {
+    private void updateWhichPagesAcceptDrops(ShrinkState state) {
         updateWhichPagesAcceptDropsHelper(state, false, 1, 1);
     }
 
-    private void updateWhichPagesAcceptDropsDuringDrag(ShrinkPosition state, int spanX, int spanY) {
+    private void updateWhichPagesAcceptDropsDuringDrag(ShrinkState state, int spanX, int spanY) {
         updateWhichPagesAcceptDropsHelper(state, true, spanX, spanY);
     }
 
     private void updateWhichPagesAcceptDropsHelper(
-            ShrinkPosition state, boolean isDragHappening, int spanX, int spanY) {
+            ShrinkState state, boolean isDragHappening, int spanX, int spanY) {
         final int screenCount = getChildCount();
         for (int i = 0; i < screenCount; i++) {
             CellLayout cl = (CellLayout) getChildAt(i);
 
             switch (state) {
-                case SHRINK_TO_TOP:
+                case TOP:
                     if (!isDragHappening) {
                         boolean showDropHighlight = i == mCurrentPage;
                         cl.setAcceptsDrops(showDropHighlight);
                         break;
                     }
                     // otherwise, fall through below and mark non-full screens as accepting drops
-                case SHRINK_TO_BOTTOM_HIDDEN:
-                case SHRINK_TO_BOTTOM_VISIBLE:
+                case BOTTOM_HIDDEN:
+                case BOTTOM_VISIBLE:
                     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
@@ -1167,7 +1155,7 @@
                     break;
                 default:
                      throw new RuntimeException(
-                             "updateWhichPagesAcceptDropsHelper passed an unhandled ShrinkPosition");
+                             "updateWhichPagesAcceptDropsHelper passed an unhandled ShrinkState");
             }
         }
     }
@@ -1181,19 +1169,25 @@
      * appearance).
      *
      */
-    public void onDragStartedWithItemSpans(int spanX, int spanY) {
-        updateWhichPagesAcceptDropsDuringDrag(mShrunkenState, spanX, spanY);
-    }
+    public void onDragStartedWithItemSpans(int spanX, int spanY, Bitmap b) {
+        mIsDragInProcess = true;
 
-    public void onDragStartedWithItemMinSize(int minWidth, int minHeight) {
-        int[] spanXY = CellLayout.rectToCell(getResources(), minWidth, minHeight, null);
-        onDragStartedWithItemSpans(spanXY[0], spanXY[1]);
+        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.OUTER_BLUR_RADIUS;
+
+        // The outline is used to visualize where the item will land if dropped
+        mDragOutline = createDragOutline(b, canvas, bitmapPadding);
+
+        updateWhichPagesAcceptDropsDuringDrag(mShrinkState, spanX, spanY);
     }
 
     // we call this method whenever a drag and drop in Launcher finishes, even if Workspace was
     // never dragged over
     public void onDragStopped() {
-        updateWhichPagesAcceptDrops(mShrunkenState);
+        mIsDragInProcess = false;
+        updateWhichPagesAcceptDrops(mShrinkState);
     }
 
     @Override
@@ -1203,28 +1197,48 @@
 
     // We call this when we trigger an unshrink by clicking on the CellLayout cl
     public void unshrink(CellLayout clThatWasClicked) {
+        unshrink(clThatWasClicked, false);
+    }
+
+    public void unshrink(CellLayout clThatWasClicked, boolean springLoaded) {
         int newCurrentPage = indexOfChild(clThatWasClicked);
         if (mIsSmall) {
-            int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
-            int delta = newX - mScrollX;
-
-            final int screenCount = getChildCount();
-            for (int i = 0; i < screenCount; i++) {
-                CellLayout cl = (CellLayout) getChildAt(i);
-                cl.setX(cl.getX() + delta);
+            if (springLoaded) {
+                setLayoutScale(SPRING_LOADED_DRAG_SHRINK_FACTOR);
             }
-            setCurrentPage(newCurrentPage);
-            unshrink();
+            moveToNewPageWithoutMovingCellLayouts(newCurrentPage);
+            unshrink(true, springLoaded);
         }
     }
 
-    void unshrink() {
-        unshrink(true);
+
+    public void enterSpringLoadedDragMode(CellLayout clThatWasClicked) {
+        mShrinkState = ShrinkState.SPRING_LOADED;
+        unshrink(clThatWasClicked, true);
+        mDragTargetLayout.onDragEnter();
+    }
+
+    public void exitSpringLoadedDragMode(ShrinkState shrinkState) {
+        shrink(shrinkState);
+        if (mDragTargetLayout != null) {
+            mDragTargetLayout.onDragExit();
+        }
     }
 
     void unshrink(boolean animated) {
+        unshrink(animated, false);
+    }
+
+    void unshrink(boolean animated, boolean springLoaded) {
         if (mIsSmall) {
-            mIsSmall = false;
+            float finalScaleFactor = 1.0f;
+            float finalBackgroundAlpha = 0.0f;
+            if (springLoaded) {
+                finalScaleFactor = SPRING_LOADED_DRAG_SHRINK_FACTOR;
+                finalBackgroundAlpha = 1.0f;
+            } else {
+                mIsSmall = false;
+            }
             if (mAnimator != null) {
                 mAnimator.cancel();
             }
@@ -1250,9 +1264,9 @@
                     ObjectAnimator animWithInterpolator = ObjectAnimator.ofPropertyValuesHolder(cl,
                             PropertyValuesHolder.ofFloat("translationX", translation),
                             PropertyValuesHolder.ofFloat("translationY", 0.0f),
-                            PropertyValuesHolder.ofFloat("scaleX", 1.0f),
-                            PropertyValuesHolder.ofFloat("scaleY", 1.0f),
-                            PropertyValuesHolder.ofFloat("backgroundAlpha", 0.0f),
+                            PropertyValuesHolder.ofFloat("scaleX", finalScaleFactor),
+                            PropertyValuesHolder.ofFloat("scaleY", finalScaleFactor),
+                            PropertyValuesHolder.ofFloat("backgroundAlpha", finalBackgroundAlpha),
                             PropertyValuesHolder.ofFloat("alpha", finalAlphaValue),
                             PropertyValuesHolder.ofFloat("rotationY", rotation));
                     animWithInterpolator.setDuration(duration);
@@ -1261,8 +1275,8 @@
                 } else {
                     cl.setTranslationX(translation);
                     cl.setTranslationY(0.0f);
-                    cl.setScaleX(1.0f);
-                    cl.setScaleY(1.0f);
+                    cl.setScaleX(finalScaleFactor);
+                    cl.setScaleY(finalScaleFactor);
                     cl.setBackgroundAlpha(0.0f);
                     cl.setAlpha(finalAlphaValue);
                     cl.setRotationY(rotation);
@@ -1329,6 +1343,22 @@
     }
 
     /**
+     * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
+     * Responsibility for the bitmap is transferred to the caller.
+     */
+    private Bitmap createDragOutline(Bitmap orig, Canvas canvas, int padding) {
+        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
+        final Bitmap b = Bitmap.createBitmap(
+                orig.getWidth() + padding, orig.getHeight() + padding, Bitmap.Config.ARGB_8888);
+
+        canvas.setBitmap(b);
+        canvas.drawBitmap(orig, 0, 0, new Paint());
+        mOutlineHelper.applyMediumExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor);
+
+        return b;
+    }
+
+    /**
      * Creates a drag outline to represent a drop (that we don't have the actual information for
      * yet).  May be changed in the future to alter the drop outline slightly depending on the
      * clip description mime data.
@@ -1549,12 +1579,12 @@
         }
 
         if (source != this) {
-            if (mIsSmall) {
+            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);
-            } else {
-                onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
+                onDropExternal(-1, -1, dragInfo, mDragTargetLayout, false);
             }
         } else if (mDragInfo != null) {
             final View cell = mDragInfo.cell;
@@ -1611,7 +1641,8 @@
             // 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);
-            parent.onDropChild(cell);
+            boolean animateDrop = !mWasSpringLoadedOnDragExit;
+            parent.onDropChild(cell, animateDrop);
         }
     }
 
@@ -1764,7 +1795,7 @@
                 if (isShortcut) {
                     final Intent intent = data.getItem(index).getIntent();
                     Object info = model.infoFromShortcutIntent(mContext, intent, data.getIcon());
-                    onDropExternal(x, y, info, layout);
+                    onDropExternal(x, y, info, layout, false);
                 } else {
                     if (widgets.size() == 1) {
                         // If there is only one item, then go ahead and add and configure
@@ -1953,21 +1984,34 @@
             CellLayout layout;
             int originX = x - xOffset;
             int originY = y - yOffset;
-            if (mIsSmall || mIsInUnshrinkAnimation) {
+            boolean shrunken = mIsSmall || mIsInUnshrinkAnimation;
+            if (shrunken) {
                 layout = findMatchingPageForDragOver(
                         dragView, originX, originY, xOffset, yOffset);
 
                 if (layout != mDragTargetLayout) {
                     if (mDragTargetLayout != null) {
                         mDragTargetLayout.setHover(false);
+                        mSpringLoadedDragControllger.onDragExit();
                     }
                     mDragTargetLayout = layout;
                     if (mDragTargetLayout != null && mDragTargetLayout.getAcceptsDrops()) {
                         mDragTargetLayout.setHover(true);
+                        mSpringLoadedDragControllger.onDragEnter(mDragTargetLayout);
                     }
                 }
             } else {
                 layout = getCurrentDropLayout();
+                if (layout != mDragTargetLayout) {
+                    if (mDragTargetLayout != null) {
+                        mDragTargetLayout.onDragExit();
+                    }
+                    layout.onDragEnter();
+                    mDragTargetLayout = layout;
+                }
+            }
+            if (!shrunken || mShrinkState == ShrinkState.SPRING_LOADED) {
+                layout = getCurrentDropLayout();
 
                 final ItemInfo item = (ItemInfo)dragInfo;
                 if (dragInfo instanceof LauncherAppWidgetInfo) {
@@ -1998,23 +2042,12 @@
                     }
                 }
 
-                if (layout != mDragTargetLayout) {
-                    if (mDragTargetLayout != null) {
-                        mDragTargetLayout.onDragExit();
-                    }
-                    layout.onDragEnter();
-                    mDragTargetLayout = layout;
-                }
-
-                // only visualize the drop locations for moving icons within the home screen on
-                // tablet on phone, we also visualize icons dragged in from All Apps
-                if ((!LauncherApplication.isScreenXLarge() || source == this)
-                        && mDragTargetLayout != null) {
+                if (mDragTargetLayout != null) {
                     final View child = (mDragInfo == null) ? null : mDragInfo.cell;
-                    int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
-                    int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
+                    float[] localOrigin = { originX, originY };
+                    mapPointFromSelfToChild(mDragTargetLayout, localOrigin, null);
                     mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
-                            localOriginX, localOriginY, item.spanX, item.spanY);
+                            (int) localOrigin[0], (int) localOrigin[1], item.spanX, item.spanY);
                 }
             }
         }
@@ -2022,20 +2055,19 @@
 
     public void onDragExit(DragSource source, int x, int y, int xOffset,
             int yOffset, DragView dragView, Object dragInfo) {
+        mWasSpringLoadedOnDragExit = mShrinkState == ShrinkState.SPRING_LOADED;
         if (mDragTargetLayout != null) {
             mDragTargetLayout.onDragExit();
         }
         if (!mIsPageMoving) {
             hideOutlines();
         }
+        if (mShrinkState == ShrinkState.SPRING_LOADED) {
+            mLauncher.exitSpringLoadedDragMode();
+        }
         clearAllHovers();
     }
 
-    private void onDropExternal(int x, int y, Object dragInfo,
-            CellLayout cellLayout) {
-        onDropExternal(x, y, dragInfo, cellLayout, false);
-    }
-
     @Override
     public void getHitRect(Rect outRect) {
         // We want the workspace to have the whole area of the display (it will find the correct
@@ -2046,25 +2078,25 @@
 
     /**
      * Add the item specified by dragInfo to the given layout.
-     * This is basically the equivalent of onDropExternal, except it's not initiated
-     * by drag and drop.
      * @return true if successful
      */
-    public boolean addExternalItemToScreen(Object dragInfo, View layout) {
-        CellLayout cl = (CellLayout) layout;
-        ItemInfo info = (ItemInfo) dragInfo;
-
-        if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
-            onDropExternal(-1, -1, dragInfo, cl, false);
+    public boolean addExternalItemToScreen(ItemInfo dragInfo, CellLayout layout) {
+        if (layout.findCellForSpan(mTempEstimate, dragInfo.spanX, dragInfo.spanY)) {
+            onDropExternal(-1, -1, (ItemInfo) dragInfo, (CellLayout) layout, false);
             return true;
         }
         mLauncher.showOutOfSpaceMessage();
         return false;
     }
 
-    // Drag from somewhere else
-    // 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.
+    /**
+     * 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
+     * come from another app altogether.
+     *
+     * 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) {
         int screen = indexOfChild(cellLayout);
@@ -2090,11 +2122,9 @@
                     throw new IllegalStateException("Unknown item type: " + info.itemType);
             }
             cellLayout.onDragExit();
-            cellLayout.animateDrop();
         } else {
             // This is for other drag/drop cases, like dragging from All Apps
             ItemInfo info = (ItemInfo) dragInfo;
-
             View view = null;
 
             switch (info.itemType) {
@@ -2124,7 +2154,8 @@
             }
             addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
                     mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
-            cellLayout.onDropChild(view);
+            boolean animateDrop = !mWasSpringLoadedOnDragExit;
+            cellLayout.onDropChild(view, animateDrop);
             cellLayout.animateDrop();
             CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
 
@@ -2178,6 +2209,7 @@
 
     void setLauncher(Launcher launcher) {
         mLauncher = launcher;
+        mSpringLoadedDragControllger = new SpringLoadedDragController(mLauncher);
     }
 
     public void setDragController(DragController dragController) {
@@ -2195,7 +2227,8 @@
                 // final Object tag = mDragInfo.cell.getTag();
             }
         } else if (mDragInfo != null) {
-            ((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell);
+            boolean animateDrop = !mWasSpringLoadedOnDragExit;
+            ((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell, animateDrop);
         }
 
         mDragOutline = null;
@@ -2256,6 +2289,7 @@
         for (int i = 0; i < childCount; i++) {
             ((CellLayout) getChildAt(i)).setHover(false);
         }
+        mSpringLoadedDragControllger.onDragExit();
     }
 
     @Override