Merge "Request no title on addbookmark page."
diff --git a/res/drawable-hdpi/bg_bookmark_widget_holo.9.png b/res/drawable-hdpi/bg_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..8a23d6f
--- /dev/null
+++ b/res/drawable-hdpi/bg_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_ic_back_bookmark_widget_holo_dark.png b/res/drawable-hdpi/btn_ic_back_bookmark_widget_holo_dark.png
new file mode 100644
index 0000000..447f3af
--- /dev/null
+++ b/res/drawable-hdpi/btn_ic_back_bookmark_widget_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_ic_bookmark_bookmark_widget_holo_dark.png b/res/drawable-hdpi/btn_ic_bookmark_bookmark_widget_holo_dark.png
new file mode 100644
index 0000000..1c10e98
--- /dev/null
+++ b/res/drawable-hdpi/btn_ic_bookmark_bookmark_widget_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/gradient_overlay_bg_bookmark_widget_holo.png b/res/drawable-hdpi/gradient_overlay_bg_bookmark_widget_holo.png
new file mode 100644
index 0000000..1a84583
--- /dev/null
+++ b/res/drawable-hdpi/gradient_overlay_bg_bookmark_widget_holo.png
Binary files differ
diff --git a/res/drawable-hdpi/header_bg_bookmark_widget_holo.png b/res/drawable-hdpi/header_bg_bookmark_widget_holo.png
new file mode 100644
index 0000000..8d0706a
--- /dev/null
+++ b/res/drawable-hdpi/header_bg_bookmark_widget_holo.png
Binary files differ
diff --git a/res/drawable-hdpi/header_row_focused_bookmark_widget_holo.9.png b/res/drawable-hdpi/header_row_focused_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..b3406fd
--- /dev/null
+++ b/res/drawable-hdpi/header_row_focused_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/header_row_press_bookmark_widget_holo.9.png b/res/drawable-hdpi/header_row_press_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..2a6ff60
--- /dev/null
+++ b/res/drawable-hdpi/header_row_press_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_browser_bookmark_widget_holo.png b/res/drawable-hdpi/ic_browser_bookmark_widget_holo.png
new file mode 100644
index 0000000..1fb772e
--- /dev/null
+++ b/res/drawable-hdpi/ic_browser_bookmark_widget_holo.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_folder_bookmark_widget_holo_dark.png b/res/drawable-hdpi/ic_folder_bookmark_widget_holo_dark.png
new file mode 100644
index 0000000..8a167e2
--- /dev/null
+++ b/res/drawable-hdpi/ic_folder_bookmark_widget_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/list_div_bookmark_widget_holo.9.png b/res/drawable-hdpi/list_div_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..65f42ba
--- /dev/null
+++ b/res/drawable-hdpi/list_div_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/list_div_top_btm_bookmark_widget_holo.9.png b/res/drawable-hdpi/list_div_top_btm_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..e9165d2
--- /dev/null
+++ b/res/drawable-hdpi/list_div_top_btm_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/row_activated_bookmark_widget_holo.9.png b/res/drawable-hdpi/row_activated_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..b6cfc4c
--- /dev/null
+++ b/res/drawable-hdpi/row_activated_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/stripes_overlay_bg_bookmark_widget_holo.png b/res/drawable-hdpi/stripes_overlay_bg_bookmark_widget_holo.png
new file mode 100644
index 0000000..95d24fa
--- /dev/null
+++ b/res/drawable-hdpi/stripes_overlay_bg_bookmark_widget_holo.png
Binary files differ
diff --git a/res/drawable-mdpi/bg_bookmark_widget_holo.9.png b/res/drawable-mdpi/bg_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..ac56bbe
--- /dev/null
+++ b/res/drawable-mdpi/bg_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/btn_ic_back_bookmark_widget_holo_dark.png b/res/drawable-mdpi/btn_ic_back_bookmark_widget_holo_dark.png
new file mode 100644
index 0000000..d8697b8
--- /dev/null
+++ b/res/drawable-mdpi/btn_ic_back_bookmark_widget_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/btn_ic_bookmark_bookmark_widget_holo_dark.png b/res/drawable-mdpi/btn_ic_bookmark_bookmark_widget_holo_dark.png
new file mode 100644
index 0000000..21a2cc3
--- /dev/null
+++ b/res/drawable-mdpi/btn_ic_bookmark_bookmark_widget_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/gradient_overlay_bg_bookmark_widget_holo.png b/res/drawable-mdpi/gradient_overlay_bg_bookmark_widget_holo.png
new file mode 100644
index 0000000..1673338
--- /dev/null
+++ b/res/drawable-mdpi/gradient_overlay_bg_bookmark_widget_holo.png
Binary files differ
diff --git a/res/drawable-mdpi/header_bg_bookmark_widget_holo.png b/res/drawable-mdpi/header_bg_bookmark_widget_holo.png
new file mode 100644
index 0000000..9c3f7a6
--- /dev/null
+++ b/res/drawable-mdpi/header_bg_bookmark_widget_holo.png
Binary files differ
diff --git a/res/drawable-mdpi/header_row_focused_bookmark_widget_holo.9.png b/res/drawable-mdpi/header_row_focused_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..b745159
--- /dev/null
+++ b/res/drawable-mdpi/header_row_focused_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/header_row_press_bookmark_widget_holo.9.png b/res/drawable-mdpi/header_row_press_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..2e8874e
--- /dev/null
+++ b/res/drawable-mdpi/header_row_press_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_browser_bookmark_widget_holo.png b/res/drawable-mdpi/ic_browser_bookmark_widget_holo.png
new file mode 100644
index 0000000..0d9e49d
--- /dev/null
+++ b/res/drawable-mdpi/ic_browser_bookmark_widget_holo.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_folder_bookmark_widget_holo_dark.png b/res/drawable-mdpi/ic_folder_bookmark_widget_holo_dark.png
new file mode 100644
index 0000000..910e9ec
--- /dev/null
+++ b/res/drawable-mdpi/ic_folder_bookmark_widget_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pie_back.png b/res/drawable-mdpi/ic_pie_back.png
new file mode 100644
index 0000000..daddaea
--- /dev/null
+++ b/res/drawable-mdpi/ic_pie_back.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pie_bookmarks.png b/res/drawable-mdpi/ic_pie_bookmarks.png
new file mode 100644
index 0000000..ffa430d
--- /dev/null
+++ b/res/drawable-mdpi/ic_pie_bookmarks.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pie_close_tab.png b/res/drawable-mdpi/ic_pie_close_tab.png
new file mode 100644
index 0000000..62396f4
--- /dev/null
+++ b/res/drawable-mdpi/ic_pie_close_tab.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pie_forward.png b/res/drawable-mdpi/ic_pie_forward.png
new file mode 100644
index 0000000..bd8dcac
--- /dev/null
+++ b/res/drawable-mdpi/ic_pie_forward.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pie_more.png b/res/drawable-mdpi/ic_pie_more.png
new file mode 100644
index 0000000..c96c6a4
--- /dev/null
+++ b/res/drawable-mdpi/ic_pie_more.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pie_new_tab.png b/res/drawable-mdpi/ic_pie_new_tab.png
new file mode 100644
index 0000000..206675a
--- /dev/null
+++ b/res/drawable-mdpi/ic_pie_new_tab.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pie_refresh.png b/res/drawable-mdpi/ic_pie_refresh.png
new file mode 100644
index 0000000..5980f8b
--- /dev/null
+++ b/res/drawable-mdpi/ic_pie_refresh.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pie_search.png b/res/drawable-mdpi/ic_pie_search.png
new file mode 100644
index 0000000..6981697
--- /dev/null
+++ b/res/drawable-mdpi/ic_pie_search.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_pie_tabs.png b/res/drawable-mdpi/ic_pie_tabs.png
new file mode 100644
index 0000000..fda262a
--- /dev/null
+++ b/res/drawable-mdpi/ic_pie_tabs.png
Binary files differ
diff --git a/res/drawable-mdpi/list_div_bookmark_widget_holo.9.png b/res/drawable-mdpi/list_div_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..fc1946f
--- /dev/null
+++ b/res/drawable-mdpi/list_div_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/list_div_top_btm_bookmark_widget_holo.9.png b/res/drawable-mdpi/list_div_top_btm_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..309b608
--- /dev/null
+++ b/res/drawable-mdpi/list_div_top_btm_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/row_activated_bookmark_widget_holo.9.png b/res/drawable-mdpi/row_activated_bookmark_widget_holo.9.png
new file mode 100644
index 0000000..ed8760f
--- /dev/null
+++ b/res/drawable-mdpi/row_activated_bookmark_widget_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/stripes_overlay_bg_bookmark_widget_holo.png b/res/drawable-mdpi/stripes_overlay_bg_bookmark_widget_holo.png
new file mode 100644
index 0000000..8c9614b
--- /dev/null
+++ b/res/drawable-mdpi/stripes_overlay_bg_bookmark_widget_holo.png
Binary files differ
diff --git a/res/drawable/preview.png b/res/drawable/preview.png
index b363ab5..b239716 100644
--- a/res/drawable/preview.png
+++ b/res/drawable/preview.png
Binary files differ
diff --git a/res/drawable/widget_background.xml b/res/drawable/widget_background.xml
new file mode 100644
index 0000000..de6c3f2
--- /dev/null
+++ b/res/drawable/widget_background.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+
+<layer-list
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <bitmap
+            android:src="@drawable/gradient_overlay_bg_bookmark_widget_holo"
+            android:gravity="top|fill_horizontal" />
+    </item>
+    <item>
+        <bitmap
+            android:src="@drawable/stripes_overlay_bg_bookmark_widget_holo"
+            android:gravity="top|fill_horizontal" />
+    </item>
+</layer-list>
diff --git a/res/drawable/widget_header_selector.xml b/res/drawable/widget_header_selector.xml
new file mode 100644
index 0000000..0e6bc47
--- /dev/null
+++ b/res/drawable/widget_header_selector.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:exitFadeDuration="@android:integer/config_mediumAnimTime">
+    <item
+        android:state_window_focused="false"
+        android:drawable="@android:color/transparent" />
+    <item
+        android:state_focused="true"
+        android:state_pressed="true"
+        android:drawable="@drawable/header_row_press_bookmark_widget_holo" />
+    <item
+        android:state_focused="false"
+        android:state_pressed="true"
+        android:drawable="@drawable/header_row_press_bookmark_widget_holo" />
+    <item
+        android:state_focused="true"
+        android:drawable="@drawable/header_row_focused_bookmark_widget_holo" />
+</selector>
diff --git a/res/layout/bookmarklistwidget.xml b/res/layout/bookmarklistwidget.xml
index 17aee1d..f3857f8 100644
--- a/res/layout/bookmarklistwidget.xml
+++ b/res/layout/bookmarklistwidget.xml
@@ -13,41 +13,87 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<LinearLayout
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:background="@null"
-    android:focusable="true"
-    android:clickable="true">
+    android:paddingTop="4dip"
+    android:paddingBottom="20dip"
+    android:paddingLeft="12dip"
+    android:paddingRight="12dip">
     <LinearLayout
