am 004f9d77: set up fast-forward from froyo-release to gingerbread

Merge commit '004f9d772ce44a95111e38e9a447074b090b37f9'

* commit '004f9d772ce44a95111e38e9a447074b090b37f9':
  Filter input events and smooth out touch scrolling. Bug 2639807
  Fix proguard flags.
  Sort apps in AllApps3D.setApps().
  Launcher2 performance: Don't sort apps in LauncherModel.
  resolve conflicts
  Bug 2509023 - NPE on upgrade to froyo
  Unbind root script around load activities to prevent commands from being delayed due to swap buffers.
  Fix 2507267 - stack overflow when adding shortcut
diff --git a/res/anim/widget_chooser_slide_up.xml b/res/anim/widget_chooser_slide_up.xml
new file mode 100644
index 0000000..b43ec36
--- /dev/null
+++ b/res/anim/widget_chooser_slide_up.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<translate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fromXDelta="0%p"
+    android:toXDelta="0%p"
+    android:fromYDelta="100%p"
+    android:toYDelta="0%p"
+
+    android:duration="500"
+    android:fillAfter="true" />
diff --git a/res/drawable/add_button.png b/res/drawable/add_button.png
new file mode 100644
index 0000000..0edcfa3
--- /dev/null
+++ b/res/drawable/add_button.png
Binary files differ
diff --git a/res/layout-xlarge/launcher.xml b/res/layout-xlarge/launcher.xml
new file mode 100644
index 0000000..092e018
--- /dev/null
+++ b/res/layout-xlarge/launcher.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<com.android.launcher2.DragLayer
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
+
+    android:id="@+id/drag_layer"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <include layout="@layout/all_apps" />
+
+    <!-- The workspace contains 5 screens of cells -->
+    <com.android.launcher2.Workspace
+        android:id="@+id/workspace"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        launcher:defaultScreen="2">
+
+        <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
+        <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
+        <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
+        <include android:id="@+id/cell4" layout="@layout/workspace_screen" />
+        <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
+
+    </com.android.launcher2.Workspace>
+
+    <com.android.launcher2.DeleteZone
+        android:id="@+id/delete_zone"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingTop="@dimen/delete_zone_padding"
+        android:layout_gravity="top|right"
+
+        android:scaleType="center"
+        android:src="@drawable/delete_zone_selector"
+        android:visibility="gone"
+        launcher:direction="horizontal"
+        />
+    <ImageView
+        android:id="@+id/add_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingTop="@dimen/delete_zone_padding"
+        android:layout_gravity="top|right"
+
+        android:scaleType="center"
+        android:src="@drawable/add_button"
+
+        android:onClick="onClickAddButton"
+        android:focusable="true"
+        android:clickable="true" />
+
+    <RelativeLayout
+        android:id="@+id/all_apps_button_cluster"
+        android:layout_width="@dimen/button_bar_height"
+        android:layout_height="@dimen/button_bar_height"
+        android:layout_gravity="top|left"
+        android:paddingTop="2dip"
+        >
+       <com.android.launcher2.HandleView
+           style="@style/HotseatButton"
+           android:id="@+id/all_apps_button"
+           android:layout_centerHorizontal="true"
+           android:layout_alignParentBottom="true"
+
+           android:src="@drawable/all_apps_button"
+           launcher:direction="horizontal"
+           />
+    </RelativeLayout>
+    <com.android.launcher2.WidgetChooser
+        android:id="@+id/widget_chooser"
+        android:layout_width="match_parent"
+        android:layout_height="100dip"
+        android:layout_gravity="bottom"
+        android:visibility="gone"
+        />
+</com.android.launcher2.DragLayer>
diff --git a/res/layout/widget_item.xml b/res/layout/widget_item.xml
new file mode 100644
index 0000000..c79bd31
--- /dev/null
+++ b/res/layout/widget_item.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:background="?android:attr/galleryItemBackground"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:scaleType="fitXY"
+    android:focusable="true" />
diff --git a/res/raw/allapps.rs b/res/raw/allapps.rs
index af5abd3..1465308 100644
--- a/res/raw/allapps.rs
+++ b/res/raw/allapps.rs
@@ -1,50 +1,78 @@
 #pragma version(1)
-#pragma stateVertex(PV)
-#pragma stateFragment(PFTexNearest)
-#pragma stateStore(PSIcons)
+
+#pragma rs java_package_name(com.android.launcher2)
+
+#include "../../../../../frameworks/base/libs/rs/scriptc/rs_types.rsh"
+#include "../../../../../frameworks/base/libs/rs/scriptc/rs_math.rsh"
+#include "../../../../../frameworks/base/libs/rs/scriptc/rs_graphics.rsh"
 
 #define PI 3.14159f
 
-int g_SpecialHWWar;
+// Constants from Java
+int COLUMNS_PER_PAGE_PORTRAIT;
+int ROWS_PER_PAGE_PORTRAIT;
+int COLUMNS_PER_PAGE_LANDSCAPE;
+int ROWS_PER_PAGE_LANDSCAPE;
+
+int gIconCount;
+int gSelectedIconIndex = -1;
+rs_allocation gSelectedIconTexture;
+rs_allocation gHomeButton;
+
+rs_program_fragment gPFTexNearest;
+rs_program_fragment gPFTexMip;
+rs_program_fragment gPFTexMipAlpha;
+rs_program_vertex gPVCurve;
+rs_program_store gPS;
+rs_mesh gSMCell;
+
+rs_allocation *gIconIDs;
+rs_allocation *gLabelIDs;
+
+typedef struct VpConsts {
+    float4 Position;
+    float4 ScaleOffset;
+    float2 BendPos;
+    float2 ImgSize;
+} VpConsts_t;
+VpConsts_t *vpConstants;
+
+
+#pragma rs export_var(COLUMNS_PER_PAGE_PORTRAIT, ROWS_PER_PAGE_PORTRAIT, COLUMNS_PER_PAGE_LANDSCAPE, ROWS_PER_PAGE_LANDSCAPE, gIconCount, gSelectedIconIndex, gSelectedIconTexture, gHomeButton, gTargetPos, gPFTexNearest, gPFTexMip, gPFTexMipAlpha, gPVCurve, gPS, gSMCell, gIconIDs, gLabelIDs, vpConstants)
+#pragma rs export_func(move, moveTo, setZoom, fling)
+
 
 // Attraction to center values from page edge to page center.
-float g_AttractionTable[9];
-float g_FrictionTable[9];
-float g_PhysicsTableSize;
+static float g_AttractionTable[9] = {20.f, 20.f, 20.f, 10.f, -10.f, -20.f, -20.f, -20.f, -20.f};
+static float g_FrictionTable[9] = {10.f, 10.f, 11.f, 15.f, 15.f, 11.f, 10.f, 10.f, 10.f};
+static float g_PhysicsTableSize = 7;
 
-float g_PosPage;
-float g_PosVelocity;
-float g_LastPositionX;
-int g_LastTouchDown;
-float g_DT;
-int g_LastTime;
-int g_PosMax;
-float g_Zoom;
-float g_Animation;
-float g_OldPosPage;
-float g_OldPosVelocity;
-float g_OldZoom;
-float g_MoveToTotalTime;
-float g_MoveToTime;
-float g_MoveToOldPos;
+static float gZoomTarget;
+static float gTargetPos;
+static float g_PosPage = 0.f;
+static float g_PosVelocity = 0.f;
+static float g_LastPositionX = 0.f;
+static bool g_LastTouchDown = false;
+static float g_DT;
+static int64_t g_LastTime;
+static int g_PosMax;
+static float g_Zoom = 0.f;
+static float g_Animation = 1.f;
+static float g_OldPosPage;
+static float g_OldPosVelocity;
+static float g_OldZoom;
+static float g_MoveToTotalTime = 0.2f;
+static float g_MoveToTime = 0.f;
+static float g_MoveToOldPos = 0.f;
 
-int g_Cols;
-int g_Rows;
+static int g_Cols;
+static int g_Rows;
 
 // Drawing constants, should be parameters ======
 #define VIEW_ANGLE 1.28700222f
 
-int g_DrawLastFrame;
-int lastFrame(int draw) {
-    // We draw one extra frame to work around the last frame post bug.
-    // We also need to track if we drew the last frame to deal with large DT
-    // in the physics.
-    int ret = g_DrawLastFrame | draw;
-    g_DrawLastFrame = draw;
-    return ret;  // should return draw instead.
-}
 