-        android:id="@+id/header"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        android:padding="8dip"
-        android:background="@color/bookmarkWidgetHeader">
-        <ImageView
-            android:id="@+id/logo"
-            android:layout_width="32dp"
-            android:layout_height="32dp"
-            android:src="@mipmap/ic_launcher_browser" />
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical"
-            android:text="@string/tab_bookmarks"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:paddingLeft="8dip" />
-    </LinearLayout>
-    <ListView
-        android:id="@+id/bookmarks_list"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="@color/bookmarkWidgetItemBackground"
-        android:cacheColorHint="@color/bookmarkWidgetItemBackground"
-        android:dividerHeight="1px"
-        android:divider="@color/bookmarkWidgetDivider" />
-</LinearLayout>
+        android:orientation="vertical"
+        android:background="@drawable/bg_bookmark_widget_holo"
+        android:paddingLeft="0dip"
+        android:paddingRight="0dip"
+        android:paddingBottom="0dip">
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="42dip"
+            android:orientation="horizontal"
+            android:background="@drawable/header_bg_bookmark_widget_holo"
+            android:layout_marginLeft="5dip"
+            android:layout_marginRight="5dip">
+            <LinearLayout
+                android:id="@+id/header_browser"
+                android:layout_width="0dip"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:orientation="horizontal"
+                android:paddingLeft="16dip"
+                android:focusable="true"
+                android:clickable="true"
+                android:background="@drawable/widget_header_selector">
+                <ImageView
+                    android:id="@+id/logo"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical"
+                    android:src="@drawable/ic_browser_bookmark_widget_holo" />
+                <TextView
+                    android:layout_width="0dip"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:layout_gravity="center_vertical"
+                    android:text="@string/application_name"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:textStyle="bold"
+                    android:paddingLeft="8dip" />
+            </LinearLayout>
+            <ImageView
+                android:id="@+id/header_bookmarks"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:src="@drawable/btn_ic_bookmark_bookmark_widget_holo_dark"
+                android:scaleType="centerInside"
+                android:focusable="true"
+                android:clickable="true"
+                android:background="@drawable/widget_header_selector"
+                android:paddingLeft="8dip"
+                android:paddingRight="8dip" />
+        </LinearLayout>
+        <ImageView android:background="@drawable/list_div_top_btm_bookmark_widget_holo"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="2dip"
+            android:layout_marginRight="2dip" />
+        <ListView
+            android:id="@+id/bookmarks_list"
+            android:layout_width="match_parent"
+            android:layout_height="0dip"
+            android:layout_weight="1"
+            android:background="@drawable/widget_background"
+            android:cacheColorHint="@android:color/transparent"
+            android:divider="@drawable/list_div_bookmark_widget_holo"
+            android:layout_marginLeft="5dip"
+            android:layout_marginRight="5dip" />
+        <ImageView android:background="@drawable/list_div_top_btm_bookmark_widget_holo"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_marginLeft="2dip"
+            android:layout_marginRight="2dip"
+            android:layout_marginBottom="2dip" />
+    </LinearLayout>
+</FrameLayout>
diff --git a/res/layout/bookmarklistwidget_item.xml b/res/layout/bookmarklistwidget_item.xml
index 9e41d39..039bc2c 100644
--- a/res/layout/bookmarklistwidget_item.xml
+++ b/res/layout/bookmarklistwidget_item.xml
@@ -18,23 +18,23 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/list_item"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:minHeight="@dimen/widgetItemMinHeight"
+    android:layout_height="48dp"
     android:orientation="horizontal"
-    android:padding="8dip"
-    android:background="@color/bookmarkWidgetFolderBackground">
+    android:background="@drawable/row_activated_bookmark_widget_holo">
     <ImageView
         android:id="@+id/thumb"
         android:src="@drawable/browser_thumbnail"
-        android:layout_height="24dp"
-        android:layout_width="24dp"
+        android:layout_height="32dp"
+        android:layout_width="32dp"
         android:layout_gravity="center_vertical"
+        android:layout_marginLeft="16dp"
         android:scaleType="fitXY"/>
     <TextView
         android:id="@+id/label"
-        android:layout_width="wrap_content"
+        android:layout_width="0dip"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
+        android:layout_weight="1"
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:paddingLeft="8dip"
         android:maxLines="1"
diff --git a/res/layout/url_bar.xml b/res/layout/url_bar.xml
index 61b03ed..884267e 100644
--- a/res/layout/url_bar.xml
+++ b/res/layout/url_bar.xml
@@ -48,7 +48,14 @@
             android:layout_weight="1.0"
             android:layout_marginLeft="16dip"
             android:orientation="horizontal"
-            android:background="@drawable/textfield_active_holo_dark">
+            android:background="@drawable/textfield_default_holo_dark">
+            <ImageView
+                android:id="@+id/voice_icon"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:src="@drawable/ic_search_light"
+                style="@style/HoloIcon"
+                android:visibility="gone" />
             <ImageView
                 android:id="@+id/lock"
                 android:layout_width="wrap_content"
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 5a5d255..31a8458 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -29,4 +29,6 @@
     <color name="bookmarkWidgetDivider">#383847</color>
     <color name="bookmarkWidgetItemBackground">#2b2b3c</color>
     <color name="bookmarkWidgetFolderBackground">#A0383847</color>
+    <color name="qc_slice_normal">#C0A0A0A0</color>
+    <color name="qc_slice_active">#C02090FF</color>
 </resources>
diff --git a/res/values/dimensions.xml b/res/values/dimensions.xml
index 7cfa3f6..a4ab90a 100644
--- a/res/values/dimensions.xml
+++ b/res/values/dimensions.xml
@@ -28,4 +28,7 @@
     <dimen name="widgetItemMinHeight">48dip</dimen>
     <dimen name="favicon_size">16dip</dimen>
     <dimen name="favicon_padded_size">20dip</dimen>
+    <dimen name="qc_radius">130dip</dimen>
+    <dimen name="qc_radius_inc">100dip</dimen>
+    <dimen name="qc_slop">15dip</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1c8b71c..383ac9c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -590,6 +590,13 @@
         <item>EUC-KR</item>
     </string-array>
     <string name="pref_default_text_encoding_default" translatable="false">Latin-1</string>
+    <!-- Title for lab settings [CHAR LIMIT=25] -->
+    <string name="pref_lab_title">Lab</string>
+    <!-- Title for lab quick controls feature [CHAR LIMIT=40] -->
+    <string name="pref_lab_quick_controls">Quick Controls</string>
+    <!-- Summary for lab quick controls feature [CHAR LIMIT=80] -->
+    <string name="pref_lab_quick_controls_summary">
+        Swipe thumb from left or right edge to access quick controls</string>
     <!-- Title for a dialog displayed when the browser has a data connectivity
             problem -->
     <string name="browserFrameNetworkErrorLabel">Data connectivity problem</string>
diff --git a/res/xml/lab_preferences.xml b/res/xml/lab_preferences.xml
new file mode 100644
index 0000000..2168471
--- /dev/null
+++ b/res/xml/lab_preferences.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen
+        xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <CheckBoxPreference
+        android:key="enable_quick_controls"
+        android:defaultValue="false"
+        android:title="@string/pref_lab_quick_controls"
+        android:summary="@string/pref_lab_quick_controls_summary" />
+
+</PreferenceScreen>
diff --git a/res/xml/preference_headers.xml b/res/xml/preference_headers.xml
index 1a54990..8533a3a 100644
--- a/res/xml/preference_headers.xml
+++ b/res/xml/preference_headers.xml
@@ -35,4 +35,9 @@
     <header android:fragment="com.android.browser.preferences.AdvancedPreferencesFragment"
         android:title="@string/pref_extras_title"
     />
+
+    <header android:fragment="com.android.browser.preferences.LabPreferencesFragment"
+        android:title="@string/pref_lab_title"
+    />
+
 </preference-headers>
diff --git a/src/com/android/browser/BaseUi.java b/src/com/android/browser/BaseUi.java
index 6b8b447..1e9038d 100644
--- a/src/com/android/browser/BaseUi.java
+++ b/src/com/android/browser/BaseUi.java
@@ -231,22 +231,10 @@
         mActiveTab = tab;
         attachTabToContentView(tab);
         setShouldShowErrorConsole(tab, mUiController.shouldShowErrorConsole());
-        WebView view = tab.getWebView();
-        // TabControl.setCurrentTab has been called before this,
-        // so the tab is guaranteed to have a webview
-        if (view == null) {
-            Log.e(LOGTAG, "active tab with no webview detected");
-            return;
-        }
-        view.setEmbeddedTitleBar(getEmbeddedTitleBar());
-        if (tab.isInVoiceSearchMode()) {
-            showVoiceTitleBar(tab.getVoiceDisplayTitle());
-        } else {
-            revertVoiceTitleBar(tab);
-        }
-        resetTitleIconAndProgress(tab);
-        updateLockIconToLatest(tab);
-        tab.getTopWindow().requestFocus();
+    }
+
+    Tab getActiveTab() {
+        return mActiveTab;
     }
 
     @Override
@@ -444,6 +432,9 @@
 
     @Override
     public void showComboView(boolean startWithHistory, Bundle extras) {
+        if (mComboView != null) {
+            return;
+        }
         mComboView = new CombinedBookmarkHistoryView(mActivity,
                 mUiController,
                 startWithHistory ?
diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java
index 8282eb0..ba5ba29 100644
--- a/src/com/android/browser/BrowserActivity.java
+++ b/src/com/android/browser/BrowserActivity.java
@@ -39,6 +39,8 @@
 
 public class BrowserActivity extends Activity {
 
+    public static final String ACTION_SHOW_BOOKMARKS = "show_bookmarks";
+    public static final String ACTION_SHOW_BROWSER = "show_browser";
     public static final String ACTION_RESTART = "--restart--";
     private static final String EXTRA_STATE = "state";
 
diff --git a/src/com/android/browser/BrowserBookmarksAdapter.java b/src/com/android/browser/BrowserBookmarksAdapter.java
index f587f01..c680a88 100644
--- a/src/com/android/browser/BrowserBookmarksAdapter.java
+++ b/src/com/android/browser/BrowserBookmarksAdapter.java
@@ -81,7 +81,7 @@
         tv.setText(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE));
         if (cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0) {
             // folder
-            favicon.setImageResource(R.drawable.ic_folder);
+            favicon.setImageResource(R.drawable.ic_folder_bookmark_widget_holo_dark);
         } else {
             byte[] faviconData = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_FAVICON);
             Bitmap faviconBitmap = null;
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index c030915..c39218c 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -369,7 +369,7 @@
         if (isFolder) {
             item.setUrl(null);
             Bitmap bitmap =
-                BitmapFactory.decodeResource(getResources(), R.drawable.ic_folder);
+                BitmapFactory.decodeResource(getResources(), R.drawable.ic_folder_bookmark_widget_holo_dark);
             item.setFavicon(bitmap);
             new LookupBookmarkCount(getActivity(), item)
                     .execute(cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID));
@@ -472,6 +472,7 @@
         }
         mCrumbs.setController(null);
         mCrumbs = null;
+        getLoaderManager().stopLoader(LOADER_BOOKMARKS);
     }
 
     @Override
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index 18feee9..c623012 100644
--- a/src/com/android/browser/BrowserHistoryPage.java
+++ b/src/com/android/browser/BrowserHistoryPage.java
@@ -209,8 +209,8 @@
         mEmptyView = root.findViewById(android.R.id.empty);
 
         // Start the loader
-        getLoaderManager().initLoader(LOADER_HISTORY, null, this);
-        getLoaderManager().initLoader(LOADER_MOST_VISITED, null, this);
+        getLoaderManager().restartLoader(LOADER_HISTORY, null, this);
+        getLoaderManager().restartLoader(LOADER_MOST_VISITED, null, this);
 
         // Register to receive icons in case they haven't all been loaded.
         CombinedBookmarkHistoryView.getIconListenerSet().addListener(mIconReceiver);
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 1f091e2..1b8acc6 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -117,6 +117,9 @@
     private boolean navDump = false;
     private boolean hardwareAccelerated = true;
 
+    // Lab settings
+    private boolean quickControls = false;
+
     // By default the error console is shown once the user navigates to about:debug.
     // The setting can be then toggled from the settings menu.
     private boolean showConsole = true;
@@ -167,6 +170,8 @@
     public final static String PREF_HARDWARE_ACCEL = "enable_hardware_accel";
     public final static String PREF_USER_AGENT = "user_agent";
 
+    public final static String PREF_QUICK_CONTROLS = "enable_quick_controls";
+
     private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; " +
             "U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/533.16 (KHTML, " +
             "like Gecko) Version/5.0 Safari/533.16";
@@ -490,6 +495,8 @@
             navDump = p.getBoolean("enable_nav_dump", navDump);
         }
 
+        quickControls = p.getBoolean(PREF_QUICK_CONTROLS, quickControls);
+
         // Only set these on startup if it is a dev build
         if (DEV_BUILD) {
             userAgent = Integer.parseInt(p.getString(PREF_USER_AGENT, "0"));
@@ -573,6 +580,10 @@
         return hardwareAccelerated;
     }
 
+    public boolean useQuickControls() {
+        return quickControls;
+    }
+
     public boolean showDebugSettings() {
         return showDebugSettings;
     }
@@ -836,6 +847,8 @@
         } else if (PREF_USER_AGENT.equals(key)) {
             userAgent = Integer.parseInt(p.getString(PREF_USER_AGENT, "0"));
             update();
+        } else if (PREF_QUICK_CONTROLS.equals(key)) {
+            quickControls = p.getBoolean(PREF_QUICK_CONTROLS, quickControls);
         }
     }
 }
diff --git a/src/com/android/browser/CombinedBookmarkHistoryView.java b/src/com/android/browser/CombinedBookmarkHistoryView.java
index e63d126..cc56489 100644
--- a/src/com/android/browser/CombinedBookmarkHistoryView.java
+++ b/src/com/android/browser/CombinedBookmarkHistoryView.java
@@ -43,7 +43,6 @@
 interface BookmarksHistoryCallbacks {
     public void onUrlSelected(String url, boolean newWindow);
     public void onRemoveParentChildRelationships();
-    public void onComboCanceled();
 }
 
 public class CombinedBookmarkHistoryView extends LinearLayout
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index e88a676..8483efa 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -36,7 +36,6 @@
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Picture;
@@ -51,10 +50,10 @@
 import android.preference.PreferenceActivity;
 import android.provider.Browser;
 import android.provider.BrowserContract;
-import android.provider.BrowserContract.History;
 import android.provider.BrowserContract.Images;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Intents.Insert;
+import android.speech.RecognizerIntent;
 import android.speech.RecognizerResultsIntent;
 import android.text.TextUtils;
 import android.util.Log;
@@ -94,6 +93,9 @@
         implements WebViewController, UiController {
 
     private static final String LOGTAG = "Controller";
+    private static final String SEND_APP_ID_EXTRA =
+        "android.speech.extras.SEND_APPLICATION_ID_EXTRA";
+
 
     // public message ids
     public final static int LOAD_URL = 1001;
@@ -316,6 +318,9 @@
         if (jsFlags.trim().length() != 0) {
             getCurrentWebView().setJsFlags(jsFlags);
         }
+        if (BrowserActivity.ACTION_SHOW_BOOKMARKS.equals(intent.getAction())) {
+            bookmarksOrHistoryPicker(false);
+        }
     }
 
     void setWebViewFactory(WebViewFactory factory) {
@@ -429,6 +434,8 @@
                     {
                         String url = (String) msg.getData().get("url");
                         String title = (String) msg.getData().get("title");
+                        String src = (String) msg.getData().get("src");
+                        if (url == "") url = src; // use image if no anchor
                         if (TextUtils.isEmpty(url)) {
                             break;
                         }
@@ -440,9 +447,11 @@
                         }
                         switch (msg.arg1) {
                             case R.id.open_context_menu_id:
-                            case R.id.view_image_context_menu_id:
                                 loadUrlFromContext(getCurrentTopWebView(), url);
                                 break;
+                            case R.id.view_image_context_menu_id:
+                                loadUrlFromContext(getCurrentTopWebView(), src);
+                                break;
                             case R.id.open_newtab_context_menu_id:
                                 final Tab parent = mTabControl.getCurrentTab();
                                 final Tab newTab = openTab(parent, url, false);
@@ -1009,6 +1018,16 @@
                 null, false);
     }
 
+    public void startVoiceSearch() {
+        Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
+        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
+                RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
+        intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
+                mActivity.getComponentName().flattenToString());
+        intent.putExtra(SEND_APP_ID_EXTRA, false);
+        mActivity.startActivity(intent);
+    }
+
     public void activateVoiceSearchMode(String title) {
         mUi.showVoiceTitleBar(title);
     }