-void updateReadback() {
+static void updateReadback() {
     if ((g_OldPosPage != g_PosPage) ||
         (g_OldPosVelocity != g_PosVelocity) ||
         (g_OldZoom != g_Zoom)) {
@@ -57,92 +85,55 @@
         i[0] = g_PosPage * (1 << 16);
         i[1] = g_PosVelocity * (1 << 16);
         i[2] = g_OldZoom * (1 << 16);
-        sendToClient(&i[0], 1, 12, 1);
-    }
-}
-
-void setColor(float r, float g, float b, float a) {
-    if (g_SpecialHWWar) {
-        color(0, 0, 0, 0.001f);
-    } else {
-        color(r, g, b, a);
+        rsSendToClient(&i[0], 1, 12, 1);
     }
 }
 
 void init() {
-    g_AttractionTable[0] = 20.0f;
-    g_AttractionTable[1] = 20.0f;
-    g_AttractionTable[2] = 20.0f;
-    g_AttractionTable[3] = 10.0f;
-    g_AttractionTable[4] = -10.0f;
-    g_AttractionTable[5] = -20.0f;
-    g_AttractionTable[6] = -20.0f;
-    g_AttractionTable[7] = -20.0f;
-    g_AttractionTable[8] = -20.0f;  // dup 7 to avoid a clamp later
-    g_FrictionTable[0] = 10.0f;
-    g_FrictionTable[1] = 10.0f;
-    g_FrictionTable[2] = 11.0f;
-    g_FrictionTable[3] = 15.0f;
-    g_FrictionTable[4] = 15.0f;
-    g_FrictionTable[5] = 11.0f;
-    g_FrictionTable[6] = 10.0f;
-    g_FrictionTable[7] = 10.0f;
-    g_FrictionTable[8] = 10.0f;  // dup 7 to avoid a clamp later
-    g_PhysicsTableSize = 7;
-
-    g_PosVelocity = 0;
-    g_PosPage = 0;
-    g_LastTouchDown = 0;
-    g_LastPositionX = 0;
-    g_Zoom = 0;
-    g_Animation = 1.f;
-    g_SpecialHWWar = 1;
-    g_MoveToTime = 0;
-    g_MoveToOldPos = 0;
-    g_MoveToTotalTime = 0.2f; // Duration of scrolling 1 line
 }
 
-void resetHWWar() {
-    g_SpecialHWWar = 1;
-}
-
-void move() {
+void move(float newPos) {
     if (g_LastTouchDown) {
-        float dx = -(state->newPositionX - g_LastPositionX);
+        float dx = -(newPos - g_LastPositionX);
         g_PosVelocity = 0;
         g_PosPage += dx * 5.2f;
 
         float pmin = -0.49f;
         float pmax = g_PosMax + 0.49f;
-        g_PosPage = clampf(g_PosPage, pmin, pmax);
+        g_PosPage = clamp(g_PosPage, pmin, pmax);
     }
-    g_LastTouchDown = state->newTouchDown;
-    g_LastPositionX = state->newPositionX;
+    g_LastTouchDown = true;
+    g_LastPositionX = newPos;
     g_MoveToTime = 0;
-    //debugF("Move P", g_PosPage);
 }
 
-void moveTo() {
+void moveTo(float targetPos) {
+    gTargetPos = targetPos;
     g_MoveToTime = g_MoveToTotalTime;
     g_PosVelocity = 0;
     g_MoveToOldPos = g_PosPage;
-
-	// debugF("======= moveTo", state->targetPos);
 }
 
-void setZoom() {
-    g_Zoom = state->zoomTarget;
-    g_DrawLastFrame = 1;
+void setZoom(float z, /*bool*/ int animate) {
+    gZoomTarget = z;
+    if (gZoomTarget < 0.001f) {
+        gZoomTarget = 0;
+    }
+    if (!animate) {
+        g_Zoom = gZoomTarget;
+    }
     updateReadback();
 }
 
-void fling() {
-    g_LastTouchDown = 0;
-    g_PosVelocity = -state->flingVelocity * 4;
-    float av = fabsf(g_PosVelocity);
+void fling(float newPos, float vel) {
+    move(newPos);
+
+    g_LastTouchDown = false;
+    g_PosVelocity = -vel * 4;
+    float av = fabs(g_PosVelocity);
     float minVel = 3.5f;
 
-    minVel *= 1.f - (fabsf(fracf(g_PosPage + 0.5f) - 0.5f) * 0.45f);
+    minVel *= 1.f - (fabs(rsFrac(g_PosPage + 0.5f) - 0.5f) * 0.45f);
 
     if (av < minVel && av > 0.2f) {
         if (g_PosVelocity > 0) {
@@ -153,81 +144,71 @@
     }
 
     if (g_PosPage <= 0) {
-        g_PosVelocity = maxf(0, g_PosVelocity);
+        g_PosVelocity = max(0.f, g_PosVelocity);
     }
     if (g_PosPage > g_PosMax) {
-        g_PosVelocity = minf(0, g_PosVelocity);
+        g_PosVelocity = min(0.f, g_PosVelocity);
     }
 }
 
-float
-modf(float x, float y)
-{
-    return x-(y*floorf(x/y));
+// Interpolates values in the range 0..1 to a curve that eases in
+// and out.
+static float getInterpolation(float input) {
+    return (cos((input + 1) * PI) * 0.5f) + 0.5f;
 }
 
 
-/*
- * Interpolates values in the range 0..1 to a curve that eases in
- * and out.
- */
-float
-getInterpolation(float input) {
-    return (cosf((input + 1) * PI) / 2.0f) + 0.5f;
-}
-
-
-void updatePos() {
+static void updatePos() {
     if (g_LastTouchDown) {
         return;
     }
 
-    float tablePosNorm = fracf(g_PosPage + 0.5f);
+    float tablePosNorm = rsFrac(g_PosPage + 0.5f);
     float tablePosF = tablePosNorm * g_PhysicsTableSize;
     int tablePosI = tablePosF;
     float tablePosFrac = tablePosF - tablePosI;
-    float accel = lerpf(g_AttractionTable[tablePosI],
+    float accel = mix(g_AttractionTable[tablePosI],
                         g_AttractionTable[tablePosI + 1],
                         tablePosFrac) * g_DT;
-    float friction = lerpf(g_FrictionTable[tablePosI],
+    float friction = mix(g_FrictionTable[tablePosI],
                         g_FrictionTable[tablePosI + 1],
                         tablePosFrac) * g_DT;
 
     if (g_MoveToTime) {
         // New position is old posiition + (total distance) * (interpolated time)
-        g_PosPage = g_MoveToOldPos + (state->targetPos - g_MoveToOldPos) * getInterpolation((g_MoveToTotalTime - g_MoveToTime) / g_MoveToTotalTime);
+        g_PosPage = g_MoveToOldPos + (gTargetPos - g_MoveToOldPos) * getInterpolation((g_MoveToTotalTime - g_MoveToTime) / g_MoveToTotalTime);
         g_MoveToTime -= g_DT;
         if (g_MoveToTime <= 0) {
             g_MoveToTime = 0;
-            g_PosPage = state->targetPos;
+            g_PosPage = gTargetPos;
         }
         return;
     }
 
     // If our velocity is low OR acceleration is opposing it, apply it.
-    if (fabsf(g_PosVelocity) < 4.0f || (g_PosVelocity * accel) < 0) {
+    if (fabs(g_PosVelocity) < 4.0f || (g_PosVelocity * accel) < 0) {
         g_PosVelocity += accel;
     }
-    //debugF("g_PosPage", g_PosPage);
-    //debugF("  g_PosVelocity", g_PosVelocity);
-    //debugF("  friction", friction);
-    //debugF("  accel", accel);
+    //RS_DEBUG(g_PosPage);
+    //RS_DEBUG(g_PosVelocity);
+    //RS_DEBUG(friction);
+    //RS_DEBUG(accel);
 
     // Normal physics
     if (g_PosVelocity > 0) {
         g_PosVelocity -= friction;
-        g_PosVelocity = maxf(g_PosVelocity, 0);
+        g_PosVelocity = max(g_PosVelocity, 0.f);
     } else {
         g_PosVelocity += friction;
-        g_PosVelocity = minf(g_PosVelocity, 0);
+        g_PosVelocity = min(g_PosVelocity, 0.f);
     }
 
-    if ((friction > fabsf(g_PosVelocity)) && (friction > fabsf(accel))) {
+    if ((friction > fabs(g_PosVelocity)) && (friction > fabs(accel))) {
         // Special get back to center and overcome friction physics.
         float t = tablePosNorm - 0.5f;
-        if (fabsf(t) < (friction * g_DT)) {
+        if (fabs(t) < (friction * g_DT)) {
             // really close, just snap
-            g_PosPage = roundf(g_PosPage);
+            g_PosPage = round(g_PosPage);
             g_PosVelocity = 0;
         } else {
             if (t > 0) {
@@ -240,52 +221,53 @@
 
     // Check for out of boundry conditions.
     if (g_PosPage < 0 && g_PosVelocity < 0) {
-        float damp = 1.0 + (g_PosPage * 4);
-        damp = clampf(damp, 0.f, 0.9f);
+        float damp = 1.0f + (g_PosPage * 4);
+        damp = clamp(damp, 0.f, 0.9f);
         g_PosVelocity *= damp;
     }
     if (g_PosPage > g_PosMax && g_PosVelocity > 0) {
-        float damp = 1.0 - ((g_PosPage - g_PosMax) * 4);
-        damp = clampf(damp, 0.f, 0.9f);
+        float damp = 1.0f - ((g_PosPage - g_PosMax) * 4);
+        damp = clamp(damp, 0.f, 0.9f);
         g_PosVelocity *= damp;
     }
 
     g_PosPage += g_PosVelocity * g_DT;
-    g_PosPage = clampf(g_PosPage, -0.49, g_PosMax + 0.49);
+    g_PosPage = clamp(g_PosPage, -0.49f, g_PosMax + 0.49f);
 }
 
-
-void
+static void
 draw_home_button()
 {
-    setColor(1.0f, 1.0f, 1.0f, 1.0f);
-    bindTexture(NAMED_PFTexNearest, 0, state->homeButtonId);
+    color(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgBindTexture(gPFTexNearest, 0, gHomeButton);
 
-    float w = getWidth();
-    float h = getHeight();
+    float w = rsgGetWidth();
+    float h = rsgGetHeight();
+    float tw = rsAllocationGetDimX(gHomeButton);
+    float th = rsAllocationGetDimY(gHomeButton);
 
     float x;
     float y;
-    if (getWidth() > getHeight()) {
-        x = w - (params->homeButtonTextureWidth * (1 - g_Animation)) + 20;
-        y = (h - params->homeButtonTextureHeight) * 0.5f;
+    if (w > h) {
+        x = w - (tw * (1 - g_Animation)) + 20;
+        y = (h - th) * 0.5f;
     } else {
-        x = (w - params->homeButtonTextureWidth) / 2;
-        y = -g_Animation * params->homeButtonTextureHeight;
+        x = (w - tw) / 2;
+        y = -g_Animation * th;
         y -= 30; // move the house to the edge of the screen as it doesn't fill the texture.
     }
 
-    drawSpriteScreenspace(x, y, 0, params->homeButtonTextureWidth, params->homeButtonTextureHeight);
+    rsgDrawSpriteScreenspace(x, y, 0, tw, th);
 }
 
-void drawFrontGrid(float rowOffset, float p)
+static void drawFrontGrid(float rowOffset, float p)
 {
-    float h = getHeight();
-    float w = getWidth();
+    float h = rsgGetHeight();
+    float w = rsgGetWidth();
 
     int intRowOffset = rowOffset;
     float rowFrac = rowOffset - intRowOffset;
-    float colWidth = 120.f;//getWidth() / 4;
+    float colWidth = 120.f;//w / 4;
     float rowHeight = colWidth + 25.f;
     float yoff = 0.5f * h + 1.5f * rowHeight;
 
@@ -299,17 +281,16 @@
 
     int iconNum = (intRowOffset - 5) * colCount;
 
-
-    bindProgramVertex(NAMED_PVCurve);
+    rsgBindProgramVertex(gPVCurve);
 
     vpConstants->Position.z = p;
 
-    setColor(1.0f, 1.0f, 1.0f, 1.0f);
+    color(1.0f, 1.0f, 1.0f, 1.0f);
     for (row = -5; row < 15; row++) {
         float y = yoff - ((-rowFrac + row) * rowHeight);
 
         for (col=0; col < colCount; col++) {
-            if (iconNum >= state->iconCount) {
+            if (iconNum >= gIconCount) {
                 return;
             }
 
@@ -317,28 +298,29 @@
                 float x = colWidth * col + (colWidth / 2);
                 vpConstants->Position.x = x + 0.2f;
 
-                if (state->selectedIconIndex == iconNum && !p) {
-                    bindProgramFragment(NAMED_PFTexNearest);
-                    bindTexture(NAMED_PFTexNearest, 0, state->selectedIconTexture);
-                    vpConstants->ImgSize.x = SELECTION_TEXTURE_WIDTH_PX;
-                    vpConstants->ImgSize.y = SELECTION_TEXTURE_HEIGHT_PX;
-                    vpConstants->Position.y = y - (SELECTION_TEXTURE_HEIGHT_PX - ICON_TEXTURE_HEIGHT_PX) * 0.5f;
-                    drawSimpleMesh(NAMED_SMCell);
+                if (gSelectedIconIndex == iconNum && !p && gSelectedIconTexture.p) {
+                    rsgBindProgramFragment(gPFTexNearest);
+                    rsgBindTexture(gPFTexNearest, 0, gSelectedIconTexture);
+                    vpConstants->ImgSize.x = rsAllocationGetDimX(gSelectedIconTexture);
+                    vpConstants->ImgSize.y = rsAllocationGetDimY(gSelectedIconTexture);
+                    vpConstants->Position.y = y - (rsAllocationGetDimY(gSelectedIconTexture)
+                                                - rsAllocationGetDimY(gIconIDs[iconNum])) * 0.5f;
+                    rsgDrawSimpleMesh(gSMCell);
                 }
 
-                bindProgramFragment(NAMED_PFTexMip);
-                vpConstants->ImgSize.x = ICON_TEXTURE_WIDTH_PX;
-                vpConstants->ImgSize.y = ICON_TEXTURE_HEIGHT_PX;
+                rsgBindProgramFragment(gPFTexMip);
+                vpConstants->ImgSize.x = rsAllocationGetDimX(gIconIDs[iconNum]);
+                vpConstants->ImgSize.y = rsAllocationGetDimY(gIconIDs[iconNum]);
                 vpConstants->Position.y = y - 0.2f;
-                bindTexture(NAMED_PFTexMip, 0, loadI32(ALLOC_ICON_IDS, iconNum));
-                drawSimpleMesh(NAMED_SMCell);
+                rsgBindTexture(gPFTexMip, 0, gIconIDs[iconNum]);
+                rsgDrawSimpleMesh(gSMCell);
 
-                bindProgramFragment(NAMED_PFTexMipAlpha);
-                vpConstants->ImgSize.x = 120.f;
-                vpConstants->ImgSize.y = 64.f;
+                rsgBindProgramFragment(gPFTexMipAlpha);
+                vpConstants->ImgSize.x = rsAllocationGetDimX(gLabelIDs[iconNum]);
+                vpConstants->ImgSize.y = rsAllocationGetDimY(gLabelIDs[iconNum]);
                 vpConstants->Position.y = y - 64.f - 0.2f;
-                bindTexture(NAMED_PFTexMipAlpha, 0, loadI32(ALLOC_LABEL_IDS, iconNum));
-                drawSimpleMesh(NAMED_SMCell);
+                rsgBindTexture(gPFTexMipAlpha, 0, gLabelIDs[iconNum]);
+                rsgDrawSimpleMesh(gSMCell);
             }
             iconNum++;
         }
@@ -346,82 +328,65 @@
 }
 
 
-int
-main(int launchID)
+int root()
 {
     // Compute dt in seconds.
-    int newTime = uptimeMillis();
-    g_DT = (newTime - g_LastTime) / 1000.f;
+    int64_t newTime = rsUptimeMillis();
+    g_DT = (newTime - g_LastTime) * 0.001f;
     g_LastTime = newTime;
 
-    if (!g_DrawLastFrame) {
-        // If we stopped rendering we cannot use DT.
-        // assume 30fps in this case.
-        g_DT = 0.033f;
-    }
     // physics may break if DT is large.
-    g_DT = minf(g_DT, 0.2f);
+    g_DT = min(g_DT, 0.1f);
 
-    if (g_Zoom != state->zoomTarget) {
+    if (g_Zoom != gZoomTarget) {
         float dz = g_DT * 1.7f;
-        if (state->zoomTarget < 0.5f) {
+        if (gZoomTarget < 0.5f) {
             dz = -dz;
         }
-        if (fabsf(g_Zoom - state->zoomTarget) < fabsf(dz)) {
-            g_Zoom = state->zoomTarget;
+        if (fabs(g_Zoom - gZoomTarget) < fabs(dz)) {
+            g_Zoom = gZoomTarget;
         } else {
             g_Zoom += dz;
         }
         updateReadback();
     }
-    g_Animation = powf(1-g_Zoom, 3);
+    g_Animation = pow(1.f - g_Zoom, 3.f);
 
     // Set clear value to dim the background based on the zoom position.
-    if ((g_Zoom < 0.001f) && (state->zoomTarget < 0.001f) && !g_SpecialHWWar) {
-        pfClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    if ((g_Zoom < 0.001f) && (gZoomTarget < 0.001f)) {
+        rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         // When we're zoomed out and not tracking motion events, reset the pos to 0.
         if (!g_LastTouchDown) {
             g_PosPage = 0;
         }
-        return lastFrame(0);
+        return 0;
     } else {
-        pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom);
+        rsgClearColor(0.0f, 0.0f, 0.0f, g_Zoom);
     }
 
+    rsgBindProgramStore(gPS);
+
     // icons & labels
-    int iconCount = state->iconCount;
-    if (getWidth() > getHeight()) {
-        g_Cols = 6;
-        g_Rows = 3;
+    if (rsgGetWidth() > rsgGetHeight()) {
+        g_Cols = COLUMNS_PER_PAGE_LANDSCAPE;
+        g_Rows = ROWS_PER_PAGE_LANDSCAPE;
     } else {
-        g_Cols = 4;
-        g_Rows = 4;
+        g_Cols = COLUMNS_PER_PAGE_PORTRAIT;
+        g_Rows = ROWS_PER_PAGE_PORTRAIT;
     }
-    g_PosMax = ((iconCount + (g_Cols-1)) / g_Cols) - g_Rows;
+
+    g_PosMax = ((gIconCount + (g_Cols-1)) / g_Cols) - g_Rows;
     if (g_PosMax < 0) g_PosMax = 0;
 
     updatePos();
     updateReadback();
 
-    //debugF("    draw g_PosPage", g_PosPage);
-
     // Draw the icons ========================================
     drawFrontGrid(g_PosPage, g_Animation);
 
-    bindProgramFragment(NAMED_PFTexNearest);
+    rsgBindProgramFragment(gPFTexNearest);
     draw_home_button();
-
-    // This is a WAR to do a rendering pass without drawing during init to
-    // force the driver to preload and compile its shaders.
-    // Without this the first animation does not appear due to the time it
-    // takes to init the driver state.
-    if (g_SpecialHWWar) {
-        g_SpecialHWWar = 0;
-        return 1;
-    }
-
-    // Bug workaround where the last frame is not always displayed
-    // So we keep rendering until the bug is fixed.
-    return lastFrame((g_PosVelocity != 0) || fracf(g_PosPage) || g_Zoom != state->zoomTarget || (g_MoveToTime != 0));
+    return (g_PosVelocity != 0) || rsFrac(g_PosPage) || g_Zoom != gZoomTarget || (g_MoveToTime != 0);
 }
 
+
diff --git a/res/raw/allapps_bc.bc b/res/raw/allapps_bc.bc
new file mode 100644
index 0000000..59b0afb
--- /dev/null
+++ b/res/raw/allapps_bc.bc
Binary files differ
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index b8aa8ec..4a2dc49 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -131,27 +131,16 @@
     private boolean mSurrendered;
 
     private int mRestoreFocusIndex = -1;
-    
+
     @SuppressWarnings({"UnusedDeclaration"})
     static class Defines {
-        public static final int ALLOC_PARAMS = 0;
-        public static final int ALLOC_STATE = 1;
-        public static final int ALLOC_ICON_IDS = 3;
-        public static final int ALLOC_LABEL_IDS = 4;
-        public static final int ALLOC_VP_CONSTANTS = 5;
-
         public static final int COLUMNS_PER_PAGE_PORTRAIT = 4;
         public static final int ROWS_PER_PAGE_PORTRAIT = 4;
 
         public static final int COLUMNS_PER_PAGE_LANDSCAPE = 6;
         public static final int ROWS_PER_PAGE_LANDSCAPE = 3;
 
-        public static final int ICON_WIDTH_PX = 64;
-        public static final int ICON_TEXTURE_WIDTH_PX = 74;
         public static final int SELECTION_TEXTURE_WIDTH_PX = 74 + 20;
-
-        public static final int ICON_HEIGHT_PX = 64;
-        public static final int ICON_TEXTURE_HEIGHT_PX = 74;
         public static final int SELECTION_TEXTURE_HEIGHT_PX = 74 + 20;
     }
 
@@ -159,7 +148,6 @@
         super(context, attrs);
         setFocusable(true);
         setSoundEffectsEnabled(false);
-        getHolder().setFormat(PixelFormat.TRANSLUCENT);
         final ViewConfiguration config = ViewConfiguration.get(context);
         mSlop = config.getScaledTouchSlop();
         mMaxFlingVelocity = config.getScaledMaximumFlingVelocity();
@@ -274,24 +262,25 @@
         sRollo.dirtyCheck();
         sRollo.resize(w, h);
 
+        Log.d(TAG, "sc " + sRS);
         if (sRS != null) {
             sRS.mMessageCallback = mMessageProc = new AAMessage();
         }
 
         if (sRollo.mUniformAlloc != null) {
-            float tf[] = new float[] {72.f, 72.f,
-                                      120.f, 120.f, 0.f, 0.f,
-                                      120.f, 680.f,
-                                      (2.f / 480.f), 0, -((float)w / 2) - 0.25f, -380.25f};
+            ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
+            i.ScaleOffset.x = (2.f / 480.f);
+            i.ScaleOffset.y = 0;
+            i.ScaleOffset.z = -((float)w / 2) - 0.25f;
+            i.ScaleOffset.w = -380.25f;
+            i.BendPos.x = 120.f;
+            i.BendPos.y = 680.f;
             if (w > h) {
-                tf[6] = 40.f;
-                tf[7] = h - 40.f;
-                tf[9] = 1.f;
-                tf[10] = -((float)w / 2) - 0.25f;
-                tf[11] = -((float)h / 2) - 0.25f;
+                i.ScaleOffset.z = 40.f;
+                i.ScaleOffset.w = h - 40.f;
+                i.BendPos.y = 1.f;
             }
-
-            sRollo.mUniformAlloc.data(tf);
+            sRollo.mUniformAlloc.set(i, 0, true);
         }
 
         //long endTime = SystemClock.uptimeMillis();
@@ -307,18 +296,17 @@
         if (mArrowNavigation) {
             if (!hasWindowFocus) {
                 // Clear selection when we lose window focus
-                mLastSelectedIcon = sRollo.mState.selectedIconIndex;
+                mLastSelectedIcon = sRollo.mScript.get_gSelectedIconIndex();
                 sRollo.setHomeSelected(SELECTED_NONE);
                 sRollo.clearSelectedIcon();
-                sRollo.mState.save();
             } else {
-                if (sRollo.mState.iconCount > 0) {
+                if (sRollo.mScript.get_gIconCount() > 0) {
                     if (mLastSelection == SELECTION_ICONS) {
                         int selection = mLastSelectedIcon;
                         final int firstIcon = Math.round(sRollo.mScrollPos) * mColumnsPerPage;
                         if (selection < 0 || // No selection
                                 selection < firstIcon || // off the top of the screen
-                                selection >= sRollo.mState.iconCount || // past last icon
+                                selection >= sRollo.mScript.get_gIconCount() || // past last icon
                                 selection >= firstIcon + // past last icon on screen
                                     (mColumnsPerPage * mRowsPerPage)) {
                             selection = firstIcon;
@@ -326,10 +314,8 @@
 
                         // Select the first icon when we gain window focus
                         sRollo.selectIcon(selection, SELECTED_FOCUSED);
-                        sRollo.mState.save();
                     } else if (mLastSelection == SELECTION_HOME) {
                         sRollo.setHomeSelected(SELECTED_FOCUSED);
-                        sRollo.mState.save();
                     }
                 }
             }
@@ -356,7 +342,6 @@
                     // Clear selection when we lose focus
                     sRollo.clearSelectedIcon();
                     sRollo.setHomeSelected(SELECTED_NONE);
-                    sRollo.mState.save();
                     mArrowNavigation = false;
                 }
             } else {
@@ -366,11 +351,10 @@
     }
 
     private void gainFocus() {
-        if (!mArrowNavigation && sRollo.mState.iconCount > 0) {
+        if (!mArrowNavigation && sRollo.mScript.get_gIconCount() > 0) {
             // Select the first icon when we gain keyboard focus
             mArrowNavigation = true;
             sRollo.selectIcon(Math.round(sRollo.mScrollPos) * mColumnsPerPage, SELECTED_FOCUSED);
-            sRollo.mState.save();
         }
     }
 
@@ -382,7 +366,7 @@
         if (!isVisible()) {
             return false;
         }
-        final int iconCount = sRollo.mState.iconCount;
+        final int iconCount = sRollo.mScript.get_gIconCount();
 
         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) {
             if (mArrowNavigation) {
@@ -390,7 +374,7 @@
                     reallyPlaySoundEffect(SoundEffectConstants.CLICK);
                     mLauncher.closeAllApps(true);
                 } else {
-                    int whichApp = sRollo.mState.selectedIconIndex;
+                    int whichApp = sRollo.mScript.get_gSelectedIconIndex();
                     if (whichApp >= 0) {
                         ApplicationInfo app = mAllAppsList.get(whichApp);
                         mLauncher.startActivitySafely(app.intent, app);
@@ -402,10 +386,10 @@
 
         if (iconCount > 0) {
             final boolean isPortrait = getWidth() < getHeight();
-            
+
             mArrowNavigation = true;
 
-            int currentSelection = sRollo.mState.selectedIconIndex;
+            int currentSelection = sRollo.mScript.get_gSelectedIconIndex();
             int currentTopRow = Math.round(sRollo.mScrollPos);
 
             // The column of the current selection, in the range 0..COLUMNS_PER_PAGE_PORTRAIT-1
@@ -511,7 +495,6 @@
             }
             if (newSelection != currentSelection) {
                 sRollo.selectIcon(newSelection, SELECTED_FOCUSED);
-                sRollo.mState.save();
             }
         }
         return handled;
@@ -611,7 +594,6 @@
                     (!isPortrait && x > mTouchXBorders[mTouchXBorders.length-1])) {
                 mTouchTracking = TRACKING_HOME;
                 sRollo.setHomeSelected(SELECTED_PRESSED);
-                sRollo.mState.save();
                 mCurrentIconIndex = -1;
             } else {
                 mTouchTracking = TRACKING_FLING;
@@ -619,9 +601,6 @@
                 mMotionDownRawX = (int)ev.getRawX();
                 mMotionDownRawY = (int)ev.getRawY();
 
-                sRollo.mState.newPositionX = ev.getRawY() / getHeight();
-                sRollo.mState.newTouchDown = 1;
-
                 if (!sRollo.checkClickOK()) {
                     sRollo.clearSelectedIcon();
                 } else {
@@ -632,8 +611,7 @@
                         cancelLongPress();
                     }
                 }
-                sRollo.mState.save();
-                sRollo.move();
+                sRollo.move(ev.getRawY() / getHeight());
                 mVelocityTracker = VelocityTracker.obtain();
                 mVelocityTracker.addMovement(ev);
                 mStartedScrolling = false;
@@ -646,7 +624,6 @@
                         y > mTouchYBorders[mTouchYBorders.length-1]) || (!isPortrait
                         && x > mTouchXBorders[mTouchXBorders.length-1])
                         ? SELECTED_PRESSED : SELECTED_NONE);
-                sRollo.mState.save();
             } else if (mTouchTracking == TRACKING_FLING) {
                 int rawY = (int)ev.getRawY();
                 int slop;
@@ -667,14 +644,11 @@
                         cancelLongPress();
                         mCurrentIconIndex = -1;
                     }
-                    sRollo.mState.newPositionX = ev.getRawY() / getHeight();
-                    sRollo.mState.newTouchDown = 1;
-                    sRollo.move();
+                    sRollo.move(ev.getRawY() / getHeight());
 
                     mStartedScrolling = true;
                     sRollo.clearSelectedIcon();
                     mVelocityTracker.addMovement(ev);
-                    sRollo.mState.save();
                 }
             }
             break;
@@ -688,18 +662,13 @@
                         mLauncher.closeAllApps(true);
                     }
                     sRollo.setHomeSelected(SELECTED_NONE);
-                    sRollo.mState.save();
                 }
                 mCurrentIconIndex = -1;
             } else if (mTouchTracking == TRACKING_FLING) {
-                sRollo.mState.newTouchDown = 0;
-                sRollo.mState.newPositionX = ev.getRawY() / getHeight();
-
                 mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, mMaxFlingVelocity);
-                sRollo.mState.flingVelocity = mVelocityTracker.getYVelocity() / getHeight();
                 sRollo.clearSelectedIcon();
-                sRollo.mState.save();
-                sRollo.fling();
+                sRollo.fling(ev.getRawY() / getHeight(),
+                             mVelocityTracker.getYVelocity() / getHeight());
 
                 if (mVelocityTracker != null) {
                     mVelocityTracker.recycle();
@@ -761,7 +730,7 @@
             int pos = -1;
             switch (mLastSelection) {
             case SELECTION_ICONS:
-                index = sRollo.mState.selectedIconIndex;
+                index = sRollo.mScript.get_gSelectedIconIndex();
                 if (index >= 0) {
                     ApplicationInfo info = mAllAppsList.get(index);
                     if (info.title != null) {
@@ -853,13 +822,12 @@
         if (sRollo != null && reload) {
             sRollo.setApps(list);
         }
-        
+
         if (hasFocus() && mRestoreFocusIndex != -1) {
             sRollo.selectIcon(mRestoreFocusIndex, SELECTED_FOCUSED);
-            sRollo.mState.save();
             mRestoreFocusIndex = -1;
         }
-        
+
         mLocks &= ~LOCK_ICONS_PENDING;
     }
 
@@ -876,7 +844,7 @@
         final int N = list.size();
         if (sRollo != null) {
             sRollo.pause();
-            sRollo.reallocAppsList(sRollo.mState.iconCount + N);
+            sRollo.reallocAppsList(sRollo.mScript.get_gIconCount() + N);
         }
 
         for (int i=0; i<N; i++) {
@@ -946,17 +914,6 @@
         return -1;
     }
 
-    /*
-    private static int countPages(int iconCount) {
-        int iconsPerPage = getColumnsCount() * Defines.ROWS_PER_PAGE_PORTRAIT;
-        int pages = iconCount / iconsPerPage;
-        if (pages*iconsPerPage != iconCount) {
-            pages++;
-        }
-        return pages;
-    }
-    */
-
     class AAMessage extends RenderScript.RSMessage {
         public void run() {
             sRollo.mScrollPos = ((float)mData[0]) / (1 << 16);
@@ -988,23 +945,12 @@
         private int mHeight;
 
         private Resources mRes;
-        private Script mScript;
-        private Script.Invokable mInvokeMove;
-        private Script.Invokable mInvokeMoveTo;
-        private Script.Invokable mInvokeFling;
-        private Script.Invokable mInvokeResetWAR;
-        private Script.Invokable mInvokeSetZoom;
+        ScriptC_Allapps mScript;
 
-        private ProgramStore mPSIcons;
-        private ProgramFragment mPFTexMip;
-        private ProgramFragment mPFTexMipAlpha;
-        private ProgramFragment mPFTexNearest;
-        private ProgramVertex mPV;
-        private ProgramVertex mPVCurve;
         private SimpleMesh mMesh;
         private ProgramVertex.MatrixAllocation mPVA;
 
-        private Allocation mUniformAlloc;
+        private ScriptField_VpConsts mUniformAlloc;
 
         private Allocation mHomeButtonNormal;
         private Allocation mHomeButtonFocused;
@@ -1017,15 +963,11 @@
         private Allocation[] mLabels;
         private int[] mLabelIds;
         private Allocation mAllocLabelIds;
-        private Allocation mSelectedIcon;
 
         private Bitmap mSelectionBitmap;
         private Canvas mSelectionCanvas;
-        
-        private float mScrollPos;        
 
-        Params mParams;
-        State mState;
+        private float mScrollPos;
 
         AllApps3D mAllApps;
         boolean mInitialize;
@@ -1056,41 +998,6 @@
             }
         }
 
-        class Params extends BaseAlloc {
-            Params() {
-                mType = Type.createFromClass(sRS, Params.class, 1, "ParamsClass");
-                mAlloc = Allocation.createTyped(sRS, mType);
-                save();
-            }
-            public int bubbleWidth;
-            public int bubbleHeight;
-            public int bubbleBitmapWidth;
-            public int bubbleBitmapHeight;
-
-            public int homeButtonWidth;
-            public int homeButtonHeight;
-            public int homeButtonTextureWidth;
-            public int homeButtonTextureHeight;
-        }
-
-        class State extends BaseAlloc {
-            public float newPositionX;
-            public int newTouchDown;
-            public float flingVelocity;
-            public int iconCount;
-            public int selectedIconIndex = -1;
-            public int selectedIconTexture;
-            public float zoomTarget;
-            public int homeButtonId;
-            public float targetPos;
-
-            State() {
-                mType = Type.createFromClass(sRS, State.class, 1, "StateClass");
-                mAlloc = Allocation.createTyped(sRS, mType);
-                save();
-            }
-        }
-
         public RolloRS(AllApps3D allApps) {
             mAllApps = allApps;
         }
@@ -1099,12 +1006,17 @@
             mRes = res;
             mWidth = width;
             mHeight = height;
+            mScript = new ScriptC_Allapps(sRS, mRes, R.raw.allapps_bc, true);
+
             initProgramVertex();
             initProgramFragment();
             initProgramStore();
             initGl();
             initData();
-            initRs();
+
+            mScript.bind_gIconIDs(mAllocIconIds);
+            mScript.bind_gLabelIDs(mAllocLabelIds);
+            sRS.contextBindRootScript(mScript);
         }
 
         public void initMesh() {
@@ -1120,7 +1032,7 @@
                 tm.addTriangle(ct+1, ct+3, ct+2);
             }
             mMesh = tm.create();
-            mMesh.setName("SMCell");
+            mScript.set_gSMCell(mMesh);
         }
 
         void resize(int w, int h) {
@@ -1135,18 +1047,12 @@
 
             ProgramVertex.Builder pvb = new ProgramVertex.Builder(sRS, null, null);
             pvb.setTextureMatrixEnable(true);
-            mPV = pvb.create();
-            mPV.setName("PV");
-            mPV.bindAllocation(mPVA);
+            ProgramVertex pv = pvb.create();
+            pv.bindAllocation(mPVA);
+            sRS.contextBindProgramVertex(pv);
 
-            Element.Builder eb = new Element.Builder(sRS);
-            eb.add(Element.createVector(sRS, Element.DataType.FLOAT_32, 2), "ImgSize");
-            eb.add(Element.createVector(sRS, Element.DataType.FLOAT_32, 4), "Position");
-            eb.add(Element.createVector(sRS, Element.DataType.FLOAT_32, 2), "BendPos");
-            eb.add(Element.createVector(sRS, Element.DataType.FLOAT_32, 4), "ScaleOffset");
-            Element e = eb.create();
-
-            mUniformAlloc = Allocation.createSized(sRS, e, 1);
+            mUniformAlloc = new ScriptField_VpConsts(sRS, 1);
+            mScript.bind_vpConstants(mUniformAlloc);
 
             initMesh();
             ProgramVertex.ShaderBuilder sb = new ProgramVertex.ShaderBuilder(sRS);
@@ -1209,12 +1115,11 @@
             sb.setShader(t);
             sb.addConstant(mUniformAlloc.getType());
             sb.addInput(mMesh.getVertexType(0).getElement());
-            mPVCurve = sb.create();
-            mPVCurve.setName("PVCurve");
-            mPVCurve.bindAllocation(mPVA);
-            mPVCurve.bindConstants(mUniformAlloc, 1);
+            ProgramVertex pvc = sb.create();
+            pvc.bindAllocation(mPVA);
+            pvc.bindConstants(mUniformAlloc.getAllocation(), 1);
 
-            sRS.contextBindProgramVertex(mPV);
+            mScript.set_gPVCurve(pvc);
         }
 
         private void initProgramFragment() {
@@ -1232,20 +1137,20 @@
             ProgramFragment.Builder bf = new ProgramFragment.Builder(sRS);
             bf.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
                           ProgramFragment.Builder.Format.RGBA, 0);
-            mPFTexMip = bf.create();
-            mPFTexMip.setName("PFTexMip");
-            mPFTexMip.bindSampler(linear, 0);
+            ProgramFragment pfTexMip = bf.create();
+            pfTexMip.bindSampler(linear, 0);
 
-            mPFTexNearest = bf.create();
-            mPFTexNearest.setName("PFTexNearest");
-            mPFTexNearest.bindSampler(nearest, 0);
+            ProgramFragment pfTexNearest = bf.create();
+            pfTexNearest.bindSampler(nearest, 0);
 
             bf.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
                           ProgramFragment.Builder.Format.ALPHA, 0);
-            mPFTexMipAlpha = bf.create();
-            mPFTexMipAlpha.setName("PFTexMipAlpha");
-            mPFTexMipAlpha.bindSampler(linear, 0);
+            ProgramFragment pfTexMipAlpha = bf.create();
+            pfTexMipAlpha.bindSampler(linear, 0);
 
+            mScript.set_gPFTexNearest(pfTexNearest);
+            mScript.set_gPFTexMip(pfTexMip);
+            mScript.set_gPFTexMipAlpha(pfTexMipAlpha);
         }
 
         private void initProgramStore() {
@@ -1255,23 +1160,17 @@
             bs.setDitherEnable(true);
             bs.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA,
                             ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-            mPSIcons = bs.create();
-            mPSIcons.setName("PSIcons");
+            mScript.set_gPS(bs.create());
         }
 
         private void initGl() {
         }
 
         private void initData() {
-            mParams = new Params();
-            mState = new State();
-
-            final Utilities.BubbleText bubble = new Utilities.BubbleText(mAllApps.getContext());
-
-            mParams.bubbleWidth = bubble.getBubbleWidth();
-            mParams.bubbleHeight = bubble.getMaxBubbleHeight();
-            mParams.bubbleBitmapWidth = bubble.getBitmapWidth();
-            mParams.bubbleBitmapHeight = bubble.getBitmapHeight();
+            mScript.set_COLUMNS_PER_PAGE_PORTRAIT(Defines.COLUMNS_PER_PAGE_PORTRAIT);
+            mScript.set_ROWS_PER_PAGE_PORTRAIT(Defines.ROWS_PER_PAGE_PORTRAIT);
+            mScript.set_COLUMNS_PER_PAGE_LANDSCAPE(Defines.COLUMNS_PER_PAGE_LANDSCAPE);
+            mScript.set_ROWS_PER_PAGE_LANDSCAPE(Defines.ROWS_PER_PAGE_LANDSCAPE);
 
             mHomeButtonNormal = Allocation.createFromBitmapResource(sRS, mRes,
                     R.drawable.home_button_normal, Element.RGBA_8888(sRS), false);
@@ -1282,15 +1181,8 @@
             mHomeButtonPressed = Allocation.createFromBitmapResource(sRS, mRes,
                     R.drawable.home_button_pressed, Element.RGBA_8888(sRS), false);
             mHomeButtonPressed.uploadToTexture(0);
-            mParams.homeButtonWidth = 76;
-            mParams.homeButtonHeight = 68;
-            mParams.homeButtonTextureWidth = 128;
-            mParams.homeButtonTextureHeight = 128;
 
-            mState.homeButtonId = mHomeButtonNormal.getID();
-
-            mParams.save();
-            mState.save();
+            mScript.set_gHomeButton(mHomeButtonNormal);
 
             mSelectionBitmap = Bitmap.createBitmap(Defines.SELECTION_TEXTURE_WIDTH_PX,
                     Defines.SELECTION_TEXTURE_HEIGHT_PX, Bitmap.Config.ARGB_8888);
@@ -1299,30 +1191,6 @@
             setApps(null);
         }
 
-        private void initRs() {
-            ScriptC.Builder sb = new ScriptC.Builder(sRS);
-            sb.setScript(mRes, R.raw.allapps);
-            sb.setRoot(true);
-            sb.addDefines(mAllApps.mDefines);
-            sb.setType(mParams.mType, "params", Defines.ALLOC_PARAMS);
-            sb.setType(mState.mType, "state", Defines.ALLOC_STATE);
-            sb.setType(mUniformAlloc.getType(), "vpConstants", Defines.ALLOC_VP_CONSTANTS);
-            mInvokeMove = sb.addInvokable("move");
-            mInvokeFling = sb.addInvokable("fling");
-            mInvokeMoveTo = sb.addInvokable("moveTo");
-            mInvokeResetWAR = sb.addInvokable("resetHWWar");
-            mInvokeSetZoom = sb.addInvokable("setZoom");
-            mScript = sb.create();
-            mScript.setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-            mScript.bindAllocation(mParams.mAlloc, Defines.ALLOC_PARAMS);
-            mScript.bindAllocation(mState.mAlloc, Defines.ALLOC_STATE);
-            mScript.bindAllocation(mAllocIconIds, Defines.ALLOC_ICON_IDS);
-            mScript.bindAllocation(mAllocLabelIds, Defines.ALLOC_LABEL_IDS);
-            mScript.bindAllocation(mUniformAlloc, Defines.ALLOC_VP_CONSTANTS);
-
-            sRS.contextBindRootScript(mScript);
-        }
-
         void dirtyCheck() {
             if (sZoomDirty) {
                 setZoom(mAllApps.sNextZoom, mAllApps.sAnimateNextZoom);
@@ -1340,20 +1208,21 @@
 
             mIcons = new Allocation[count];
             mIconIds = new int[allocCount];
-            mAllocIconIds = Allocation.createSized(sRS, Element.USER_I32(sRS), allocCount);
+            mAllocIconIds = Allocation.createSized(sRS, Element.I32(sRS), allocCount);
 
             mLabels = new Allocation[count];
             mLabelIds = new int[allocCount];
-            mAllocLabelIds = Allocation.createSized(sRS, Element.USER_I32(sRS), allocCount);
+            mAllocLabelIds = Allocation.createSized(sRS, Element.I32(sRS), allocCount);
 
-            mState.iconCount = count;
-            for (int i=0; i < mState.iconCount; i++) {
+            mScript.set_gIconCount(count);
+            for (int i=0; i < count; i++) {
                 createAppIconAllocations(i, list.get(i));
             }
-            for (int i=0; i < mState.iconCount; i++) {
+            for (int i=0; i < count; i++) {
                 uploadAppIcon(i, list.get(i));
             }
             saveAppsList();
+            android.util.Log.e("rs", "setApps");
             sRollo.resume();
         }
 
@@ -1362,15 +1231,7 @@
                 sRollo.clearSelectedIcon();
                 sRollo.setHomeSelected(SELECTED_NONE);
             }
-            if (zoom > 0.001f) {
-                sRollo.mState.zoomTarget = zoom;
-            } else {
-                sRollo.mState.zoomTarget = 0;
-            }
-            sRollo.mState.save();
-            if (!animate) {
-                sRollo.mInvokeSetZoom.execute();
-            }
+            sRollo.mScript.invoke_setZoom(zoom, animate ? 1 : 0);
         }
 
         private void createAppIconAllocations(int index, ApplicationInfo item) {
@@ -1400,13 +1261,13 @@
         private void reallocAppsList(int count) {
             Allocation[] icons = new Allocation[count];
             int[] iconIds = new int[count];
-            mAllocIconIds = Allocation.createSized(sRS, Element.USER_I32(sRS), count);
+            mAllocIconIds = Allocation.createSized(sRS, Element.I32(sRS), count);
 
             Allocation[] labels = new Allocation[count];
             int[] labelIds = new int[count];
-            mAllocLabelIds = Allocation.createSized(sRS, Element.USER_I32(sRS), count);
+            mAllocLabelIds = Allocation.createSized(sRS, Element.I32(sRS), count);
 
-            final int oldCount = sRollo.mState.iconCount;
+            final int oldCount = sRollo.mScript.get_gIconCount();
 
             System.arraycopy(mIcons, 0, icons, 0, oldCount);
             System.arraycopy(mIconIds, 0, iconIds, 0, oldCount);
@@ -1423,7 +1284,7 @@
          * Handle the allocations for the new app.  Make sure you call saveAppsList when done.
          */
         private void addApp(int index, ApplicationInfo item) {
-            final int count = mState.iconCount - index;
+            final int count = mScript.get_gIconCount() - index;
             final int dest = index + 1;
 
             System.arraycopy(mIcons, index, mIcons, dest, count);
@@ -1433,14 +1294,15 @@
 
             createAppIconAllocations(index, item);
             uploadAppIcon(index, item);
-            sRollo.mState.iconCount++;
+
+            mScript.set_gIconCount(mScript.get_gIconCount() + 1);
         }
 
         /**
          * Handle the allocations for the removed app.  Make sure you call saveAppsList when done.
          */
         private void removeApp(int index) {
-            final int count = mState.iconCount - index - 1;
+            final int count = mScript.get_gIconCount() - index - 1;
             final int src = index + 1;
 
             System.arraycopy(mIcons, src, mIcons, index, count);
@@ -1448,8 +1310,8 @@
             System.arraycopy(mLabels, src, mLabels, index, count);
             System.arraycopy(mLabelIds, src, mLabelIds, index, count);
 
-            sRollo.mState.iconCount--;
-            final int last = mState.iconCount;
+            mScript.set_gIconCount(mScript.get_gIconCount() - 1);
+            final int last = mScript.get_gIconCount();
 
             mIcons[last] = null;
             mIconIds[last] = 0;
@@ -1466,31 +1328,21 @@
                 mAllocIconIds.data(mIconIds);
                 mAllocLabelIds.data(mLabelIds);
 
-                mScript.bindAllocation(mAllocIconIds, Defines.ALLOC_ICON_IDS);
-                mScript.bindAllocation(mAllocLabelIds, Defines.ALLOC_LABEL_IDS);
-
-                mState.save();
-
-                // Note: mScript may be null if we haven't initialized it yet.
-                // In that case, this is a no-op.
-                if (mInvokeResetWAR != null) {
-                    mInvokeResetWAR.execute();
-                }
+                mScript.bind_gIconIDs(mAllocIconIds);
+                mScript.bind_gLabelIDs(mAllocLabelIds);
             }
         }
 
-        void fling() {
-            mInvokeFling.execute();
+        void fling(float pos, float v) {
+            mScript.invoke_fling(pos, v);
         }
 
-        void move() {
-            mInvokeMove.execute();
+        void move(float pos) {
+            mScript.invoke_move(pos);
         }
 
         void moveTo(float row) {
-            mState.targetPos = row;
-            mState.save();
-            mInvokeMoveTo.execute();
+            mScript.invoke_moveTo(row);
         }
 
         /**
@@ -1520,7 +1372,7 @@
                 if (mAllApps != null) {
                     mAllApps.mRestoreFocusIndex = index;
                 }
-                mState.selectedIconIndex = -1;
+                mScript.set_gSelectedIconIndex(-1);
                 if (mAllApps.mLastSelection == SELECTION_ICONS) {
                     mAllApps.mLastSelection = SELECTION_NONE;
                 }
@@ -1529,8 +1381,8 @@
                     mAllApps.mLastSelection = SELECTION_ICONS;
                 }
 
-                int prev = mState.selectedIconIndex;
-                mState.selectedIconIndex = index;
+                int prev = mScript.get_gSelectedIconIndex();
+                mScript.set_gSelectedIconIndex(index);
 
                 ApplicationInfo info = appsList.get(index);
                 Bitmap selectionBitmap = mSelectionBitmap;
@@ -1539,10 +1391,10 @@
                         selectionBitmap.getWidth(), selectionBitmap.getHeight(),
                         pressed == SELECTED_PRESSED, info.iconBitmap);
 
-                mSelectedIcon = Allocation.createFromBitmap(sRS, selectionBitmap,
+                Allocation si = Allocation.createFromBitmap(sRS, selectionBitmap,
                         Element.RGBA_8888(sRS), false);
-                mSelectedIcon.uploadToTexture(0);
-                mState.selectedIconTexture = mSelectedIcon.getID();
+                si.uploadToTexture(0);
+                mScript.set_gSelectedIconTexture(si);
 
                 if (prev != index) {
                     if (info.title != null && info.title.length() > 0) {
@@ -1557,24 +1409,24 @@
          * You need to call save() on mState on your own after calling this.
          */
         void clearSelectedIcon() {
-            mState.selectedIconIndex = -1;
+            mScript.set_gSelectedIconIndex(-1);
         }
 
         void setHomeSelected(int mode) {
             final int prev = mAllApps.mLastSelection;
             switch (mode) {
             case SELECTED_NONE:
-                mState.homeButtonId = mHomeButtonNormal.getID();
+                mScript.set_gHomeButton(mHomeButtonNormal);
                 break;
             case SELECTED_FOCUSED:
                 mAllApps.mLastSelection = SELECTION_HOME;
-                mState.homeButtonId = mHomeButtonFocused.getID();
+                mScript.set_gHomeButton(mHomeButtonFocused);
                 if (prev != SELECTION_HOME) {
                     mAllApps.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
                 }
                 break;
             case SELECTED_PRESSED:
-                mState.homeButtonId = mHomeButtonPressed.getID();
+                mScript.set_gHomeButton(mHomeButtonPressed);
                 break;
             }
         }
@@ -1594,23 +1446,15 @@
                 Log.d(TAG, "sRollo.mLabelIds.length=" + mLabelIds.length);
             }
             Log.d(TAG, "sRollo.mLabelIds=" +  Arrays.toString(mLabelIds));
-            Log.d(TAG, "sRollo.mState.newPositionX=" + mState.newPositionX);
-            Log.d(TAG, "sRollo.mState.newTouchDown=" + mState.newTouchDown);
-            Log.d(TAG, "sRollo.mState.flingVelocity=" + mState.flingVelocity);
-            Log.d(TAG, "sRollo.mState.iconCount=" + mState.iconCount);
-            Log.d(TAG, "sRollo.mState.selectedIconIndex=" + mState.selectedIconIndex);
-            Log.d(TAG, "sRollo.mState.selectedIconTexture=" + mState.selectedIconTexture);
-            Log.d(TAG, "sRollo.mState.zoomTarget=" + mState.zoomTarget);
-            Log.d(TAG, "sRollo.mState.homeButtonId=" + mState.homeButtonId);
-            Log.d(TAG, "sRollo.mState.targetPos=" + mState.targetPos);
-            Log.d(TAG, "sRollo.mParams.bubbleWidth=" + mParams.bubbleWidth);
-            Log.d(TAG, "sRollo.mParams.bubbleHeight=" + mParams.bubbleHeight);
-            Log.d(TAG, "sRollo.mParams.bubbleBitmapWidth=" + mParams.bubbleBitmapWidth);
-            Log.d(TAG, "sRollo.mParams.bubbleBitmapHeight=" + mParams.bubbleBitmapHeight);
-            Log.d(TAG, "sRollo.mParams.homeButtonWidth=" + mParams.homeButtonWidth);
-            Log.d(TAG, "sRollo.mParams.homeButtonHeight=" + mParams.homeButtonHeight);
-            Log.d(TAG, "sRollo.mParams.homeButtonTextureWidth=" + mParams.homeButtonTextureWidth);
-            Log.d(TAG, "sRollo.mParams.homeButtonTextureHeight=" + mParams.homeButtonTextureHeight);
+            //Log.d(TAG, "sRollo.mState.newPositionX=" + mState.newPositionX);
+            //Log.d(TAG, "sRollo.mState.newTouchDown=" + mState.newTouchDown);
+            //Log.d(TAG, "sRollo.mState.flingVelocity=" + mState.flingVelocity);
+            //Log.d(TAG, "sRollo.mState.iconCount=" + mState.iconCount);
+            //Log.d(TAG, "sRollo.mState.selectedIconIndex=" + mState.selectedIconIndex);
+            //Log.d(TAG, "sRollo.mState.selectedIconTexture=" + mState.selectedIconTexture);
+            //Log.d(TAG, "sRollo.mState.zoomTarget=" + mState.zoomTarget);
+            //Log.d(TAG, "sRollo.mState.homeButtonId=" + mState.homeButtonId);
+            //Log.d(TAG, "sRollo.mState.targetPos=" + mState.targetPos);
         }
     }
 
@@ -1641,5 +1485,3 @@
         }
     }
 }
-
-
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 9d39c2c..73481c2 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -136,8 +136,8 @@
     public void addView(View child, int index, ViewGroup.LayoutParams params) {
         // Generate an id for each view, this assumes we have at most 256x256 cells
         // per workspace screen
-        final LayoutParams cellParams = (LayoutParams) params;
-        cellParams.regenerateId = true;
+        final LayoutParams lp = (LayoutParams) params;
+        child.setId(((getId() & 0xFF) << 16) | (lp.cellX & 0xFF) << 8 | (lp.cellY & 0xFF));
 
         super.addView(child, index, params);
     }
@@ -158,67 +158,72 @@
         mCellInfo.screen = ((ViewGroup) getParent()).indexOfChild(this);
     }
 
+    public void setTagToCellInfoForPoint(int touchX, int touchY) {
+        final CellInfo cellInfo = mCellInfo;
+        final Rect frame = mRect;
+        final int x = touchX + mScrollX;
+        final int y = touchY + mScrollY;
+        final int count = getChildCount();
+
+        boolean found = false;
+        for (int i = count - 1; i >= 0; i--) {
+            final View child = getChildAt(i);
+
+            if ((child.getVisibility()) == VISIBLE || child.getAnimation() != null) {
+                child.getHitRect(frame);
+                if (frame.contains(x, y)) {
+                    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                    cellInfo.cell = child;
+                    cellInfo.cellX = lp.cellX;
+                    cellInfo.cellY = lp.cellY;
+                    cellInfo.spanX = lp.cellHSpan;
+                    cellInfo.spanY = lp.cellVSpan;
+                    cellInfo.valid = true;
+                    found = true;
+                    mDirtyTag = false;
+                    break;
+                }
+            }
+        }
+            
+        mLastDownOnOccupiedCell = found;
+
+        if (!found) {
+            int cellXY[] = mCellXY;
+            pointToCellExact(x, y, cellXY);
+
+            final boolean portrait = mPortrait;
+            final int xCount = portrait ? mShortAxisCells : mLongAxisCells;
+            final int yCount = portrait ? mLongAxisCells : mShortAxisCells;
+
+            final boolean[][] occupied = mOccupied;
+            findOccupiedCells(xCount, yCount, occupied, null);
+
+            cellInfo.cell = null;
+            cellInfo.cellX = cellXY[0];
+            cellInfo.cellY = cellXY[1];
+            cellInfo.spanX = 1;
+            cellInfo.spanY = 1;
+            cellInfo.valid = cellXY[0] >= 0 && cellXY[1] >= 0 && cellXY[0] < xCount &&
+                    cellXY[1] < yCount && !occupied[cellXY[0]][cellXY[1]];
+
+            // Instead of finding the interesting vacant cells here, wait until a
+            // caller invokes getTag() to retrieve the result. Finding the vacant
+            // cells is a bit expensive and can generate many new objects, it's
+            // therefore better to defer it until we know we actually need it.
+
+            mDirtyTag = true;
+        }
+        setTag(cellInfo);
+    }
+
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         final int action = ev.getAction();
         final CellInfo cellInfo = mCellInfo;
 
         if (action == MotionEvent.ACTION_DOWN) {
-            final Rect frame = mRect;
-            final int x = (int) ev.getX() + mScrollX;
-            final int y = (int) ev.getY() + mScrollY;
-            final int count = getChildCount();
-
-            boolean found = false;
-            for (int i = count - 1; i >= 0; i--) {
-                final View child = getChildAt(i);
-
-                if ((child.getVisibility()) == VISIBLE || child.getAnimation() != null) {
-                    child.getHitRect(frame);
-                    if (frame.contains(x, y)) {
-                        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                        cellInfo.cell = child;
-                        cellInfo.cellX = lp.cellX;
-                        cellInfo.cellY = lp.cellY;
-                        cellInfo.spanX = lp.cellHSpan;
-                        cellInfo.spanY = lp.cellVSpan;
-                        cellInfo.valid = true;
-                        found = true;
-                        mDirtyTag = false;
-                        break;
-                    }
-                }
-            }
-            
-            mLastDownOnOccupiedCell = found;
-
-            if (!found) {
-                int cellXY[] = mCellXY;
-                pointToCellExact(x, y, cellXY);
-
-                final boolean portrait = mPortrait;
-                final int xCount = portrait ? mShortAxisCells : mLongAxisCells;
-                final int yCount = portrait ? mLongAxisCells : mShortAxisCells;
-
-                final boolean[][] occupied = mOccupied;
-                findOccupiedCells(xCount, yCount, occupied, null);
-
-                cellInfo.cell = null;
-                cellInfo.cellX = cellXY[0];
-                cellInfo.cellY = cellXY[1];
-                cellInfo.spanX = 1;
-                cellInfo.spanY = 1;
-                cellInfo.valid = cellXY[0] >= 0 && cellXY[1] >= 0 && cellXY[0] < xCount &&
-                        cellXY[1] < yCount && !occupied[cellXY[0]][cellXY[1]];
-
-                // Instead of finding the interesting vacant cells here, wait until a
-                // caller invokes getTag() to retrieve the result. Finding the vacant
-                // cells is a bit expensive and can generate many new objects, it's
-                // therefore better to defer it until we know we actually need it.
-
-                mDirtyTag = true;
-            }
-            setTag(cellInfo);
+            setTagToCellInfoForPoint((int) ev.getX(), (int) ev.getY());
         } else if (action == MotionEvent.ACTION_UP) {
             cellInfo.cell = null;
             cellInfo.cellX = -1;
@@ -536,11 +541,6 @@
                         shortAxisStartPadding);
             }
             
-            if (lp.regenerateId) {
-                child.setId(((getId() & 0xFF) << 16) | (lp.cellX & 0xFF) << 8 | (lp.cellY & 0xFF));
-                lp.regenerateId = false;
-            }
-
             int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
             int childheightMeasureSpec =
                     MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
@@ -889,8 +889,6 @@
         @ViewDebug.ExportedProperty
         int y;
 
-        boolean regenerateId;
-        
         boolean dropped;
 
         public LayoutParams(Context c, AttributeSet attrs) {
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index a5988bf..07e8834 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -17,6 +17,7 @@
 package com.android.launcher2;
 
 import com.android.common.Search;
+import com.android.launcher.R;
 
 import android.app.Activity;
 import android.app.AlertDialog;
@@ -24,6 +25,8 @@
 import android.app.SearchManager;
 import android.app.StatusBarManager;
 import android.app.WallpaperManager;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -31,9 +34,8 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.Intent.ShortcutIconResource;
 import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
+import android.content.Intent.ShortcutIconResource;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
@@ -41,10 +43,10 @@
 import android.content.res.TypedArray;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
-import android.graphics.Rect;
 import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
+import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -66,25 +68,22 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.View.OnLongClickListener;
+import android.view.animation.AnimationUtils;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.PopupWindow;
 import android.widget.TextView;
 import android.widget.Toast;
-import android.widget.ImageView;
-import android.widget.PopupWindow;
-import android.widget.LinearLayout;
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.HashMap;
+import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.DataInputStream;
-
-import com.android.launcher.R;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
 
 /**
  * Default launcher application.
@@ -182,6 +181,7 @@
     private DeleteZone mDeleteZone;
     private HandleView mHandleView;
     private AllAppsView mAllAppsGrid;
+    private WidgetChooser mWidgetChooser;
 
     private Bundle mSavedState;
 
@@ -536,10 +536,13 @@
                     completeAddLiveFolder(data, mAddItemCellInfo);
                     break;
                 case REQUEST_PICK_APPWIDGET:
-                    addAppWidget(data);
+                    addAppWidgetFromPick(data);
                     break;
                 case REQUEST_CREATE_APPWIDGET:
-                    completeAddAppWidget(data, mAddItemCellInfo);
+                    int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
+                    // TODO: Is this log message meaningful?
+                    if (LOGD) Log.d(TAG, "dumping extras content=" + data.getExtras());
+                    completeAddAppWidget(appWidgetId, mAddItemCellInfo);
                     break;
                 case REQUEST_PICK_WALLPAPER:
                     // We just wanted the activity result here so we can clear mWaitingForResult
@@ -572,8 +575,11 @@
     @Override
     protected void onPause() {
         super.onPause();
-        dismissPreview(mPreviousView);
-        dismissPreview(mNextView);
+        // Some launcher layouts don't have a previous and next view
+        if (mPreviousView != null) {
+            dismissPreview(mPreviousView);
+            dismissPreview(mNextView);
+        }
         mDragController.cancelDrag();
     }
 
@@ -720,24 +726,30 @@
         mHandleView.setOnClickListener(this);
         mHandleView.setOnLongClickListener(this);
 
-        ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
-        hotseatLeft.setContentDescription(mHotseatLabels[0]);
-        hotseatLeft.setImageDrawable(mHotseatIcons[0]);
-        ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right);
-        hotseatRight.setContentDescription(mHotseatLabels[1]);
-        hotseatRight.setImageDrawable(mHotseatIcons[1]);
+        mWidgetChooser = (WidgetChooser) findViewById(R.id.widget_chooser);
+        if (mWidgetChooser != null) {
+            mWidgetChooser.setDragController(dragController);
+            mWidgetChooser.setLauncher(this);
+        } else {
+             ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
+             hotseatLeft.setContentDescription(mHotseatLabels[0]);
+             hotseatLeft.setImageDrawable(mHotseatIcons[0]);
+             ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right);
+             hotseatRight.setContentDescription(mHotseatLabels[1]);
+             hotseatRight.setImageDrawable(mHotseatIcons[1]);
 
-        mPreviousView = (ImageView) dragLayer.findViewById(R.id.previous_screen);
-        mNextView = (ImageView) dragLayer.findViewById(R.id.next_screen);
+             mPreviousView = (ImageView) dragLayer.findViewById(R.id.previous_screen);
+             mNextView = (ImageView) dragLayer.findViewById(R.id.next_screen);
 
-        Drawable previous = mPreviousView.getDrawable();
-        Drawable next = mNextView.getDrawable();
-        mWorkspace.setIndicators(previous, next);
+             Drawable previous = mPreviousView.getDrawable();
+             Drawable next = mNextView.getDrawable();
+             mWorkspace.setIndicators(previous, next);
 
-        mPreviousView.setHapticFeedbackEnabled(false);
-        mPreviousView.setOnLongClickListener(this);
-        mNextView.setHapticFeedbackEnabled(false);
-        mNextView.setOnLongClickListener(this);
+             mPreviousView.setHapticFeedbackEnabled(false);
+             mPreviousView.setOnLongClickListener(this);
+             mNextView.setHapticFeedbackEnabled(false);
+             mNextView.setOnLongClickListener(this);
+        }
 
         workspace.setOnLongClickListener(this);
         workspace.setDragController(dragController);
@@ -745,7 +757,8 @@
 
         deleteZone.setLauncher(this);
         deleteZone.setDragController(dragController);
-        deleteZone.setHandle(findViewById(R.id.all_apps_button_cluster));
+        int deleteZoneHandleId = isScreenXLarge() ? R.id.add_button : R.id.all_apps_button_cluster;
+        deleteZone.setHandle(findViewById(deleteZoneHandleId));
 
         dragController.setDragScoller(workspace);
         dragController.setDragListener(deleteZone);
@@ -876,12 +889,7 @@
      * @param data The intent describing the appWidgetId.
      * @param cellInfo The position on screen where to create the widget.
      */
-    private void completeAddAppWidget(Intent data, CellLayout.CellInfo cellInfo) {
-        Bundle extras = data.getExtras();
-        int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
-
-        if (LOGD) Log.d(TAG, "dumping extras content=" + extras.toString());
-
+    private void completeAddAppWidget(int appWidgetId, CellLayout.CellInfo cellInfo) {
         AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
 
         // Calculate the grid spans needed to fit this widget
@@ -1171,9 +1179,27 @@
         showAddDialog(mMenuAddInfo);
     }
 
-    void addAppWidget(Intent data) {
+    boolean isScreenXLarge() {
+        int screenLayout = getResources().getConfiguration().screenLayout;
+        return (screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE;
+    }
+
+    void addAppWidgetFromDrop(ComponentName appWidgetProvider, CellLayout.CellInfo cellInfo) {
+        mAddItemCellInfo = cellInfo;
+        int appWidgetId = getAppWidgetHost().allocateAppWidgetId();
+        AppWidgetManager.getInstance(this).bindAppWidgetId(appWidgetId, appWidgetProvider);
+        addAppWidgetImpl(appWidgetId);
+    }
+
+    void addAppWidgetFromPick(Intent data) {
         // TODO: catch bad widget exception when sent
         int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
+        // TODO: Is this log message meaningful?
+        if (LOGD) Log.d(TAG, "dumping extras content=" + data.getExtras());
+        addAppWidgetImpl(appWidgetId);
+    }
+
+    void addAppWidgetImpl(int appWidgetId) {
         AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
 
         if (appWidget.configure != null) {
@@ -1185,7 +1211,7 @@
             startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);
         } else {
             // Otherwise just add it
-            onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data);
+            completeAddAppWidget(appWidgetId, mAddItemCellInfo);
         }
     }
 
@@ -1389,8 +1415,11 @@
         } else {
             closeFolder();
         }
-        dismissPreview(mPreviousView);
-        dismissPreview(mNextView);
+        // Some launcher layouts don't have a previous and next view
+        if (mPreviousView != null) {
+            dismissPreview(mPreviousView);
+            dismissPreview(mNextView);
+        }
     }
 
     private void closeFolder() {
@@ -1456,6 +1485,24 @@
         }
     }
 
+    /**
+     * Event handler for the "plus" button that appears on the home screen, which
+     * enters home screen customization mode.
+     *
+     * @param v The view that was clicked.
+     */
+    public void onClickAddButton(View v) {
+        View widgetChooser = findViewById(R.id.widget_chooser);
+        widgetChooser.setVisibility(View.VISIBLE);
+
+        // Animate the widget chooser up from the bottom of the screen
+        widgetChooser.startAnimation(AnimationUtils.loadAnimation(this, R.anim.widget_chooser_slide_up));
+    }
+
+    public void onClickAllAppsButton(View w) {
+        showAllApps(true);
+    }
+
     void startActivitySafely(Intent intent, Object tag) {
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         try {
diff --git a/src/com/android/launcher2/LauncherAppWidgetInfo.java b/src/com/android/launcher2/LauncherAppWidgetInfo.java
index 8499ebb..3c81bac 100644
--- a/src/com/android/launcher2/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher2/LauncherAppWidgetInfo.java
@@ -17,6 +17,7 @@
 package com.android.launcher2;
 
 import android.appwidget.AppWidgetHostView;
+import android.content.ComponentName;
 import android.content.ContentValues;
 
 /**
@@ -29,6 +30,7 @@
      * {@link android.appwidget.AppWidgetManager} for updates.
      */
     int appWidgetId;
+    ComponentName providerName;
     
     /**
      * View that holds this widget after it's been created.  This view isn't created
diff --git a/src/com/android/launcher2/ScriptC_Allapps.java b/src/com/android/launcher2/ScriptC_Allapps.java
new file mode 100644
index 0000000..aeb1c26
--- /dev/null
+++ b/src/com/android/launcher2/ScriptC_Allapps.java
@@ -0,0 +1,261 @@
+/*
+ * 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.renderscript.*;
+import android.content.res.Resources;
+import android.util.Log;
+
+public class ScriptC_Allapps extends ScriptC {
+    // Constructor
+    public  ScriptC_Allapps(RenderScript rs, Resources resources, int id, boolean isRoot) {
+        super(rs, resources, id, isRoot);
+    }
+
+    private final static int mExportVarIdx_COLUMNS_PER_PAGE_PORTRAIT = 0;
+    private int mExportVar_COLUMNS_PER_PAGE_PORTRAIT;
+    public void set_COLUMNS_PER_PAGE_PORTRAIT(int v) {
+        mExportVar_COLUMNS_PER_PAGE_PORTRAIT = v;
+        setVar(mExportVarIdx_COLUMNS_PER_PAGE_PORTRAIT, v);
+    }
+
+    public int get_COLUMNS_PER_PAGE_PORTRAIT() {
+        return mExportVar_COLUMNS_PER_PAGE_PORTRAIT;
+    }
+
+    private final static int mExportVarIdx_ROWS_PER_PAGE_PORTRAIT = 1;
+    private int mExportVar_ROWS_PER_PAGE_PORTRAIT;
+    public void set_ROWS_PER_PAGE_PORTRAIT(int v) {
+        mExportVar_ROWS_PER_PAGE_PORTRAIT = v;
+        setVar(mExportVarIdx_ROWS_PER_PAGE_PORTRAIT, v);
+    }
+
+    public int get_ROWS_PER_PAGE_PORTRAIT() {
+        return mExportVar_ROWS_PER_PAGE_PORTRAIT;
+    }
+
+    private final static int mExportVarIdx_COLUMNS_PER_PAGE_LANDSCAPE = 2;
+    private int mExportVar_COLUMNS_PER_PAGE_LANDSCAPE;
+    public void set_COLUMNS_PER_PAGE_LANDSCAPE(int v) {
+        mExportVar_COLUMNS_PER_PAGE_LANDSCAPE = v;
+        setVar(mExportVarIdx_COLUMNS_PER_PAGE_LANDSCAPE, v);
+    }
+
+    public int get_COLUMNS_PER_PAGE_LANDSCAPE() {
+        return mExportVar_COLUMNS_PER_PAGE_LANDSCAPE;
+    }
+
+    private final static int mExportVarIdx_ROWS_PER_PAGE_LANDSCAPE = 3;
+    private int mExportVar_ROWS_PER_PAGE_LANDSCAPE;
+    public void set_ROWS_PER_PAGE_LANDSCAPE(int v) {
+        mExportVar_ROWS_PER_PAGE_LANDSCAPE = v;
+        setVar(mExportVarIdx_ROWS_PER_PAGE_LANDSCAPE, v);
+    }
+
+    public int get_ROWS_PER_PAGE_LANDSCAPE() {
+        return mExportVar_ROWS_PER_PAGE_LANDSCAPE;
+    }
+
+    private final static int mExportVarIdx_gIconCount = 4;
+    private int mExportVar_gIconCount;
+    public void set_gIconCount(int v) {
+        mExportVar_gIconCount = v;
+        setVar(mExportVarIdx_gIconCount, v);
+    }
+
+    public int get_gIconCount() {
+        return mExportVar_gIconCount;
+    }
+
+    private final static int mExportVarIdx_gSelectedIconIndex = 5;
+    private int mExportVar_gSelectedIconIndex;
+    public void set_gSelectedIconIndex(int v) {
+        mExportVar_gSelectedIconIndex = v;
+        setVar(mExportVarIdx_gSelectedIconIndex, v);
+    }
+
+    public int get_gSelectedIconIndex() {
+        return mExportVar_gSelectedIconIndex;
+    }
+
+    private final static int mExportVarIdx_gSelectedIconTexture = 6;
+    private Allocation mExportVar_gSelectedIconTexture;
+    public void set_gSelectedIconTexture(Allocation v) {
+        mExportVar_gSelectedIconTexture = v;
+        setVar(mExportVarIdx_gSelectedIconTexture, (v == null) ? 0 : v.getID());
+    }
+
+    public Allocation get_gSelectedIconTexture() {
+        return mExportVar_gSelectedIconTexture;
+    }
+
+    private final static int mExportVarIdx_gHomeButton = 7;
+    private Allocation mExportVar_gHomeButton;
+    public void set_gHomeButton(Allocation v) {
+        mExportVar_gHomeButton = v;
+        setVar(mExportVarIdx_gHomeButton, (v == null) ? 0 : v.getID());
+    }
+
+    public Allocation get_gHomeButton() {
+        return mExportVar_gHomeButton;
+    }
+
+    private final static int mExportVarIdx_gPFTexNearest = 8;
+    private ProgramFragment mExportVar_gPFTexNearest;
+    public void set_gPFTexNearest(ProgramFragment v) {
+        mExportVar_gPFTexNearest = v;
+        setVar(mExportVarIdx_gPFTexNearest, (v == null) ? 0 : v.getID());
+    }
+
+    public ProgramFragment get_gPFTexNearest() {
+        return mExportVar_gPFTexNearest;
+    }
+
+    private final static int mExportVarIdx_gPFTexMip = 9;
+    private ProgramFragment mExportVar_gPFTexMip;
+    public void set_gPFTexMip(ProgramFragment v) {
+        mExportVar_gPFTexMip = v;
+        setVar(mExportVarIdx_gPFTexMip, (v == null) ? 0 : v.getID());
+    }
+
+    public ProgramFragment get_gPFTexMip() {
+        return mExportVar_gPFTexMip;
+    }
+
+    private final static int mExportVarIdx_gPFTexMipAlpha = 10;
+    private ProgramFragment mExportVar_gPFTexMipAlpha;
+    public void set_gPFTexMipAlpha(ProgramFragment v) {
+        mExportVar_gPFTexMipAlpha = v;
+        setVar(mExportVarIdx_gPFTexMipAlpha, (v == null) ? 0 : v.getID());
+    }
+
+    public ProgramFragment get_gPFTexMipAlpha() {
+        return mExportVar_gPFTexMipAlpha;
+    }
+
+    private final static int mExportVarIdx_gPVCurve = 11;
+    private ProgramVertex mExportVar_gPVCurve;
+    public void set_gPVCurve(ProgramVertex v) {
+        mExportVar_gPVCurve = v;
+        setVar(mExportVarIdx_gPVCurve, (v == null) ? 0 : v.getID());
+    }
+
+    public ProgramVertex get_gPVCurve() {
+        return mExportVar_gPVCurve;
+    }
+
+    private final static int mExportVarIdx_gPS = 12;
+    private ProgramStore mExportVar_gPS;
+    public void set_gPS(ProgramStore v) {
+        mExportVar_gPS = v;
+        setVar(mExportVarIdx_gPS, (v == null) ? 0 : v.getID());
+    }
+
+    public ProgramStore get_gPS() {
+        return mExportVar_gPS;
+    }
+
+    private final static int mExportVarIdx_gSMCell = 13;
+    private SimpleMesh mExportVar_gSMCell;
+    public void set_gSMCell(SimpleMesh v) {
+        mExportVar_gSMCell = v;
+        setVar(mExportVarIdx_gSMCell, (v == null) ? 0 : v.getID());
+    }
+
+    public SimpleMesh get_gSMCell() {
+        return mExportVar_gSMCell;
+    }
+
+    private final static int mExportVarIdx_gIconIDs = 14;
+    private Allocation mExportVar_gIconIDs;
+    public void bind_gIconIDs(Allocation v) {
+        mExportVar_gIconIDs = v;
+        if(v == null) bindAllocation(null, mExportVarIdx_gIconIDs);
+        else bindAllocation(v, mExportVarIdx_gIconIDs);
+    }
+
+    public Allocation get_gIconIDs() {
+        return mExportVar_gIconIDs;
+    }
+
+    private final static int mExportVarIdx_gLabelIDs = 15;
+    private Allocation mExportVar_gLabelIDs;
+    public void bind_gLabelIDs(Allocation v) {
+        mExportVar_gLabelIDs = v;
+        if(v == null) bindAllocation(null, mExportVarIdx_gLabelIDs);
+        else bindAllocation(v, mExportVarIdx_gLabelIDs);
+    }
+
+    public Allocation get_gLabelIDs() {
+        return mExportVar_gLabelIDs;
+    }
+
+    private final static int mExportVarIdx_vpConstants = 16;
+    private ScriptField_VpConsts mExportVar_vpConstants;
+    public void bind_vpConstants(ScriptField_VpConsts v) {
+        mExportVar_vpConstants = v;
+        if(v == null) bindAllocation(null, mExportVarIdx_vpConstants);
+        else bindAllocation(v.getAllocation(), mExportVarIdx_vpConstants);
+    }
+
+    public ScriptField_VpConsts get_vpConstants() {
+        return mExportVar_vpConstants;
+    }
+
+    private final static int mExportVarIdx_gTargetPos = 17;
+    private float mExportVar_gTargetPos;
+    public void set_gTargetPos(float v) {
+        mExportVar_gTargetPos = v;
+        setVar(mExportVarIdx_gTargetPos, v);
+    }
+
+    public float get_gTargetPos() {
+        return mExportVar_gTargetPos;
+    }
+
+    private final static int mExportFuncIdx_move = 0;
+    public void invoke_move(float newPos) {
+        FieldPacker move_fp = new FieldPacker(4);
+        move_fp.addF32(newPos);
+        invoke(mExportFuncIdx_move, move_fp);
+    }
+
+    private final static int mExportFuncIdx_moveTo = 1;
+    public void invoke_moveTo(float targetPos) {
+        FieldPacker moveTo_fp = new FieldPacker(4);
+        moveTo_fp.addF32(targetPos);
+        invoke(mExportFuncIdx_moveTo, moveTo_fp);
+    }
+
+    private final static int mExportFuncIdx_setZoom = 2;
+    public void invoke_setZoom(float z, int animate) {
+        FieldPacker setZoom_fp = new FieldPacker(8);
+        setZoom_fp.addF32(z);
+        setZoom_fp.addI32(animate);
+        invoke(mExportFuncIdx_setZoom, setZoom_fp);
+    }
+
+    private final static int mExportFuncIdx_fling = 3;
+    public void invoke_fling(float newPos, float vel) {
+        FieldPacker fling_fp = new FieldPacker(8);
+        fling_fp.addF32(newPos);
+        fling_fp.addF32(vel);
+        invoke(mExportFuncIdx_fling, fling_fp);
+    }
+
+}
+
diff --git a/src/com/android/launcher2/ScriptField_VpConsts.java b/src/com/android/launcher2/ScriptField_VpConsts.java
new file mode 100644
index 0000000..b5e41b7
--- /dev/null
+++ b/src/com/android/launcher2/ScriptField_VpConsts.java
@@ -0,0 +1,83 @@
+/*
+ * 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.renderscript.*;
+import android.content.res.Resources;
+import android.util.Log;
+
+public class ScriptField_VpConsts extends android.renderscript.Script.FieldBase {
+    static public class Item {
+        public static final int sizeof = 48;
+
+        Float4 Position;
+        Float4 ScaleOffset;
+        Float2 BendPos;
+        Float2 ImgSize;
+
+        Item() {
+            Position = new Float4();
+            ScaleOffset = new Float4();
+            BendPos = new Float2();
+            ImgSize = new Float2();
+        }
+
+    }
+
+    private Item mItemArray[];
+    private FieldPacker mIOBuffer;
+    public  ScriptField_VpConsts(RenderScript rs, int count) {
+        mItemArray = null;
+        mIOBuffer = null;
+        {
+            Element.Builder eb = new Element.Builder(rs);
+            eb.add(Element.createVector(rs, Element.DataType.FLOAT_32, 4), "Position");
+            eb.add(Element.createVector(rs, Element.DataType.FLOAT_32, 4), "ScaleOffset");
+            eb.add(Element.createVector(rs, Element.DataType.FLOAT_32, 2), "BendPos");
+            eb.add(Element.createVector(rs, Element.DataType.FLOAT_32, 2), "ImgSize");
+            mElement = eb.create();
+        }
+
+        init(rs, count);
+    }
+
+    private void copyToArray(Item i, int index) {
+        if (mIOBuffer == null) mIOBuffer = new FieldPacker(Item.sizeof * mType.getX() /* count */);
+        mIOBuffer.reset(index * Item.sizeof);
+        mIOBuffer.addF32(i.Position);
+        mIOBuffer.addF32(i.ScaleOffset);
+        mIOBuffer.addF32(i.BendPos);
+        mIOBuffer.addF32(i.ImgSize);
+    }
+
+    public void set(Item i, int index, boolean copyNow) {
+        if (mItemArray == null) mItemArray = new Item[mType.getX() /* count */];
+        mItemArray[index] = i;
+        if (copyNow)  {
+            copyToArray(i, index);
+            mAllocation.subData1D(index /** Item.sizeof*/, 1/*Item.sizeof*/, mIOBuffer.getData());
+        }
+
+    }
+
+    public void copyAll() {
+        for (int ct=0; ct < mItemArray.length; ct++) copyToArray(mItemArray[ct], ct);
+        mAllocation.data(mIOBuffer.getData());
+    }
+
+}
+
diff --git a/src/com/android/launcher2/WidgetChooser.java b/src/com/android/launcher2/WidgetChooser.java
new file mode 100644
index 0000000..fc354d7
--- /dev/null
+++ b/src/com/android/launcher2/WidgetChooser.java
@@ -0,0 +1,94 @@
+package com.android.launcher2;
+
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.Gallery;
+
+public class WidgetChooser extends Gallery
+    implements Gallery.OnItemLongClickListener, DragSource {
+
+    Context mContext;
+
+    private Launcher mLauncher;
+    private DragController mDragController;
+    private WidgetGalleryAdapter mWidgetGalleryAdapter;
+
+    private int mMotionDownRawX;
+    private int mMotionDownRawY;
+
+    public WidgetChooser(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setLongClickable(true);
+        setOnItemLongClickListener(this);
+        mContext = context;
+
+        setCallbackDuringFling(false);
+
+        mWidgetGalleryAdapter = new WidgetGalleryAdapter(context);
+        setAdapter(mWidgetGalleryAdapter);
+    }
+
+    public void onDropCompleted(View target, boolean success) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setDragController(DragController dragger) {
+        mDragController = dragger;
+    }
+
+    public void setLauncher(Launcher launcher) {
+        mLauncher = launcher;
+    }
+
+    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+        AppWidgetProviderInfo info = (AppWidgetProviderInfo)mWidgetGalleryAdapter.getItem(position);
+        try {
+            Resources r = mContext.getPackageManager().getResourcesForApplication(info.provider.getPackageName());
+
+            Bitmap bmp = BitmapFactory.decodeResource(r, info.icon);
+            final int w = bmp.getWidth();
+            final int h = bmp.getHeight();
+
+            // We don't really have an accurate location to use.  This will do.
+            int screenX = mMotionDownRawX - (w / 2);
+            int screenY = mMotionDownRawY - h;
+
+            LauncherAppWidgetInfo dragInfo = new LauncherAppWidgetInfo(-1);
+            dragInfo.providerName = info.provider;
+            mDragController.startDrag(bmp, screenX, screenY,
+                    0, 0, w, h, this, dragInfo, DragController.DRAG_ACTION_COPY);
+            return true;
+        } catch (NameNotFoundException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN && mLauncher.isAllAppsVisible()) {
+            return false;
+        }
+
+        super.onTouchEvent(ev);
+
+        int x = (int) ev.getX();
+        int y = (int) ev.getY();
+
+        switch (ev.getAction()) {
+        case MotionEvent.ACTION_DOWN:
+            mMotionDownRawX = (int) ev.getRawX();
+            mMotionDownRawY = (int) ev.getRawY();
+        }
+        return true;
+    }
+}
diff --git a/src/com/android/launcher2/WidgetGalleryAdapter.java b/src/com/android/launcher2/WidgetGalleryAdapter.java
new file mode 100644
index 0000000..bdb3551
--- /dev/null
+++ b/src/com/android/launcher2/WidgetGalleryAdapter.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher2;
+
+import com.android.launcher.R;
+
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+
+import java.util.List;
+
+public class WidgetGalleryAdapter extends BaseAdapter {
+    private LayoutInflater mLayoutInflater;
+    private PackageManager mPackageManager;
+    private List<AppWidgetProviderInfo> mWidgets;
+    private static final String TAG = "Launcher.WidgetGalleryAdapter";
+
+    WidgetGalleryAdapter(Context context) {
+        mLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
+        mWidgets = widgetManager.getInstalledProviders();
+        mPackageManager = context.getPackageManager();
+    }
+
+    public int getCount() {
+        return mWidgets.size();
+    }
+
+    public Object getItem(int position) {
+        return mWidgets.get(position);
+    }
+
+    public long getItemId(int position) {
+        return position;
+    }
+
+    public View getView(int position, View convertView, ViewGroup parent) {
+        ImageView imageView;
+
+        if (convertView == null) {
+            imageView = (ImageView) mLayoutInflater.inflate(R.layout.widget_item, parent, false);
+        } else {
+            imageView = (ImageView) convertView;
+        }
+
+        AppWidgetProviderInfo info = mWidgets.get(position);
+        Drawable image = null;
+        if (info.previewImage != 0) {
+            image = mPackageManager.getDrawable(
+                    info.provider.getPackageName(), info.previewImage, null);
+            if (image == null) {
+                Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon)
+                        + " for provider: " + info.provider);
+            }
+        }
+        if (image == null) {
+            image = mPackageManager.getDrawable(info.provider.getPackageName(), info.icon, null);
+        }
+        imageView.setImageDrawable(image);
+
+        return imageView;
+    }
+}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index c337c30..c56a313 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -16,8 +16,7 @@
 
 package com.android.launcher2;
 
-import java.util.ArrayList;
-import java.util.HashSet;
+import com.android.launcher.R;
 
 import android.app.WallpaperManager;
 import android.appwidget.AppWidgetManager;
@@ -47,7 +46,8 @@
 import android.widget.Scroller;
 import android.widget.TextView;
 
-import com.android.launcher.R;
+import java.util.ArrayList;
+import java.util.HashSet;
 
 /**
  * The workspace is a wide area with a wallpaper and a finite number of screens. Each
@@ -450,8 +450,10 @@
             postInvalidate();
         } else if (mNextScreen != INVALID_SCREEN) {
             mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1));
-            mPreviousIndicator.setLevel(mCurrentScreen);
-            mNextIndicator.setLevel(mCurrentScreen);
+            if (mPreviousIndicator != null) {
+                mPreviousIndicator.setLevel(mCurrentScreen);
+                mNextIndicator.setLevel(mCurrentScreen);
+            }
             Launcher.setScreen(mCurrentScreen);
             mNextScreen = INVALID_SCREEN;
             clearChildrenCache();
@@ -963,8 +965,10 @@
 
         mNextScreen = whichScreen;
 
+        if (mPreviousIndicator != null) {
         mPreviousIndicator.setLevel(mNextScreen);
         mNextIndicator.setLevel(mNextScreen);
+        }
 
         View focusedChild = getFocusedChild();
         if (focusedChild != null && whichScreen != mCurrentScreen &&
@@ -1098,7 +1102,7 @@
         // Drag from somewhere else
         ItemInfo info = (ItemInfo) dragInfo;
 
-        View view;
+        View view = null;
 
         switch (info.itemType) {
         case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
@@ -1113,23 +1117,31 @@
             view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
                     (ViewGroup) getChildAt(mCurrentScreen), ((UserFolderInfo) info));
             break;
+        case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+            cellLayout.setTagToCellInfoForPoint(x, y);
+            mLauncher.addAppWidgetFromDrop(((LauncherAppWidgetInfo)dragInfo).providerName, cellLayout.getTag());
+            break;
         default:
             throw new IllegalStateException("Unknown item type: " + info.itemType);
         }
 
-        cellLayout.addView(view, insertAtFirst ? 0 : -1);
-        view.setHapticFeedbackEnabled(false);
-        view.setOnLongClickListener(mLongClickListener);
-        if (view instanceof DropTarget) {
-            mDragController.addDropTarget((DropTarget) view);
+        // addAppWidgetFromDrop already took care of attaching the widget view to the appropriate cell
+        // TODO why aren't we calling addInScreen here?
+        if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {
+            cellLayout.addView(view, insertAtFirst ? 0 : -1);
+            view.setHapticFeedbackEnabled(false);
+            view.setOnLongClickListener(mLongClickListener);
+            if (view instanceof DropTarget) {
+                mDragController.addDropTarget((DropTarget) view);
+            }
+
+            mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell);
+            cellLayout.onDropChild(view, mTargetCell);
+            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
+
+            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
+                    LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY);
         }
-
-        mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell);
-        cellLayout.onDropChild(view, mTargetCell);
-        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
-
-        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
-                LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY);
     }
     
     /**