@@ -1119,14 +1138,6 @@
     }
 
     /**
-     * callback from ComboPage when dismissed
-     */
-    @Override
-    public void onComboCanceled() {
-        removeComboView();
-    }
-
-    /**
      * dismiss the ComboPage
      */
     @Override
diff --git a/src/com/android/browser/IntentHandler.java b/src/com/android/browser/IntentHandler.java
index cbbc482..bd5595f 100644
--- a/src/com/android/browser/IntentHandler.java
+++ b/src/com/android/browser/IntentHandler.java
@@ -84,6 +84,14 @@
             // just resume the browser
             return;
         }
+        if (BrowserActivity.ACTION_SHOW_BOOKMARKS.equals(action)) {
+            mController.bookmarksOrHistoryPicker(false);
+            return;
+        }
+        if (BrowserActivity.ACTION_SHOW_BROWSER.equals(action)) {
+            mController.removeComboView();
+            return;
+        }
         // In case the SearchDialog is open.
         ((SearchManager) mActivity.getSystemService(Context.SEARCH_SERVICE))
                 .stopSearch();
diff --git a/src/com/android/browser/PhoneUi.java b/src/com/android/browser/PhoneUi.java
index 66656cf..e35e624 100644
--- a/src/com/android/browser/PhoneUi.java
+++ b/src/com/android/browser/PhoneUi.java
@@ -19,6 +19,7 @@
 import android.app.Activity;
 import android.content.Context;
 import android.graphics.PixelFormat;
+import android.util.Log;
 import android.view.ActionMode;
 import android.view.Gravity;
 import android.view.Menu;
@@ -118,6 +119,27 @@
     }
 
     @Override
+    public void setActiveTab(Tab tab) {
+        super.setActiveTab(tab);
+        WebView view = tab.getWebView();
+        // TabControl.setCurrentTab has been called before this,
+        // so the tab is guaranteed to have a webview
+        if (view == null) {
+            Log.e(LOGTAG, "active tab with no webview detected");
+            return;
+        }
+        view.setEmbeddedTitleBar(getEmbeddedTitleBar());
+        if (tab.isInVoiceSearchMode()) {
+            showVoiceTitleBar(tab.getVoiceDisplayTitle());
+        } else {
+            revertVoiceTitleBar(tab);
+        }
+        resetTitleIconAndProgress(tab);
+        updateLockIconToLatest(tab);
+        tab.getTopWindow().requestFocus();
+    }
+
+    @Override
     protected void attachFakeTitleBar(WebView mainView) {
         WindowManager manager = (WindowManager)
                 mActivity.getSystemService(Context.WINDOW_SERVICE);
diff --git a/src/com/android/browser/PieControl.java b/src/com/android/browser/PieControl.java
new file mode 100644
index 0000000..210e9ea
--- /dev/null
+++ b/src/com/android/browser/PieControl.java
@@ -0,0 +1,151 @@
+/*
+ * 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.browser;
+
+import com.android.browser.view.PieMenu;
+
+import android.app.Activity;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup.LayoutParams;
+import android.webkit.WebView;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * controller for Quick Controls pie menu
+ */
+public class PieControl implements OnClickListener, PieMenu.PieController {
+
+    private Activity mActivity;
+    private UiController mUiController;
+    private XLargeUi mUi;
+    private PieMenu mPie;
+    private ImageView mBack;
+    private ImageView mForward;
+    private ImageView mRefresh;
+    private ImageView mUrl;
+    private ImageView mOptions;
+    private ImageView mBookmarks;
+    private ImageView mNewTab;
+    private ImageView mClose;
+
+    private Map<View,Tab> mTabItems;
+
+    boolean mNewTabMode = true;
+
+    public PieControl(Activity activity, UiController controller, XLargeUi ui) {
+        mActivity = activity;
+        mUiController = controller;
+        mUi = ui;
+        mTabItems = new HashMap<View, Tab>();
+    }
+
+    protected void attachToContainer(FrameLayout container) {
+        if (mPie == null) {
+            mPie = new PieMenu(mActivity);
+            LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
+                    LayoutParams.MATCH_PARENT);
+            mPie.setLayoutParams(lp);
+            mForward = makeMenuView(R.drawable.ic_pie_forward);
+            mPie.addItem(mForward);
+            mRefresh = makeMenuView(R.drawable.ic_pie_refresh);
+            mPie.addItem(mRefresh);
+            mBack = makeMenuView(R.drawable.ic_pie_back);
+            mPie.addItem(mBack);
+            mUrl = makeMenuView(R.drawable.ic_pie_search);
+            mPie.addItem(mUrl);
+            mBookmarks = makeMenuView(R.drawable.ic_pie_bookmarks);
+            mPie.addItem(mBookmarks);
+            mNewTab = makeMenuView(R.drawable.ic_pie_new_tab);
+            mPie.addItem(mNewTab);
+            mOptions = makeMenuView(R.drawable.ic_pie_more);
+            mPie.addItem(mOptions);
+            setClickListener(mBack, mForward, mRefresh, mUrl, mOptions,
+                    mBookmarks, mNewTab);
+            mPie.setController(this);
+        }
+        container.addView(mPie);
+    }
+
+    protected void removeFromContainer(FrameLayout container) {
+        container.removeView(mPie);
+    }
+
+    private ImageView makeMenuView(int image) {
+        ImageView item = new ImageView(mActivity);
+        item.setImageResource(image);
+        LayoutParams lp = new LayoutParams(48, 48);
+        item.setLayoutParams(lp);
+        return item;
+    }
+
+    private void setClickListener(View... views) {
+        for (View view : views) {
+            view.setOnClickListener(this);
+        }
+    }
+
+    protected void forceToTop(FrameLayout container) {
+        if (mPie.getParent() != null) {
+            container.removeView(mPie);
+            container.addView(mPie);
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        mPie.show(false);
+        Tab tab = mUiController.getTabControl().getCurrentTab();
+        WebView web = tab.getWebView();
+        if (mBack == v) {
+            web.goBack();
+        } else if (mForward == v) {
+            web.goForward();
+        } else if (mRefresh == v) {
+            if (tab.inPageLoad()) {
+                web.stopLoading();
+            } else {
+                web.reload();
+            }
+        } else if (mUrl == v) {
+            mUi.showFakeTitleBarAndEdit();
+        } else if (mOptions == v) {
+            mActivity.openOptionsMenu();
+        } else if (mBookmarks == v) {
+            mUiController.bookmarksOrHistoryPicker(false);
+        } else if (mNewTab == v) {
+            mUiController.openTabToHomePage();
+        } else if (mClose == v) {
+            mUiController.closeCurrentTab();
+        } else {
+            Tab ntab = mTabItems.get(v);
+            if (ntab != null) {
+                mUiController.switchToTab(mUiController.getTabControl().getTabIndex(ntab));
+            }
+        }
+    }
+
+    @Override
+    public boolean onOpen() {
+        return true;
+    }
+
+}
diff --git a/src/com/android/browser/SuggestionsAdapter.java b/src/com/android/browser/SuggestionsAdapter.java
index 6473dfd..260da6e 100644
--- a/src/com/android/browser/SuggestionsAdapter.java
+++ b/src/com/android/browser/SuggestionsAdapter.java
@@ -23,7 +23,6 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.AsyncTask;
-import android.os.Handler;
 import android.provider.BrowserContract;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
@@ -69,6 +68,7 @@
     int mLinesPortrait;
     int mLinesLandscape;
     Object mResultsLock = new Object();
+    List<String> mVoiceResults;
 
     interface CompletionListener {
 
@@ -92,6 +92,11 @@
         addSource(new CombinedCursor());
     }
 
+    void setVoiceResults(List<String> voiceResults) {
+        mVoiceResults = voiceResults;
+        notifyDataSetChanged();
+    }
+
     public void setLandscapeMode(boolean mode) {
         mLandscapeMode = mode;
         notifyDataSetChanged();
@@ -132,11 +137,18 @@
 
     @Override
     public int getCount() {
+        if (mVoiceResults != null) {
+            return mVoiceResults.size();
+        }
         return (mMixedResults == null) ? 0 : mMixedResults.getLineCount();
     }
 
     @Override
     public SuggestItem getItem(int position) {
+        if (mVoiceResults != null) {
+            return new SuggestItem(mVoiceResults.get(position), null,
+                    TYPE_SEARCH);
+        }
         if (mMixedResults == null) {
             return null;
         }
@@ -176,7 +188,7 @@
         View s1 = view.findViewById(R.id.suggest1);
         View s2 = view.findViewById(R.id.suggest2);
         View div = view.findViewById(R.id.suggestion_divider);
-        if (mLandscapeMode) {
+        if (mLandscapeMode  && (mVoiceResults == null)) {
             SuggestItem item = getItem(position);
             div.setVisibility(View.VISIBLE);
             if (item != null) {
@@ -310,25 +322,30 @@
         @Override
         protected FilterResults performFiltering(CharSequence constraint) {
             FilterResults res = new FilterResults();
-            if (TextUtils.isEmpty(constraint)) {
-                res.count = 0;
-                res.values = null;
-                return res;
-            }
-            startSuggestionsAsync(constraint);
-            List<SuggestItem> filterResults = new ArrayList<SuggestItem>();
-            if (constraint != null) {
-                for (CursorSource sc : mSources) {
-                    sc.runQuery(constraint);
+            if (mVoiceResults == null) {
+                if (TextUtils.isEmpty(constraint)) {
+                    res.count = 0;
+                    res.values = null;
+                    return res;
                 }
-                mixResults(filterResults);
+                startSuggestionsAsync(constraint);
+                List<SuggestItem> filterResults = new ArrayList<SuggestItem>();
+                if (constraint != null) {
+                    for (CursorSource sc : mSources) {
+                        sc.runQuery(constraint);
+                    }
+                    mixResults(filterResults);
+                }
+                synchronized (mResultsLock) {
+                    mFilterResults = filterResults;
+                }
+                SuggestionResults mixed = buildSuggestionResults();
+                res.count = mixed.getLineCount();
+                res.values = mixed;
+            } else {
+                res.count = mVoiceResults.size();
+                res.values = mVoiceResults;
             }
-            synchronized (mResultsLock) {
-                mFilterResults = filterResults;
-            }
-            SuggestionResults mixed = buildSuggestionResults();
-            res.count = mixed.getLineCount();
-            res.values = mixed;
             return res;
         }
 
@@ -348,8 +365,10 @@
 
         @Override
         protected void publishResults(CharSequence constraint, FilterResults fresults) {
-            mMixedResults = (SuggestionResults) fresults.values;
-            mListener.onFilterComplete(fresults.count);
+            if (fresults.values instanceof SuggestionResults) {
+                mMixedResults = (SuggestionResults) fresults.values;
+                mListener.onFilterComplete(fresults.count);
+            }
             notifyDataSetChanged();
         }
 
diff --git a/src/com/android/browser/TabBar.java b/src/com/android/browser/TabBar.java
index 6a139f3..ea734a6 100644
--- a/src/com/android/browser/TabBar.java
+++ b/src/com/android/browser/TabBar.java
@@ -88,6 +88,7 @@
     private int mTabOverlap;
     private int mTabSliceWidth;
     private int mTabPadding;
+    private boolean mUseQuickControls;
 
     public TabBar(Activity activity, UiController controller, XLargeUi ui) {
         super(activity);
@@ -139,6 +140,14 @@
         mShaderPaint.setAntiAlias(true);
     }
 
+    void setUseQuickControls(boolean useQuickControls) {
+        mUseQuickControls = useQuickControls;
+    }
+
+    int getTabCount() {
+        return mTabMap.size();
+    }
+
     void updateTabs(List<Tab> tabs) {
         mTabs.clearTabs();
         mTabMap.clear();
@@ -182,6 +191,7 @@
         if (mNewTab == view) {
             mUiController.openTabToHomePage();
         } else if (mTabs.getSelectedTab() == view) {
+            if (mUseQuickControls) return;
             if (mUi.isFakeTitleBarShowing() && !isLoading()) {
                 mUi.hideFakeTitleBar();
             } else {
@@ -202,7 +212,7 @@
         mUserRequestedUrlbar = true;
     }
 
-    private void showTitleBarIndicator(boolean show) {
+    void showTitleBarIndicator(boolean show) {
         Tab tab = mTabControl.getCurrentTab();
         if (tab != null) {
             TabViewData tvd = mTabMap.get(tab);
@@ -229,6 +239,7 @@
 
     @Override
     public void onScroll(int visibleTitleHeight) {
+        if (mUseQuickControls) return;
         // isLoading is using the current tab, which initially might not be set yet
         if (mTabControl.getCurrentTab() != null) {
             if ((mVisibleTitleHeight != 0) && (visibleTitleHeight == 0)
@@ -417,7 +428,7 @@
             int[] pos = new int[2];
             getLocationInWindow(mWindowPos);
             Drawable drawable = mSelected ? mActiveDrawable : mInactiveDrawable;
-            drawable.setBounds(0, 0, mUi.getTitleBarWidth(), getHeight());
+            drawable.setBounds(0, 0, mUi.getContentWidth(), getHeight());
             drawClipped(canvas, drawable, mPath, mWindowPos[0]);
             canvas.restoreToCount(state);
             super.dispatchDraw(canvas);
diff --git a/src/com/android/browser/TitleBarXLarge.java b/src/com/android/browser/TitleBarXLarge.java
index 5890810..f1c6c6b 100644
--- a/src/com/android/browser/TitleBarXLarge.java
+++ b/src/com/android/browser/TitleBarXLarge.java
@@ -36,6 +36,8 @@
 import android.webkit.WebView;
 import android.widget.ImageView;
 
+import java.util.List;
+
 /**
  * tabbed title bar for xlarge screen browser
  */
@@ -62,10 +64,16 @@
     private View mAllButton;
     private View mClearButton;
     private View mVoiceSearch;
+    private View mVoiceSearchIndicator;
     private PageProgressView mProgressView;
     private UrlInputView mUrlInput;
+    private Drawable mFocusDrawable;
+    private Drawable mUnfocusDrawable;
+    private boolean mInVoiceMode;
 
     private boolean mInLoad;
+    private boolean mEditable;
+    private boolean mUseQuickControls;
 
     public TitleBarXLarge(Activity activity, UiController controller,
             XLargeUi ui) {
@@ -75,7 +83,12 @@
         Resources resources = activity.getResources();
         mStopDrawable = resources.getDrawable(R.drawable.ic_stop_normal);
         mReloadDrawable = resources.getDrawable(R.drawable.ic_refresh_normal);
+        mFocusDrawable = resources.getDrawable(
+                R.drawable.textfield_active_holo_dark);
+        mUnfocusDrawable = resources.getDrawable(
+                R.drawable.textfield_default_holo_dark);
         rebuildLayout(activity, true);
+        mInVoiceMode = false;
     }
 
     private void rebuildLayout(Context context, boolean rebuildData) {
@@ -98,7 +111,7 @@
         mVoiceSearch = findViewById(R.id.voicesearch);
         mProgressView = (PageProgressView) findViewById(R.id.progress);
         mUrlContainer = findViewById(R.id.urlbar_focused);
-
+        mVoiceSearchIndicator = findViewById(R.id.voice_icon);
         mBackButton.setOnClickListener(this);
         mForwardButton.setOnClickListener(this);
         mStar.setOnClickListener(this);
@@ -107,6 +120,7 @@
         mSearchButton.setOnClickListener(this);
         mGoButton.setOnClickListener(this);
         mClearButton.setOnClickListener(this);
+        mVoiceSearch.setOnClickListener(this);
         mUrlContainer.setOnClickListener(this);
         mUrlInput.setUrlInputListener(this);
         mUrlInput.setContainer(mUrlContainer);
@@ -117,9 +131,48 @@
         setUrlMode(false);
     }
 
+    public void setEditable(boolean editable) {
+        mEditable = editable;
+        mUrlInput.setFocusable(mEditable);
+        if (!mEditable) {
+            mUrlInput.setOnClickListener(this);
+        } else {
+            mUrlContainer.setOnClickListener(null);
+        }
+    }
+
+    void setUseQuickControls(boolean useQuickControls) {
+        mUseQuickControls = useQuickControls;
+        if (mUseQuickControls) {
+            mBackButton.setVisibility(View.GONE);
+            mForwardButton.setVisibility(View.GONE);
+            mStopButton.setVisibility(View.GONE);
+            mAllButton.setVisibility(View.GONE);
+        } else {
+            mBackButton.setVisibility(View.VISIBLE);
+            mForwardButton.setVisibility(View.VISIBLE);
+            mStopButton.setVisibility(View.VISIBLE);
+            mAllButton.setVisibility(View.VISIBLE);
+        }
+    }
+
+    void setShowProgressOnly(boolean progress) {
+        if (progress) {
+            mContainer.setVisibility(View.GONE);
+        } else {
+            mContainer.setVisibility(View.VISIBLE);
+        }
+    }
+
     @Override
     public void onFocusChange(View view, boolean hasFocus) {
-        setUrlMode(hasFocus);
+        if (!mEditable && hasFocus) {
+            mUi.editUrl(false);
+        } else {
+            setUrlMode(hasFocus);
+        }
+        mUrlContainer.setBackgroundDrawable(hasFocus
+                ? mFocusDrawable : mUnfocusDrawable);
     }
 
     public void setCurrentUrlIsBookmark(boolean isBookmark) {
@@ -133,9 +186,13 @@
      * @param clearInput clear the input field
      */
     void onEditUrl(boolean clearInput) {
-        mUrlInput.requestFocusFromTouch();
+        if (!mUrlInput.hasFocus()) {
+            mUrlInput.requestFocus();
+        }
         if (clearInput) {
             mUrlInput.setText("");
+        } else if (mInVoiceMode) {
+            mUrlInput.showDropDown();
         }
     }
 
@@ -146,6 +203,8 @@
     @Override
     public void onClick(View v) {
         if (mUrlInput == v) {
+            mUi.editUrl(false);
+        } else if (mUrlContainer == v) {
             if (!mUrlInput.hasFocus()) {
                 mUi.editUrl(false);
             }
@@ -169,6 +228,8 @@
             }
         } else if (mClearButton == v) {
             clearOrClose();
+        } else if (mVoiceSearch == v) {
+            mUiController.startVoiceSearch();
         }
     }
 
@@ -224,7 +285,7 @@
         mUi.hideFakeTitleBar();
         setUrlMode(false);
         // if top != null current must be set
-        if (top != null) {
+        if ((top != null) && !mInVoiceMode) {
             setDisplayTitle(mUiController.getCurrentWebView().getUrl());
         }
     }
@@ -248,14 +309,22 @@
             mSearchButton.setVisibility(View.GONE);
             mStar.setVisibility(View.GONE);
             mClearButton.setVisibility(View.VISIBLE);
+            if (mInVoiceMode) {
+                mVoiceSearchIndicator.setVisibility(View.VISIBLE);
+            }
             updateSearchMode();
         } else {
             mUrlInput.clearFocus();
-            mSearchButton.setVisibility(View.VISIBLE);
             mGoButton.setVisibility(View.GONE);
             mVoiceSearch.setVisibility(View.GONE);
             mStar.setVisibility(View.VISIBLE);
             mClearButton.setVisibility(View.GONE);
+            mVoiceSearchIndicator.setVisibility(View.GONE);
+            if (mUseQuickControls) {
+                mSearchButton.setVisibility(View.GONE);
+            } else {
+                mSearchButton.setVisibility(View.VISIBLE);
+            }
         }
     }
 
@@ -315,6 +384,8 @@
         if (mUrlInput.hasFocus()) {
             // check if input field is empty and adjust voice search state
             updateSearchMode();
+            // clear voice mode when user types
+            setInVoiceMode(false, null);
         }
     }
 
@@ -326,4 +397,18 @@
     public void onTextChanged(CharSequence s, int start, int before, int count) {
     }
 
+    // voicesearch
+
+    @Override
+    public void setInVoiceMode(boolean voicemode) {
+        setInVoiceMode(voicemode, null);
+    }
+
+    public void setInVoiceMode(boolean voicemode, List<String> voiceResults) {
+        mInVoiceMode = voicemode;
+        mUrlInput.setVoiceResults(voiceResults);
+        mVoiceSearchIndicator.setVisibility(mInVoiceMode
+                ? View.VISIBLE : View.GONE);
+    }
+
 }
diff --git a/src/com/android/browser/UiController.java b/src/com/android/browser/UiController.java
index c74d74e..68a32d3 100644
--- a/src/com/android/browser/UiController.java
+++ b/src/com/android/browser/UiController.java
@@ -53,6 +53,8 @@
 
     void bookmarksOrHistoryPicker(boolean openHistory);
 
+    void startVoiceSearch();
+
     void showVoiceSearchResults(String title);
 
     void editUrl();
diff --git a/src/com/android/browser/UrlInputView.java b/src/com/android/browser/UrlInputView.java
index bd47f6a..505662d 100644
--- a/src/com/android/browser/UrlInputView.java
+++ b/src/com/android/browser/UrlInputView.java
@@ -30,6 +30,8 @@
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
+import java.util.List;
+
 /**
  * url/search input view
  * handling suggestions
@@ -48,6 +50,7 @@
     private OnFocusChangeListener mWrappedFocusListener;
     private View mContainer;
     private boolean mLandscape;
+    private boolean mInVoiceMode;
 
     public UrlInputView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
@@ -85,6 +88,11 @@
         mContainer = container;
     }
 
+    void setVoiceResults(List<String> voiceResults) {
+        mAdapter.setVoiceResults(voiceResults);
+        mInVoiceMode = (voiceResults != null);
+    }
+
     @Override
     protected void onConfigurationChanged(Configuration config) {
         super.onConfigurationChanged(config);
@@ -134,6 +142,10 @@
     public void onFocusChange(View v, boolean hasFocus) {
         if (hasFocus) {
             forceIme();
+            if (mInVoiceMode) {
+                performFiltering(getText().toString(), 0);
+                showDropDown();
+            }
         } else {
             finishInput(null, null, null);
         }
diff --git a/src/com/android/browser/XLargeUi.java b/src/com/android/browser/XLargeUi.java
index 30180aa..7f9baa7 100644
--- a/src/com/android/browser/XLargeUi.java
+++ b/src/com/android/browser/XLargeUi.java
@@ -21,8 +21,12 @@
 import android.app.ActionBar;
 import android.app.Activity;
 import android.graphics.Bitmap;
+import android.util.Log;
 import android.view.ActionMode;
+import android.view.Gravity;
 import android.webkit.WebView;
+import android.widget.FrameLayout;
+import android.widget.FrameLayout.LayoutParams;
 
 import java.util.List;
 
@@ -33,11 +37,15 @@
 
     private static final String LOGTAG = "XLargeUi";
 
+    private ActionBar mActionBar;
     private TabBar mTabBar;
 
     private TitleBarXLarge mTitleBar;
     private TitleBarXLarge mFakeTitleBar;
 
+    private boolean mUseQuickControls;
+    private PieControl mPieControl;
+
     /**
      * @param browser
      * @param controller
@@ -46,11 +54,54 @@
         super(browser, controller);
         mTitleBar = new TitleBarXLarge(mActivity, mUiController, this);
         mTitleBar.setProgress(100);
+        mTitleBar.setEditable(false);
         mFakeTitleBar = new TitleBarXLarge(mActivity, mUiController, this);
-        ActionBar actionBar = mActivity.getActionBar();
+        mFakeTitleBar.setEditable(true);
         mTabBar = new TabBar(mActivity, mUiController, this);
-        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
-        actionBar.setCustomView(mTabBar);
+        mActionBar = mActivity.getActionBar();
+        mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+        mActionBar.setCustomView(mTabBar);
+        setUseQuickControls(BrowserSettings.getInstance().useQuickControls());
+    }
+
+    private void setUseQuickControls(boolean useQuickControls) {
+        mUseQuickControls = useQuickControls;
+        if (useQuickControls) {
+            checkTabCount();
+            mPieControl = new PieControl(mActivity, mUiController, this);
+            mPieControl.attachToContainer(mContentView);
+            setFakeTitleBarGravity(Gravity.BOTTOM);
+
+            // remove embedded title bar if present
+            WebView web = mTabControl.getCurrentWebView();
+            if ((web != null) && (web.getVisibleTitleHeight() > 0)) {
+                web.setEmbeddedTitleBar(null);
+            }
+        } else {
+            mActivity.getActionBar().show();
+            if (mPieControl != null) {
+                mPieControl.removeFromContainer(mContentView);
+            }
+            setFakeTitleBarGravity(Gravity.TOP);
+            // remove embedded title bar if present
+            WebView web = mTabControl.getCurrentWebView();
+            if ((web != null) && (web.getVisibleTitleHeight() == 0)) {
+                web.setEmbeddedTitleBar(mTitleBar);
+            }
+        }
+        mTabBar.setUseQuickControls(mUseQuickControls);
+        mFakeTitleBar.setUseQuickControls(mUseQuickControls);
+    }
+
+    private void checkTabCount() {
+        if (mUseQuickControls) {
+            int n = mTabBar.getTabCount();
+            if (n >= 2) {
+                mActivity.getActionBar().show();
+            } else if (n == 1) {
+                mActivity.getActionBar().hide();
+            }
+        }
     }
 
     @Override
@@ -112,6 +163,9 @@
     public void onPageFinished(Tab tab, String url) {
         mTabBar.onPageFinished(tab);
         super.onPageFinished(tab, url);
+        if (mUseQuickControls) {
+            mFakeTitleBar.setShowProgressOnly(false);
+        }
     }
 
     @Override
@@ -121,7 +175,17 @@
             mFakeTitleBar.setProgress(progress);
             if (progress == 100) {
                 hideFakeTitleBar();
+                if (mUseQuickControls) {
+                    mFakeTitleBar.setShowProgressOnly(false);
+                    setFakeTitleBarGravity(Gravity.BOTTOM);
+                }
             } else {
+                if (mUseQuickControls) {
+                    mFakeTitleBar.setShowProgressOnly(true);
+                    if (!isFakeTitleBarShowing()) {
+                        setFakeTitleBarGravity(Gravity.TOP);
+                    }
+                }
                 showFakeTitleBar();
             }
         }
@@ -135,28 +199,55 @@
     @Override
     public void addTab(Tab tab) {
         mTabBar.onNewTab(tab);
+        checkTabCount();
     }
 
     @Override
     public void setActiveTab(Tab tab) {
         super.setActiveTab(tab);
+        ScrollWebView view = (ScrollWebView) tab.getWebView();
+        // TabControl.setCurrentTab has been called before this,
+        // so the tab is guaranteed to have a webview
+        if (view == null) {
+            Log.e(LOGTAG, "active tab with no webview detected");
+            return;
+        }
+        // Request focus on the top window.
+        if (mUseQuickControls) {
+            mPieControl.forceToTop(mContentView);
+            view.setScrollListener(null);
+            mTabBar.showTitleBarIndicator(false);
+        } else {
+            view.setEmbeddedTitleBar(mTitleBar);
+            view.setScrollListener(this);
+        }
         mTabBar.onSetActiveTab(tab);
+        if (tab.isInVoiceSearchMode()) {
+            showVoiceTitleBar(tab.getVoiceDisplayTitle());
+        } else {
+            revertVoiceTitleBar(tab);
+        }
+        resetTitleIconAndProgress(tab);
+        updateLockIconToLatest(tab);
+        tab.getTopWindow().requestFocus();
     }
 
     @Override
     public void updateTabs(List<Tab> tabs) {
         mTabBar.updateTabs(tabs);
+        checkTabCount();
     }
 
     @Override
     public void removeTab(Tab tab) {
         super.removeTab(tab);
         mTabBar.onRemoveTab(tab);
+        checkTabCount();
     }
 
-    int getTitleBarWidth() {
-        if (mTitleBar != null) {
-            return mTitleBar.getWidth();
+    int getContentWidth() {
+        if (mContentView != null) {
+            return mContentView.getWidth();
         }
         return 0;
     }
@@ -166,6 +257,22 @@
         mFakeTitleBar.onEditUrl(clearInput);
     }
 
+    void setFakeTitleBarGravity(int gravity) {
+        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams)
+                mFakeTitleBar.getLayoutParams();
+        if (lp == null) {
+            lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+                    LayoutParams.WRAP_CONTENT);
+        }
+        lp.gravity = gravity;
+        mFakeTitleBar.setLayoutParams(lp);
+    }
+
+    void showFakeTitleBarAndEdit() {
+        showFakeTitleBar();
+        mFakeTitleBar.onEditUrl(false);
+    }
+
     @Override
     protected void attachFakeTitleBar(WebView mainView) {
         mContentView.addView(mFakeTitleBar);
@@ -206,6 +313,20 @@
     }
 
     @Override
+    public void onActionModeFinished(boolean inLoad) {
+        checkTabCount();
+        if (inLoad) {
+            // the titlebar was removed when the CAB was shown
+            // if the page is loading, show it again
+            mFakeTitleBar.setShowProgressOnly(true);
+            if (!isFakeTitleBarShowing()) {
+                setFakeTitleBarGravity(Gravity.TOP);
+            }
+            showFakeTitleBar();
+        }
+    }
+
+    @Override
     public void setUrlTitle(Tab tab, String url, String title) {
         super.setUrlTitle(tab, url, title);
         mTabBar.onUrlAndTitle(tab, url, title);
@@ -218,4 +339,26 @@
         mTabBar.onFavicon(tab, icon);
     }
 
+    @Override
+    public void showVoiceTitleBar(String title) {
+        List<String> vsresults = null;
+        if (getActiveTab() != null) {
+            vsresults = getActiveTab().getVoiceSearchResults();
+        }
+        mTitleBar.setInVoiceMode(true, null);
+        mTitleBar.setDisplayTitle(title);
+        mFakeTitleBar.setInVoiceMode(true, vsresults);
+        mFakeTitleBar.setDisplayTitle(title);
+    }
+
+    @Override
+    public void revertVoiceTitleBar(Tab tab) {
+        mTitleBar.setInVoiceMode(false, null);
+        String url = tab.getCurrentUrl();
+        mTitleBar.setDisplayTitle(url);
+        mFakeTitleBar.setInVoiceMode(false, null);
+        mFakeTitleBar.setDisplayTitle(url);
+    }
+
+
 }
diff --git a/src/com/android/browser/preferences/LabPreferencesFragment.java b/src/com/android/browser/preferences/LabPreferencesFragment.java
new file mode 100644
index 0000000..8a8546f
--- /dev/null
+++ b/src/com/android/browser/preferences/LabPreferencesFragment.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.browser.preferences;
+
+import com.android.browser.BrowserActivity;
+import com.android.browser.BrowserSettings;
+import com.android.browser.Controller;
+import com.android.browser.R;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceActivity.Header;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager.OnActivityResultListener;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+public class LabPreferencesFragment extends PreferenceFragment
+        implements OnPreferenceChangeListener {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Load the XML preferences file
+        addPreferencesFromResource(R.xml.lab_preferences);
+
+        Preference e = findPreference(BrowserSettings.PREF_QUICK_CONTROLS);
+        e.setOnPreferenceChangeListener(this);
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        // Attempt to restart
+        startActivity(new Intent(BrowserActivity.ACTION_RESTART, null,
+                getActivity(), BrowserActivity.class));
+        return true;
+    }
+
+}
diff --git a/src/com/android/browser/view/PieMenu.java b/src/com/android/browser/view/PieMenu.java
new file mode 100644
index 0000000..d838a34
--- /dev/null
+++ b/src/com/android/browser/view/PieMenu.java
@@ -0,0 +1,463 @@
+/*
+ * 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.browser.view;
+
+import com.android.browser.R;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class PieMenu extends FrameLayout {
+
+    private static final int RADIUS_GAP = 10;
+
+    public interface PieController {
+        /**
+         * called before menu opens to customize menu
+         * returns if pie state has been changed
+         */
+        public boolean onOpen();
+    }
+    private Point mCenter;
+    private int mRadius;
+    private int mRadiusInc;
+    private int mSlop;
+
+    private boolean mOpen;
+    private Paint mPaint;
+    private Paint mSelectedPaint;
+    private PieController mController;
+
+    private Map<View, List<View>> mMenu;
+    private List<View> mStack;
+
+    private boolean mDirty;
+
+    /**
+     * @param context
+     * @param attrs
+     * @param defStyle
+     */
+    public PieMenu(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(context);
+    }
+
+    /**
+     * @param context
+     * @param attrs
+     */
+    public PieMenu(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context);
+    }
+
+    /**
+     * @param context
+     */
+    public PieMenu(Context context) {
+        super(context);
+        init(context);
+    }
+
+    private void init(Context ctx) {
+        this.setTag(new MenuTag(0));
+        mStack = new ArrayList<View>();
+        mStack.add(this);
+        Resources res = ctx.getResources();
+        mRadius = (int) res.getDimension(R.dimen.qc_radius);
+        mRadiusInc = (int) res.getDimension(R.dimen.qc_radius_inc);
+        mSlop = (int) res.getDimension(R.dimen.qc_slop);
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+        mPaint.setColor(res.getColor(R.color.qc_slice_normal));
+        mSelectedPaint = new Paint();
+        mSelectedPaint.setAntiAlias(true);
+        mSelectedPaint.setColor(res.getColor(R.color.qc_slice_active));
+        mOpen = false;
+        mMenu = new HashMap<View, List<View>>();
+        setWillNotDraw(false);
+        setDrawingCacheEnabled(false);
+        mCenter = new Point(0,0);
+        mDirty = true;
+    }
+
+    public void setController(PieController ctl) {
+        mController = ctl;
+    }
+
+    public void setRadius(int r) {
+        mRadius = r;
+        requestLayout();
+    }
+
+    public void setRadiusIncrement(int ri) {
+        mRadiusInc = ri;
+        requestLayout();
+    }
+
+    /**
+     * add a menu item to another item as a submenu
+     * @param item
+     * @param parent
+     */
+    public void addItem(View item, View parent) {
+        List<View> subs = mMenu.get(parent);
+        if (subs == null) {
+            subs = new ArrayList<View>();
+            mMenu.put(parent, subs);
+        }
+        subs.add(item);
+        MenuTag tag = new MenuTag(((MenuTag) parent.getTag()).level + 1);
+        item.setTag(tag);
+    }
+
+    public void addItem(View view) {
+        // add the item to the pie itself
+        addItem(view, this);
+    }
+
+    public void removeItem(View view) {
+        List<View> subs = mMenu.get(view);
+        mMenu.remove(view);
+        for (View p : mMenu.keySet()) {
+            List<View> sl = mMenu.get(p);
+            if (sl != null) {
+                sl.remove(view);
+            }
+        }
+    }
+
+    public void clearItems(View parent) {
+        List<View> subs = mMenu.remove(parent);
+        if (subs != null) {
+            for (View sub: subs) {
+                clearItems(sub);
+            }
+        }
+    }
+
+    public void clearItems() {
+        mMenu.clear();
+    }
+
+
+    public void show(boolean show) {
+        mOpen = show;
+        if (mOpen) {
+            if (mController != null) {
+                boolean changed = mController.onOpen();
+            }
+            mDirty = true;
+        }
+        if (!show) {
+            // hide sub items
+            mStack.clear();
+            mStack.add(this);
+        }
+        invalidate();
+    }
+
+    private void setCenter(int x, int y) {
+        if (x < mSlop) {
+            mCenter.x = 0;
+        } else {
+            mCenter.x = getWidth();
+        }
+        mCenter.y = y;
+    }
+
+    private boolean onTheLeft() {
+        return mCenter.x < mSlop;
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mOpen) {
+            int radius = mRadius;
+            // start in the center for 0 level menu
+            float anchor = (float) Math.PI / 2;
+            PointF angles = new PointF();
+            int state = canvas.save();
+            if (onTheLeft()) {
+                // left handed
+                canvas.scale(-1, 1);
+            }
+            for (View parent : mStack) {
+                List<View> subs = mMenu.get(parent);
+                if (subs != null) {
+                    setGeometry(anchor, subs.size(), angles);
+                }
+                anchor = drawSlices(canvas, subs, radius, angles.x, angles.y);
+                radius += mRadiusInc + RADIUS_GAP;
+            }
+            canvas.restoreToCount(state);
+            mDirty = false;
+        }
+    }
+
+    /**
+     * draw the set of slices
+     * @param canvas
+     * @param items
+     * @param radius
+     * @param start
+     * @param sweep
+     * @return the angle of the selected slice
+     */
+    private float drawSlices(Canvas canvas, List<View> items, int radius,
+            float start, float sweep) {
+        float angle = start + sweep / 2;
+        // gap between slices in degrees
+        float gap = 1f;
+        float newanchor = 0f;
+        for (View item : items) {
+            if (mDirty) {
+                item.measure(item.getLayoutParams().width,
+                        item.getLayoutParams().height);
+                int w = item.getMeasuredWidth();
+                int h = item.getMeasuredHeight();
+                int x = (int) (radius * Math.sin(angle));
+                int y =  mCenter.y - (int) (radius * Math.cos(angle)) - h / 2;
+                if (onTheLeft()) {
+                    x = mCenter.x + x - w / 2;
+                } else {
+                    x = mCenter.x - x - w / 2;
+                }
+                item.layout(x, y, x + w, y + h);
+            }
+            float itemstart = angle - sweep / 2;
+            int inner = radius - mRadiusInc / 2;
+            int outer = radius + mRadiusInc / 2;
+            Path slice = makeSlice(getDegrees(itemstart) - gap,
+                    getDegrees(itemstart + sweep) + gap,
+                    outer, inner, mCenter);
+            MenuTag tag = (MenuTag) item.getTag();
+            tag.start = itemstart;
+            tag.sweep = sweep;
+            tag.inner = inner;
+            tag.outer = outer;
+
+            Paint p = item.isPressed() ? mSelectedPaint : mPaint;
+            canvas.drawPath(slice, p);
+            int state = canvas.save();
+            if (onTheLeft()) {
+                canvas.scale(-1, 1);
+            }
+            canvas.translate(item.getX(), item.getY());
+            item.draw(canvas);
+            canvas.restoreToCount(state);
+            if (mStack.contains(item)) {
+                // item is anchor for sub menu
+                newanchor = angle;
+            }
+            angle += sweep;
+        }
+        return newanchor;
+    }
+
+    /**
+     * converts a
+     * @param angle from 0..PI to Android degrees (clockwise starting at 3 o'clock)
+     * @return skia angle
+     */
+    private float getDegrees(double angle) {
+        return (float) (270 - 180 * angle / Math.PI);
+    }
+
+    private Path makeSlice(float startangle, float endangle, int outerradius,
+            int innerradius, Point center) {
+        RectF bb = new RectF(center.x - outerradius, center.y - outerradius,
+                center.x + outerradius, center.y + outerradius);
+        RectF bbi = new RectF(center.x - innerradius, center.y - innerradius,
+                center.x + innerradius, center.y + innerradius);
+        Path path = new Path();
+        path.arcTo(bb, startangle, endangle - startangle, true);
+        path.arcTo(bbi, endangle, startangle - endangle);
+        path.close();
+        return path;
+    }
+
+    /**
+     * all angles are 0 .. MATH.PI where 0 points up, and rotate counterclockwise
+     * set the startangle and slice sweep in result
+     * @param anchorangle : angle at which the menu is anchored
+     * @param nslices
+     * @param result : x : start, y : sweep
+     */
+    private void setGeometry(float anchorangle, int nslices, PointF result) {
+        float span = (float) Math.min(anchorangle, Math.PI - anchorangle);
+        float sweep = 2 * span / (nslices + 1);
+        result.x = anchorangle - span + sweep / 2;
+        result.y = sweep;
+    }
+
+    // touch handling for pie
+
+    View mCurrentView;
+    Rect mHitRect = new Rect();
+
+    @Override
+    public boolean onTouchEvent(MotionEvent evt) {
+        float x = evt.getX();
+        float y = evt.getY();
+        int action = evt.getActionMasked();
+        int edges = evt.getEdgeFlags();
+        if (MotionEvent.ACTION_DOWN == action) {
+            if ((x > getWidth() - mSlop) || (x < mSlop)) {
+                setCenter((int) x, (int) y);
+                show(true);
+                return true;
+            }
+        } else if (MotionEvent.ACTION_UP == action) {
+            if (mOpen) {
+                View v = mCurrentView;
+                deselect();
+                if (v != null) {
+                    v.performClick();
+                }
+                show(false);
+                return true;
+            }
+        } else if (MotionEvent.ACTION_CANCEL == action) {
+            if (mOpen) {
+                show(false);
+            }
+            deselect();
+            return false;
+        } else if (MotionEvent.ACTION_MOVE == action) {
+            View v = findView((int) x, (int) y);
+            if (mCurrentView != v) {
+                onEnter(v);
+                invalidate();
+            }
+        }
+        // always re-dispatch event
+        return false;
+    }
+
+    /**
+     * enter a slice for a view
+     * updates model only
+     * @param view
+     */
+    private void onEnter(View view) {
+        // deselect
+        if (mCurrentView != null) {
+            if (getLevel(mCurrentView) >= getLevel(view)) {
+                mCurrentView.setPressed(false);
+            }
+        }
+        if (view != null) {
+            // clear up stack
+            MenuTag tag = (MenuTag) view.getTag();
+            int i = mStack.size() - 1;
+            while (i > 0) {
+                View v = mStack.get(i);
+                if (((MenuTag) v.getTag()).level >= tag.level) {
+                    v.setPressed(false);
+                    mStack.remove(i);
+                } else {
+                    break;
+                }
+                i--;
+            }
+            List<View> items = mMenu.get(view);
+            if (items != null) {
+                mStack.add(view);
+                mDirty = true;
+            }
+            view.setPressed(true);
+        }
+        mCurrentView = view;
+    }
+
+    private void deselect() {
+        if (mCurrentView != null) {
+            mCurrentView.setPressed(false);
+        }
+        mCurrentView = null;
+    }
+
+    private int getLevel(View v) {
+        if (v == null) return -1;
+        return ((MenuTag) v.getTag()).level;
+    }
+
+    private View findView(int x, int y) {
+        // get angle and radius from x/y
+        float angle = (float) Math.PI / 2;
+        x = mCenter.x - x;
+        if (mCenter.x < mSlop) {
+            x = -x;
+        }
+        y = mCenter.y - y;
+        float dist = (float) Math.sqrt(x * x + y * y);
+        if (y > 0) {
+            angle = (float) Math.asin(x / dist);
+        } else if (y < 0) {
+            angle = (float) (Math.PI - Math.asin(x / dist ));
+        }
+        // find the matching item:
+        for (View parent : mStack) {
+            List<View> subs = mMenu.get(parent);
+            if (subs != null) {
+                for (View item : subs) {
+                    MenuTag tag = (MenuTag) item.getTag();
+                    if ((tag.inner < dist)
+                            && (tag.outer > dist)
+                            && (tag.start < angle)
+                            && (tag.start + tag.sweep > angle)) {
+                        return item;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    class MenuTag {
+
+        int level;
+        float start;
+        float sweep;
+        int inner;
+        int outer;
+
+        public MenuTag(int l) {
+            level = l;
+        }
+
+    }
+
+}
diff --git a/src/com/android/browser/widget/BookmarkListWidgetProvider.java b/src/com/android/browser/widget/BookmarkListWidgetProvider.java
index 2196ae0..99daaa1 100644
--- a/src/com/android/browser/widget/BookmarkListWidgetProvider.java
+++ b/src/com/android/browser/widget/BookmarkListWidgetProvider.java
@@ -79,6 +79,10 @@
 
     private void performUpdate(Context context,
             AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+        Intent launchBrowser = new Intent(BrowserActivity.ACTION_SHOW_BROWSER,
+                null, context, BrowserActivity.class);
+        Intent launchBookmarks = new Intent(BrowserActivity.ACTION_SHOW_BOOKMARKS,
+                null, context, BrowserActivity.class);
         // Update the widgets
         for (int appWidgetId : appWidgetIds) {
             Intent updateIntent = new Intent(context, BookmarkListWidgetService.class);
@@ -92,9 +96,10 @@
             views.setPendingIntentTemplate(R.id.bookmarks_list,
                     PendingIntent.getService(context, 0, ic,
                     PendingIntent.FLAG_UPDATE_CURRENT));
-            Intent launch = new Intent(context, BrowserActivity.class);
-            views.setOnClickPendingIntent(R.id.header, PendingIntent
-                    .getActivity(context, 0, launch, PendingIntent.FLAG_CANCEL_CURRENT));
+            views.setOnClickPendingIntent(R.id.header_browser, PendingIntent
+                    .getActivity(context, 0, launchBrowser, PendingIntent.FLAG_CANCEL_CURRENT));
+            views.setOnClickPendingIntent(R.id.header_bookmarks, PendingIntent
+                    .getActivity(context, 0, launchBookmarks, PendingIntent.FLAG_CANCEL_CURRENT));
             appWidgetManager.updateAppWidget(appWidgetId, views);
         }
     }
diff --git a/src/com/android/browser/widget/BookmarkListWidgetService.java b/src/com/android/browser/widget/BookmarkListWidgetService.java
index 8fbe807..8cf63a3 100644
--- a/src/com/android/browser/widget/BookmarkListWidgetService.java
+++ b/src/com/android/browser/widget/BookmarkListWidgetService.java
@@ -240,10 +240,10 @@
             views.setDrawableParameters(R.id.list_item, true, 0, -1, null, -1);
             if (res.mIsFolder) {
                 if (folder != null && res.mId == folder.mId) {
+                    views.setImageViewResource(R.id.thumb, R.drawable.btn_ic_back_bookmark_widget_holo_dark);
                     views.setDrawableParameters(R.id.list_item, true, 255, -1, null, -1);
-                    views.setImageViewResource(R.id.thumb, R.drawable.ic_back_normal);
                 } else {
-                    views.setImageViewResource(R.id.thumb, R.drawable.ic_folder);
+                    views.setImageViewResource(R.id.thumb, R.drawable.ic_folder_bookmark_widget_holo_dark);
                 }
             } else {
                 if (res.mBitmap != null) {